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