2011-02-25 13:40:31 +01:00
|
|
|
/**
|
|
|
|
* pci.c
|
|
|
|
* @author: Dirk Vogt
|
|
|
|
* @date: 2010-02-18
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
#include <ddekit/pci.h>
|
|
|
|
#include <ddekit/panic.h>
|
|
|
|
#include <minix/syslib.h>
|
|
|
|
|
|
|
|
#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 _PROTOTYPE( 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...");
|
|
|
|
|
2012-03-07 01:10:04 +01:00
|
|
|
pci_init();
|
2011-02-25 13:40:31 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2011-03-07 14:31:48 +01:00
|
|
|
if(start)
|
2011-02-25 13:40:31 +01:00
|
|
|
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))
|
|
|
|
{
|
2011-03-07 14:31:48 +01:00
|
|
|
*bus = 0;
|
|
|
|
*slot = dev->slot;
|
|
|
|
*func = dev->func;
|
2011-02-25 13:40:31 +01:00
|
|
|
return dev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-03-07 14:31:48 +01:00
|
|
|
/****************************************************************************/
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2011-02-25 13:40:31 +01:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|