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