2 #include "../port/lib.h"
7 #include "../port/error.h"
9 extern PhysUart i8250physuart;
10 extern PhysUart pciphysuart;
11 extern void* i8250alloc(int, int, int);
13 static Uart *perlehead, *perletail;
16 uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name,
24 head = malloc(sizeof(Uart)*n);
26 print("uartpci: no memory for Uarts\n");
30 io = p->mem[barno].bar & ~0x01;
31 snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno);
32 if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){
33 print("uartpci: I/O 0x%uX in use\n", io);
39 for(i = 0; i < n; i++){
40 ctlr = i8250alloc(io + i*iosize, p->intl, p->tbdf);
45 snprint(buf, sizeof(buf), "%s.%8.8uX", name, p->tbdf);
46 kstrdup(&uart->name, buf);
48 uart->phys = &i8250physuart;
50 (uart-1)->next = uart;
60 perletail->next = head;
63 for(perletail = head; perletail->next != nil;
64 perletail = perletail->next)
71 ultraport16si(int ctlrno, Pcidev *p, ulong freq)
77 name = "Ultraport16si"; /* 16L788 UARTs */
78 io = p->mem[4].bar & ~1;
79 if (ioalloc(io, p->mem[4].size, 0, name) < 0) {
80 print("uartpci: can't get IO space to set %s to rs-232\n", name);
83 for (i = 0; i < 16; i++) {
85 outb(io, (i << 4) + 1); /* set to RS232 mode (Don't ask!) */
88 uart = uartpci(ctlrno, p, 2, 8, freq, name, 16);
90 uart = uartpci(ctlrno, p, 3, 8, freq, name, 16);
104 * Loop through all PCI devices looking for simple serial
105 * controllers (ccrb == Pcibccomm (7)) and configure the ones which
106 * are familiar. All suitable devices are configured to
107 * simply point to the generic i8250 driver.
109 perlehead = perletail = nil;
111 for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
112 /* StarTech PCI8S9503V has ccru == 0x80 (other) */
113 if(p->ccrb != Pcibccomm || p->ccru > 2 && p->ccru != 0x80)
116 switch(p->did<<16 | p->vid){
119 case (0x9835<<16)|0x9710: /* StarTech PCI2S550 */
120 uart = uartpci(ctlrno, p, 0, 1, 1843200, "PCI2S550-0", 8);
123 uart->next = uartpci(ctlrno, p, 1, 1, 1843200,
125 if(uart->next == nil)
128 case (0x950A<<16)|0x1415: /* Oxford Semi OX16PCI954 */
129 case (0x9501<<16)|0x1415:
130 case (0x9521<<16)|0x1415:
132 * These are common devices used by 3rd-party
134 * Must check the subsystem VID and DID for correct
137 subid = pcicfgr16(p, PciSVID);
138 subid |= pcicfgr16(p, PciSID)<<16;
141 print("oxsemi uart %.8#ux of vid %#ux did %#ux unknown\n",
142 subid, p->vid, p->did);
145 uart = uartpci(ctlrno, p, 0, 4, 1843200,
146 "starport-pex4s", 8);
149 uart = uartpci(ctlrno, p, 0, 2, 14745600,
150 "starport-pex2s", 8);
152 case (0x2000<<16)|0x131F:/* SIIG CyberSerial PCIe */
153 uart = uartpci(ctlrno, p, 0, 1, 18432000,
154 "CyberSerial-1S", 8);
158 case (0x9505<<16)|0x1415: /* Oxford Semi OXuPCI952 */
159 name = "SATAGear-IOI-102"; /* PciSVID=1415, PciSID=0 */
160 if (uartpci(ctlrno, p, 0, 1, 14745600, name, 8) != nil)
162 if (uartpci(ctlrno, p, 1, 1, 14745600, name, 8) != nil)
164 uart = nil; /* don't ctlrno++ below */
166 case (0x9050<<16)|0x10B5: /* Perle PCI-Fast4 series */
167 case (0x9030<<16)|0x10B5: /* Perle Ultraport series */
169 * These devices consists of a PLX bridge (the above
170 * PCI VID+DID) behind which are some 16C654 UARTs.
171 * Must check the subsystem VID and DID for correct
174 subid = pcicfgr16(p, PciSVID);
175 subid |= pcicfgr16(p, PciSID)<<16;
179 print("uartpci: unknown perle subid %#ux\n", subid);
181 case (0x1588<<16)|0x10B5: /* StarTech PCI8S9503V (P588UG) */
183 /* max. baud rate is 921,600 */
185 uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
187 case (0x0011<<16)|0x12E0: /* Perle PCI-Fast16 */
189 uart = uartpci(ctlrno, p, 2, 16, freq, name, 8);
191 case (0x0021<<16)|0x12E0: /* Perle PCI-Fast8 */
193 uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
195 case (0x0031<<16)|0x12E0: /* Perle PCI-Fast4 */
197 uart = uartpci(ctlrno, p, 2, 4, freq, name, 8);
199 case (0x0021<<16)|0x155F: /* Perle Ultraport8 */
200 name = "Ultraport8"; /* 16C754 UARTs */
201 uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
203 case (0x0041<<16)|0x155F: /* Perle Ultraport16 */
204 name = "Ultraport16";
205 uart = uartpci(ctlrno, p, 2, 16, 2 * freq,
208 case (0x0241<<16)|0x155F: /* Perle Ultraport16 */
209 uart = ultraport16si(ctlrno, p, 4 * freq);
221 PhysUart pciphysuart = {