/* * $Id$ */ /* * Copyright (c) 2002 Johnny Zackrisson. All rights reserved. * * You are free to do whatever you want with this code. */ #include <drivers/pci_pio.h> #include <config.h> #ifdef _PCI_SUPPORT_ /* * Fill in your shit, recompile and prey. */ #define PCI_DEVS /* how many devices */ struct pci_device_id_t pci_devices = { /* Vendor id, device id, name */ 0x0000,0x0000,"Oak Technologies" /* example */ }; #endif /* PCI_DEVS */ /* XXX: these does not belong here */ static void outb(u16 port, u8 data); static void outw(u16 port, u16 data); static void outl(u16 port, u32 data); static u8 inb(u16 port); static u16 inw(u16 port); static u32 inl(u16 port); /* * XXX: static? */ int pci_get_type(); int pci_init(); int pci_find_devices(struct pci_conf_t *pci_conf[]); int pci_t1_read_config(struct pci_conf_t *pci_conf, unsigned int dev); int pci_t1_write_config(struct pci_conf_t *pci_conf, unsigned int dev); int pci_t2_read_config(struct pci_conf_t *pci_conf, unsigned int dev); int pci_t2_write_config(struct pci_conf_t *pci_conf, unsigned int dev); int pci_init() { return(0); } int pci_get_type() { int x,t=0; outb(PCI_BASE, 0); outb(PCI_INDEX_REG, 0); x = inb(PCI_BASE) + inb(PCI_INDEX_REG); if (x == 0) t = PCI_TYPE_2; x = inb(PCI_BASE); outl(PCI_BASE, BUS_ADDRESS); x = inl(PCI_BASE); if (x == BUS_ADDRESS) t = PCI_TYPE_1; outl(PCI_BASE, x); return(t); } int pci_find_devices(struct pci_conf_t *pci_conf[]) { int dev,i,x; x = pci_get_type(); if (x == PCI_TYPE_1) { for (i=0; i<PCI_DEVS; i++) { pci_t1_read_config(pci_conf[dev], i); if (pci_conf[dev]->vendor_id != 0xffff && pci_conf[dev]->device_id != 0xffff) dev++; } return(0); } else if (x == PCI_TYPE_2) { for (i=0; i<PCI_DEVS; i++) { pci_t2_read_config(pci_conf[dev], i); if (pci_conf[dev]->vendor_id != 0xffff && pci_conf[dev]->device_id != 0xffff) dev++; } return(0); } return(-1); } /* PCI type 1 access method */ int pci_t1_read_config(struct pci_conf_t *pci_conf, unsigned int dev) { unsigned int i; dev <<= 11; for (i=0; i<64; i++) { outl(PCI_BASE, (BUS_ADDRESS+(dev+(i*4)))); ((u32 *)pci_conf)[i] = inl(PCI_T1_INDEX_REG); } if ((pci_conf->vendor_id == 0xffff) && (pci_conf->device_id == 0xffff)) return(-1); return(0); } int pci_t1_write_config(struct pci_conf_t *pci_conf, unsigned int dev) { int i; /* bit 0-7 index into the conf space */ dev <<= 11; for (i=0; i<64; i++) { outl(PCI_BASE, (BUS_ADDRESS+(dev+(i*4)))); outl(PCI_T1_INDEX_REG, ((u32 *)pci_conf)[i]); } return(0); } /* PCI type 2 access method */ int pci_t2_read_config(struct pci_conf_t *pci_conf, unsigned int dev) { int i,x; /* bit 7 set to select the PCI configuration space */ x = (((dev & 7) << 1) | 0xf0); outb(PCI_BASE, x); /* bus select? */ outb(PCI_INDEX_REG, 0); for (i=0; i<64; i++) ((u32 *)pci_conf)[i] = inl(V_BUS_ADDRESS+((dev<<8)+(i*4))); outb(PCI_BASE,0); return(0); } int pci_t2_write_config(struct pci_conf_t *pci_conf, unsigned int dev) { int i,x; /* bit 7 set to select the PCI configuration space */ x = (((dev & 7) << 1) | 0xf0); outb(PCI_BASE, x); /* bus select? */ outb(PCI_INDEX_REG, 0); for (i=0; i<64; i++) outl(V_BUS_ADDRESS+((dev<<8)+(i*4)), ((u32 *)pci_conf)[i]); outb(PCI_BASE, 0); return(0); } /* XXX: these functions below should be in a nice library. */ /* write data to port */ static void outb(u16 port, u8 data) { __asm__ __volatile__( "outb %1,%0" : : "Nd" (port), "a" (data) ); } static void outw(u16 port, u16 data) { __asm__ __volatile__( "outw %1,%0" : : "Nd" (port), "a" (data) ); } static void outl(u16 port, u32 data) { __asm__ __volatile__( "outl %1,%0" : : "Nd" (port), "a" (data) ); } /* get data from port */ static u8 inb(u16 port) { u8 ret; __asm__ __volatile__( "inb %1,%0" : "=a" (ret) : "Nd" (port) ); return(port); } static u16 inw(u16 port) { u16 ret; __asm__ __volatile__( "inw %1,%0" : "=a" (ret) : "Nd" (port) ); return(ret); } static u32 inl(u16 port) { u32 ret; __asm__ __volatile__( "inl %1,%0" : "=a" (ret) : "Nd" (port) ); return(ret); }