uartpci.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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 *perlehead, *perletail;
  12. static Uart*
  13. uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name,
  14. int iosize)
  15. {
  16. int i, io;
  17. void *ctlr;
  18. char buf[64];
  19. Uart *head, *uart;
  20. io = p->mem[barno].bar & ~0x01;
  21. snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno);
  22. if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){
  23. print("uartpci: I/O 0x%uX in use\n", io);
  24. return nil;
  25. }
  26. head = uart = malloc(sizeof(Uart)*n);
  27. for(i = 0; i < n; i++){
  28. ctlr = i8250alloc(io, p->intl, p->tbdf);
  29. io += iosize;
  30. if(ctlr == nil)
  31. continue;
  32. uart->regs = ctlr;
  33. snprint(buf, sizeof(buf), "%s.%8.8uX", name, p->tbdf);
  34. kstrdup(&uart->name, buf);
  35. uart->freq = freq;
  36. uart->phys = &i8250physuart;
  37. if(uart != head)
  38. (uart-1)->next = uart;
  39. uart++;
  40. }
  41. if (head) {
  42. if(perlehead != nil)
  43. perletail->next = head;
  44. else
  45. perlehead = head;
  46. for(perletail = head; perletail->next != nil;
  47. perletail = perletail->next)
  48. ;
  49. }
  50. return head;
  51. }
  52. static Uart *
  53. ultraport16si(int ctlrno, Pcidev *p, ulong freq)
  54. {
  55. int io, i;
  56. char *name;
  57. Uart *uart;
  58. name = "Ultraport16si"; /* 16L788 UARTs */
  59. io = p->mem[4].bar & ~1;
  60. if (ioalloc(io, p->mem[4].size, 0, name) < 0) {
  61. print("uartpci: can't get IO space to set %s to rs-232\n", name);
  62. return nil;
  63. }
  64. for (i = 0; i < 16; i++) {
  65. outb(io, i << 4);
  66. outb(io, (i << 4) + 1); /* set to RS232 mode (Don't ask!) */
  67. }
  68. uart = uartpci(ctlrno, p, 2, 8, freq, name, 16);
  69. if(uart)
  70. uart = uartpci(ctlrno, p, 3, 8, freq, name, 16);
  71. return uart;
  72. }
  73. static Uart*
  74. uartpcipnp(void)
  75. {
  76. Pcidev *p;
  77. char *name;
  78. int ctlrno, subid;
  79. ulong freq;
  80. Uart *uart;
  81. /*
  82. * Loop through all PCI devices looking for simple serial
  83. * controllers (ccrb == 0x07) and configure the ones which
  84. * are familiar. All suitable devices are configured to
  85. * simply point to the generic i8250 driver.
  86. */
  87. perlehead = perletail = nil;
  88. ctlrno = 0;
  89. for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
  90. if(p->ccrb != 0x07 || p->ccru > 2)
  91. continue;
  92. switch(p->did<<16 | p->vid){
  93. default:
  94. continue;
  95. case (0x9835<<16)|0x9710: /* StarTech PCI2S550 */
  96. uart = uartpci(ctlrno, p, 0, 1, 1843200, "PCI2S550-0", 8);
  97. if(uart == nil)
  98. continue;
  99. uart->next = uartpci(ctlrno, p, 1, 1, 1843200,
  100. "PCI2S550-1", 8);
  101. if(uart->next == nil)
  102. continue;
  103. break;
  104. case (0x950A<<16)|0x1415: /* Oxford Semi OX16PCI954 */
  105. case (0x9501<<16)|0x1415:
  106. /*
  107. * These are common devices used by 3rd-party
  108. * manufacturers.
  109. * Must check the subsystem VID and DID for correct
  110. * match.
  111. */
  112. subid = pcicfgr16(p, PciSVID);
  113. subid |= pcicfgr16(p, PciSID)<<16;
  114. switch(subid){
  115. default:
  116. print("oxsemi uart %.8#ux of vid %#ux did %#ux unknown\n",
  117. subid, p->vid, p->did);
  118. continue;
  119. case (0<<16)|0x1415:
  120. uart = uartpci(ctlrno, p, 0, 4, 1843200,
  121. "starport-pex4s", 8);
  122. break;
  123. case (0x2000<<16)|0x131F:/* SIIG CyberSerial PCIe */
  124. uart = uartpci(ctlrno, p, 0, 1, 18432000,
  125. "CyberSerial-1S", 8);
  126. break;
  127. }
  128. break;
  129. case (0x9050<<16)|0x10B5: /* Perle PCI-Fast4 series */
  130. case (0x9030<<16)|0x10B5: /* Perle Ultraport series */
  131. /*
  132. * These devices consists of a PLX bridge (the above
  133. * PCI VID+DID) behind which are some 16C654 UARTs.
  134. * Must check the subsystem VID and DID for correct
  135. * match.
  136. */
  137. subid = pcicfgr16(p, PciSVID);
  138. subid |= pcicfgr16(p, PciSID)<<16;
  139. freq = 7372800;
  140. switch(subid){
  141. default:
  142. continue;
  143. case (0x0011<<16)|0x12E0: /* Perle PCI-Fast16 */
  144. name = "PCI-Fast16";
  145. uart = uartpci(ctlrno, p, 2, 16, freq, name, 8);
  146. break;
  147. case (0x0021<<16)|0x12E0: /* Perle PCI-Fast8 */
  148. name = "PCI-Fast8";
  149. uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
  150. break;
  151. case (0x0031<<16)|0x12E0: /* Perle PCI-Fast4 */
  152. name = "PCI-Fast4";
  153. uart = uartpci(ctlrno, p, 2, 4, freq, name, 8);
  154. break;
  155. case (0x0021<<16)|0x155F: /* Perle Ultraport8 */
  156. name = "Ultraport8"; /* 16C754 UARTs */
  157. uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
  158. break;
  159. case (0x0041<<16)|0x155F: /* Perle Ultraport16 */
  160. name = "Ultraport16";
  161. uart = uartpci(ctlrno, p, 2, 16, 2 * freq,
  162. name, 8);
  163. break;
  164. case (0x0241<<16)|0x155F: /* Perle Ultraport16 */
  165. uart = ultraport16si(ctlrno, p, 4 * freq);
  166. break;
  167. }
  168. break;
  169. }
  170. if(uart)
  171. ctlrno++;
  172. }
  173. return perlehead;
  174. }
  175. PhysUart pciphysuart = {
  176. .name = "UartPCI",
  177. .pnp = uartpcipnp,
  178. .enable = nil,
  179. .disable = nil,
  180. .kick = nil,
  181. .dobreak = nil,
  182. .baud = nil,
  183. .bits = nil,
  184. .stop = nil,
  185. .parity = nil,
  186. .modemctl = nil,
  187. .rts = nil,
  188. .dtr = nil,
  189. .status = nil,
  190. .fifo = nil,
  191. };