uartpci.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. extern PhysUart i8250physuart;
  9. extern PhysUart pciphysuart;
  10. extern void* i8250alloc(int, int, int);
  11. static Uart*
  12. uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name)
  13. {
  14. int i, io;
  15. void *ctlr;
  16. char buf[64];
  17. Uart *head, *uart;
  18. io = p->mem[barno].bar & ~0x01;
  19. snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno);
  20. if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){
  21. print("uartpci: I/O 0x%uX in use\n", io);
  22. return nil;
  23. }
  24. head = uart = malloc(sizeof(Uart)*n);
  25. for(i = 0; i < n; i++){
  26. ctlr = i8250alloc(io, p->intl, p->tbdf);
  27. io += 8;
  28. if(ctlr == nil)
  29. continue;
  30. uart->regs = ctlr;
  31. snprint(buf, sizeof(buf), "%s.%8.8uX", name, p->tbdf);
  32. kstrdup(&uart->name, buf);
  33. uart->freq = freq;
  34. uart->phys = &i8250physuart;
  35. if(uart != head)
  36. (uart-1)->next = uart;
  37. uart++;
  38. }
  39. return head;
  40. }
  41. static Uart*
  42. uartpcipnp(void)
  43. {
  44. Pcidev *p;
  45. char *name;
  46. int ctlrno, n, subid;
  47. Uart *head, *tail, *uart;
  48. /*
  49. * Loop through all PCI devices looking for simple serial
  50. * controllers (ccrb == 0x07) and configure the ones which
  51. * are familiar. All suitable devices are configured to
  52. * simply point to the generic i8250 driver.
  53. */
  54. head = tail = nil;
  55. ctlrno = 0;
  56. for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
  57. if(p->ccrb != 0x07 || p->ccru > 2)
  58. continue;
  59. switch((p->did<<16)|p->vid){
  60. default:
  61. continue;
  62. case (0x9835<<16)|0x9710: /* StarTech PCI2S550 */
  63. uart = uartpci(ctlrno, p, 0, 1, 1843200, "PCI2S550-0");
  64. if(uart == nil)
  65. continue;
  66. uart->next = uartpci(ctlrno, p, 1, 1, 1843200, "PCI2S550-1");
  67. break;
  68. case (0x950A<<16)|0x1415: /* Oxford Semi OX16PCI954 */
  69. /*
  70. * These are common devices used by 3rd-party
  71. * manufacturers.
  72. * Must check the subsystem VID and DID for correct
  73. * match.
  74. */
  75. subid = pcicfgr16(p, PciSVID);
  76. subid |= pcicfgr16(p, PciSID)<<16;
  77. switch(subid){
  78. default:
  79. continue;
  80. case (0x2000<<16)|0x131F:/* SIIG CyberSerial PCIe */
  81. uart = uartpci(ctlrno, p, 0, 1, 18432000, "CyberSerial-1S");
  82. if(uart == nil)
  83. continue;
  84. break;
  85. }
  86. break;
  87. case (0x9050<<16)|0x10B5: /* Perle PCI-Fast4 series */
  88. case (0x9030<<16)|0x10B5: /* Perle Ultraport series */
  89. /*
  90. * These devices consists of a PLX bridge (the above
  91. * PCI VID+DID) behind which are some 16C654 UARTs.
  92. * Must check the subsystem VID and DID for correct
  93. * match.
  94. */
  95. subid = pcicfgr16(p, PciSVID);
  96. subid |= pcicfgr16(p, PciSID)<<16;
  97. switch(subid){
  98. default:
  99. continue;
  100. case (0x0011<<16)|0x12E0: /* Perle PCI-Fast16 */
  101. n = 16;
  102. name = "PCI-Fast16";
  103. break;
  104. case (0x0021<<16)|0x12E0: /* Perle PCI-Fast8 */
  105. n = 8;
  106. name = "PCI-Fast8";
  107. break;
  108. case (0x0031<<16)|0x12E0: /* Perle PCI-Fast4 */
  109. n = 4;
  110. name = "PCI-Fast4";
  111. break;
  112. case (0x0021<<16)|0x155F: /* Perle Ultraport8 */
  113. n = 8;
  114. name = "Ultraport8"; /* 16C754 UARTs */
  115. break;
  116. }
  117. uart = uartpci(ctlrno, p, 2, n, 7372800, name);
  118. if(uart == nil)
  119. continue;
  120. break;
  121. }
  122. if(head != nil)
  123. tail->next = uart;
  124. else
  125. head = uart;
  126. for(tail = uart; tail->next != nil; tail = tail->next)
  127. ;
  128. ctlrno++;
  129. }
  130. return head;
  131. }
  132. PhysUart pciphysuart = {
  133. .name = "UartPCI",
  134. .pnp = uartpcipnp,
  135. .enable = nil,
  136. .disable = nil,
  137. .kick = nil,
  138. .dobreak = nil,
  139. .baud = nil,
  140. .bits = nil,
  141. .stop = nil,
  142. .parity = nil,
  143. .modemctl = nil,
  144. .rts = nil,
  145. .dtr = nil,
  146. .status = nil,
  147. .fifo = nil,
  148. };