123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "../port/error.h"
- extern PhysUart i8250physuart;
- extern PhysUart pciphysuart;
- extern void* i8250alloc(int, int, int);
- static Uart *perlehead, *perletail;
- static Uart*
- uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name,
- int iosize)
- {
- int i, io;
- void *ctlr;
- char buf[64];
- Uart *head, *uart;
- io = p->mem[barno].bar & ~0x01;
- snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno);
- if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){
- print("uartpci: I/O 0x%uX in use\n", io);
- return nil;
- }
- head = uart = malloc(sizeof(Uart)*n);
- if(uart == nil)
- error(Enomem);
- for(i = 0; i < n; i++){
- ctlr = i8250alloc(io, p->intl, p->tbdf);
- io += iosize;
- if(ctlr == nil)
- continue;
- uart->regs = ctlr;
- snprint(buf, sizeof(buf), "%s.%8.8uX", name, p->tbdf);
- kstrdup(&uart->name, buf);
- uart->freq = freq;
- uart->phys = &i8250physuart;
- if(uart != head)
- (uart-1)->next = uart;
- uart++;
- }
- if (head) {
- if(perlehead != nil)
- perletail->next = head;
- else
- perlehead = head;
- for(perletail = head; perletail->next != nil;
- perletail = perletail->next)
- ;
- }
- return head;
- }
- static Uart *
- ultraport16si(int ctlrno, Pcidev *p, ulong freq)
- {
- int io, i;
- char *name;
- Uart *uart;
- name = "Ultraport16si"; /* 16L788 UARTs */
- io = p->mem[4].bar & ~1;
- if (ioalloc(io, p->mem[4].size, 0, name) < 0) {
- print("uartpci: can't get IO space to set %s to rs-232\n", name);
- return nil;
- }
- for (i = 0; i < 16; i++) {
- outb(io, i << 4);
- outb(io, (i << 4) + 1); /* set to RS232 mode (Don't ask!) */
- }
- uart = uartpci(ctlrno, p, 2, 8, freq, name, 16);
- if(uart)
- uart = uartpci(ctlrno, p, 3, 8, freq, name, 16);
- return uart;
- }
- static Uart*
- uartpcipnp(void)
- {
- Pcidev *p;
- char *name;
- int ctlrno, subid;
- ulong freq;
- Uart *uart;
- /*
- * Loop through all PCI devices looking for simple serial
- * controllers (ccrb == Pcibccomm (7)) and configure the ones which
- * are familiar. All suitable devices are configured to
- * simply point to the generic i8250 driver.
- */
- perlehead = perletail = nil;
- ctlrno = 0;
- for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
- if(p->ccrb != Pcibccomm || p->ccru > 2)
- continue;
- switch(p->did<<16 | p->vid){
- default:
- continue;
- case (0x9835<<16)|0x9710: /* StarTech PCI2S550 */
- uart = uartpci(ctlrno, p, 0, 1, 1843200, "PCI2S550-0", 8);
- if(uart == nil)
- continue;
- uart->next = uartpci(ctlrno, p, 1, 1, 1843200,
- "PCI2S550-1", 8);
- if(uart->next == nil)
- continue;
- break;
- case (0x950A<<16)|0x1415: /* Oxford Semi OX16PCI954 */
- case (0x9501<<16)|0x1415:
- case (0x9521<<16)|0x1415:
- /*
- * These are common devices used by 3rd-party
- * manufacturers.
- * Must check the subsystem VID and DID for correct
- * match.
- */
- subid = pcicfgr16(p, PciSVID);
- subid |= pcicfgr16(p, PciSID)<<16;
- switch(subid){
- default:
- print("oxsemi uart %.8#ux of vid %#ux did %#ux unknown\n",
- subid, p->vid, p->did);
- continue;
- case (0<<16)|0x1415:
- uart = uartpci(ctlrno, p, 0, 4, 1843200,
- "starport-pex4s", 8);
- break;
- case (1<<16)|0x1415:
- uart = uartpci(ctlrno, p, 0, 2, 14745600,
- "starport-pex2s", 8);
- break;
- case (0x2000<<16)|0x131F:/* SIIG CyberSerial PCIe */
- uart = uartpci(ctlrno, p, 0, 1, 18432000,
- "CyberSerial-1S", 8);
- break;
- }
- break;
- case (0x9505<<16)|0x1415: /* Oxford Semi OXuPCI952 */
- name = "SATAGear-IOI-102"; /* PciSVID=1415, PciSID=0 */
- if (uartpci(ctlrno, p, 0, 1, 14745600, name, 8) != nil)
- ctlrno++;
- if (uartpci(ctlrno, p, 1, 1, 14745600, name, 8) != nil)
- ctlrno++;
- uart = nil; /* don't ctlrno++ below */
- break;
- case (0x9050<<16)|0x10B5: /* Perle PCI-Fast4 series */
- case (0x9030<<16)|0x10B5: /* Perle Ultraport series */
- /*
- * These devices consists of a PLX bridge (the above
- * PCI VID+DID) behind which are some 16C654 UARTs.
- * Must check the subsystem VID and DID for correct
- * match.
- */
- subid = pcicfgr16(p, PciSVID);
- subid |= pcicfgr16(p, PciSID)<<16;
- freq = 7372800;
- switch(subid){
- default:
- continue;
- case (0x0011<<16)|0x12E0: /* Perle PCI-Fast16 */
- name = "PCI-Fast16";
- uart = uartpci(ctlrno, p, 2, 16, freq, name, 8);
- break;
- case (0x0021<<16)|0x12E0: /* Perle PCI-Fast8 */
- name = "PCI-Fast8";
- uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
- break;
- case (0x0031<<16)|0x12E0: /* Perle PCI-Fast4 */
- name = "PCI-Fast4";
- uart = uartpci(ctlrno, p, 2, 4, freq, name, 8);
- break;
- case (0x0021<<16)|0x155F: /* Perle Ultraport8 */
- name = "Ultraport8"; /* 16C754 UARTs */
- uart = uartpci(ctlrno, p, 2, 8, freq, name, 8);
- break;
- case (0x0041<<16)|0x155F: /* Perle Ultraport16 */
- name = "Ultraport16";
- uart = uartpci(ctlrno, p, 2, 16, 2 * freq,
- name, 8);
- break;
- case (0x0241<<16)|0x155F: /* Perle Ultraport16 */
- uart = ultraport16si(ctlrno, p, 4 * freq);
- break;
- }
- break;
- }
- if(uart)
- ctlrno++;
- }
- return perlehead;
- }
- PhysUart pciphysuart = {
- .name = "UartPCI",
- .pnp = uartpcipnp,
- .enable = nil,
- .disable = nil,
- .kick = nil,
- .dobreak = nil,
- .baud = nil,
- .bits = nil,
- .stop = nil,
- .parity = nil,
- .modemctl = nil,
- .rts = nil,
- .dtr = nil,
- .status = nil,
- .fifo = nil,
- };
|