/** * pci.c * @author: Dirk Vogt * @date: 2010-02-18 */ #include "common.h" #include #include #include #ifdef DDEBUG_LEVEL_PCI #undef DDEBUG #define DDEBUG DDEBUG_LEVEL_PCI #endif #include "util.h" #include "debug.h" #define PCI_MAX_DEVS 32 #define PCI_TAKE_ALL (-1) struct ddekit_pci_dev { int devind; /* thats how we identify the defice at the pci server */ ddekit_uint16_t vid; /* as we get them for */ /* free during iteration store them */ ddekit_uint16_t did; int bus; int slot; /* slot should equal index in dev array */ int func; /* don't support multiple functionalities yet -> 0 */ }; struct ddekit_pci_dev pci_devs[PCI_MAX_DEVS]; FORWARD struct ddekit_pci_dev * ddekit_get_dev_helper(int bus, int slot, int func); /****************************************************************************/ /* ddekit_pci_init_only_one */ /****************************************************************************/ PUBLIC void ddekit_pci_init_only_one(int skip) { /* * If skip is not PCI_TAKE_ALL this function will skip skip PCI DEVICES * and than only take on PCI device. */ int res, count, more, take_all = 0; if (skip == -1) { take_all = 1; } DDEBUG_MSG_INFO("Initializing PCI subsystem..."); pci_init(); /* * Iterate the PCI-bus */ more = 1; for (count = 0 ; count < PCI_MAX_DEVS ; count++) { struct ddekit_pci_dev *d = &pci_devs[count]; if (more) { if ( count==0 ) { res = pci_first_dev(&d->devind, &d->vid, &d->did); } else { d->devind = pci_devs[count-1].devind; res = pci_next_dev(&d->devind, &d->vid, &d->did); } if (res && d->devind!=0 && (take_all || skip == 0)) { DDEBUG_MSG_VERBOSE("Found pci device: " "(ind: %x, vid: %x, did: %x) " "mapped to slot %x", d->devind, d->vid, d->did, count); d->slot = count; d->bus = 0; d->func = 0; res = pci_reserve_ok(d->devind); if (res != 0) { ddekit_panic("ddekit_pci_init_only_one: " "pci_reserve_ok failed (%d)\n",res); } } else { /* no more PCI devices */ DDEBUG_MSG_VERBOSE("Found %d PCI devices.", count); d->devind = -1; more = 0; } /*if (res) */ } else { d->devind = -1; } if (!take_all) { skip--; } } } /****************************************************************************/ /* ddekit_pci_get_device_id */ /****************************************************************************/ PUBLIC void ddekit_pci_init(void) { ddekit_pci_init_only_one(DDEKIT_PCI_ANY_ID); } /****************************************************************************/ /* ddekit_pci_get_device_id */ /****************************************************************************/ int ddekit_pci_get_device(int nr, int *bus, int *slot, int *func) { if(nr >= 0 && nr < PCI_MAX_DEVS) { *bus = 0; *slot = nr; *func =0; return 0; } return -1; } /****************************************************************************/ /* ddekit_pci_get_device_id */ /****************************************************************************/ PRIVATE struct ddekit_pci_dev * ddekit_get_dev_helper(int bus, int slot, int func) { /* * Used internally to look up devices. * Should make it easier to support multiple buses somewhen */ struct ddekit_pci_dev * ret = 0; if (slot >= 0 && slot < PCI_MAX_DEVS) { ret = &pci_devs[slot]; } if (ret->devind == -1) { ret = 0; } return ret; } /****************************************************************************/ /* ddekit_pci_read */ /****************************************************************************/ PUBLIC int ddekit_pci_read (int bus, int slot, int func, int pos, int len, ddekit_uint32_t *val) { switch(len) { case 1: return ddekit_pci_readb(bus, slot, func, pos, (ddekit_uint8_t*) val); case 2: return ddekit_pci_readw(bus, slot, func, pos, (ddekit_uint16_t*) val); case 4: return ddekit_pci_readl(bus, slot, func, pos, val); default: return -1; } } /****************************************************************************/ /* ddekit_pci_write */ /****************************************************************************/ PUBLIC int ddekit_pci_write (int bus, int slot, int func, int pos, int len, ddekit_uint32_t val) { switch(len) { case 1: return ddekit_pci_writeb(bus, slot, func, pos, (ddekit_uint8_t) val); case 2: return ddekit_pci_writew(bus, slot, func, pos, (ddekit_uint16_t) val); case 4: return ddekit_pci_writel(bus, slot, func, pos, val); default: return -1; } } /****************************************************************************/ /* ddekit_pci_readb */ /****************************************************************************/ PUBLIC int ddekit_pci_readb (int bus, int slot, int func, int pos, ddekit_uint8_t *val) { struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); if (func!=0) { *val=0; return 0; } if (dev) { *val = pci_attr_r8 (dev->devind, pos); DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", bus, slot, func, pos, *val); return 0; } return -1; } /****************************************************************************/ /* ddekit_pci_readw */ /****************************************************************************/ PUBLIC int ddekit_pci_readw (int bus, int slot, int func, int pos, ddekit_uint16_t *val) { struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); if (func!=0) { *val=0; return 0; } if (dev) { *val = pci_attr_r16 (dev->devind, pos); DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", bus, slot, func, pos, *val); return 0; } return -1; } /****************************************************************************/ /* ddekit_pci_readl */ /****************************************************************************/ PUBLIC int ddekit_pci_readl (int bus, int slot, int func, int pos, ddekit_uint32_t *val) { struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); if (func!=0) { *val=0; return 0; } if (dev) { *val = pci_attr_r32 (dev->devind, pos); DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", bus, slot, func, pos, *val); return 0; } return -1; } /****************************************************************************/ /* ddekit_pci_writeb */ /****************************************************************************/ PUBLIC int ddekit_pci_writeb (int bus, int slot, int func, int pos, ddekit_uint8_t val) { struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); if (dev) { pci_attr_w8 (dev->devind, pos, val); DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", bus, slot, func, pos, val); return 0; } return -1; } /****************************************************************************/ /* ddekit_pci_writel */ /****************************************************************************/ PUBLIC int ddekit_pci_writew (int bus, int slot, int func, int pos, ddekit_uint16_t val) { struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); if (dev) { pci_attr_w16 (dev->devind, pos, val); DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x", bus,slot,func,pos, val); return 0; } return -1; } /****************************************************************************/ /* ddekit_pci_writel */ /****************************************************************************/ PUBLIC int ddekit_pci_writel (int bus, int slot, int func, int pos, ddekit_uint32_t val) { struct ddekit_pci_dev * dev = ddekit_get_dev_helper(bus, slot, func); if (dev) { pci_attr_w32 (dev->devind, pos, val); DDEBUG_MSG_VERBOSE("bus: %d, slot: %d, func: %d, pos: %x %x",bus,slot,func,pos, val); return 0; } return -1; } /****************************************************************************/ /* ddekit_pci_find_device */ /****************************************************************************/ PUBLIC struct ddekit_pci_dev *ddekit_pci_find_device (int *bus, int *slot, int *func, struct ddekit_pci_dev *start) { int i,search=0; if(start) search = 1; for(i=0; i < PCI_MAX_DEVS ; i++) { /* start searching? */ if (search) search = (&pci_devs[i]==start); else { struct ddekit_pci_dev * dev = &pci_devs[i]; if ((*slot==dev->slot || *slot == DDEKIT_PCI_ANY_ID) && (*func==dev->func || *func == DDEKIT_PCI_ANY_ID)) { *bus = 0; *slot = dev->slot; *func = dev->func; return dev; } } } return 0; } /****************************************************************************/ /* ddekit_pci_get_vendor */ /****************************************************************************/ PUBLIC unsigned short ddekit_pci_get_vendor(struct ddekit_pci_dev *dev) { return dev->vid; } /****************************************************************************/ /* ddekit_pci_get_device_id */ /****************************************************************************/ PUBLIC unsigned short ddekit_pci_get_device_id(struct ddekit_pci_dev *dev) { return dev->did; } /* * XXX: Those are neither used be DDEFBSD or DDELinux implement them * when you need them */ /****************************************************************************/ /* ddekit_pci_enable_device */ /****************************************************************************/ PUBLIC int ddekit_pci_enable_device(struct ddekit_pci_dev *dev) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_disable_device */ /****************************************************************************/ PUBLIC int ddekit_pci_disable_device(struct ddekit_pci_dev *dev) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_set_master */ /****************************************************************************/ PUBLIC void ddekit_pci_set_master(struct ddekit_pci_dev *dev) { WARN_UNIMPL; } /****************************************************************************/ /* ddekit_pci_get_sub_vendor */ /****************************************************************************/ PUBLIC unsigned short ddekit_pci_get_sub_vendor(struct ddekit_pci_dev *dev) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_get_sub_device */ /****************************************************************************/ PUBLIC unsigned short ddekit_pci_get_sub_device(struct ddekit_pci_dev *dev) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_get_dev_class */ /****************************************************************************/ PUBLIC unsigned ddekit_pci_get_dev_class(struct ddekit_pci_dev *dev) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_get_irq */ /****************************************************************************/ PUBLIC unsigned long ddekit_pci_get_irq(struct ddekit_pci_dev *dev) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_get_name */ /****************************************************************************/ PUBLIC char *ddekit_pci_get_name(struct ddekit_pci_dev *dev) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_get_slot_name */ /****************************************************************************/ PUBLIC char *ddekit_pci_get_slot_name(struct ddekit_pci_dev *dev) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_get_resource */ /****************************************************************************/ PUBLIC ddekit_pci_res_t * ddekit_pci_get_resource(struct ddekit_pci_dev *dev, unsigned int idx) { WARN_UNIMPL; return 0; } /****************************************************************************/ /* ddekit_pci_irq_enable */ /****************************************************************************/ PUBLIC int ddekit_pci_irq_enable (int bus, int slot, int func, int pin, int *irq) { /* call not needed */ #if 0 WARN_UNIMPL; #endif return 0; }