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