/uspace/trunk/pci/libpci/i386-ports.c |
---|
14,24 → 14,24 |
static inline void outb(u8 b, u16 port) |
{ |
asm volatile ("outb %0, %1\n" : : "a" (b), "d" (port)); |
asm volatile ("outb %0, %1\n" :: "a" (b), "d" (port)); |
} |
static inline void outw(u16 w, u16 port) |
{ |
asm volatile ("outw %0, %1\n" : : "a" (w), "d" (port)); |
asm volatile ("outw %0, %1\n" :: "a" (w), "d" (port)); |
} |
static inline void outl(u32 l, u16 port) |
{ |
asm volatile ("outl %0, %1\n" : : "a" (l), "d" (port)); |
asm volatile ("outl %0, %1\n" :: "a" (l), "d" (port)); |
} |
static inline u8 inb(u16 port) |
{ |
u8 val; |
asm volatile ("inb %1, %0 \n" : "=a" (val) : "d" (port)); |
asm volatile ("inb %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
} |
38,8 → 38,8 |
static inline u16 inw(u16 port) |
{ |
u16 val; |
asm volatile ("inw %1, %0 \n" : "=a" (val) : "d" (port)); |
asm volatile ("inw %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
} |
46,18 → 46,16 |
static inline u32 inl(u16 port) |
{ |
u32 val; |
asm volatile ("inl %1, %0 \n" : "=a" (val) : "d" (port)); |
asm volatile ("inl %1, %0 \n" : "=a" (val) : "d"(port)); |
return val; |
} |
static void |
conf12_init(struct pci_access *a) |
static void conf12_init(struct pci_access *a) |
{ |
} |
static void |
conf12_cleanup(struct pci_access *a UNUSED) |
static void conf12_cleanup(struct pci_access *a UNUSED) |
{ |
} |
72,28 → 70,31 |
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID. |
*/ |
static int |
intel_sanity_check(struct pci_access *a, struct pci_methods *m) |
static int intel_sanity_check(struct pci_access *a, struct pci_methods *m) |
{ |
struct pci_dev d; |
struct pci_dev d; |
a->debug("...sanity check"); |
d.bus = 0; |
d.func = 0; |
for(d.dev = 0; d.dev < 32; d.dev++) |
{ |
u16 class, vendor; |
if (m->read(&d, PCI_CLASS_DEVICE, (byte *) &class, sizeof(class)) && |
(class == cpu_to_le16(PCI_CLASS_BRIDGE_HOST) || class == cpu_to_le16(PCI_CLASS_DISPLAY_VGA)) || |
m->read(&d, PCI_VENDOR_ID, (byte *) &vendor, sizeof(vendor)) && |
(vendor == cpu_to_le16(PCI_VENDOR_ID_INTEL) || vendor == cpu_to_le16(PCI_VENDOR_ID_COMPAQ))) |
{ |
a->debug("...outside the Asylum at 0/%02x/0", d.dev); |
return 1; |
a->debug("...sanity check"); |
d.bus = 0; |
d.func = 0; |
for (d.dev = 0; d.dev < 32; d.dev++) { |
u16 class, vendor; |
if (m-> |
read(&d, PCI_CLASS_DEVICE, (byte *) & class, |
sizeof(class)) |
&& (class == cpu_to_le16(PCI_CLASS_BRIDGE_HOST) |
|| class == cpu_to_le16(PCI_CLASS_DISPLAY_VGA)) |
|| m->read(&d, PCI_VENDOR_ID, (byte *) & vendor, |
sizeof(vendor)) |
&& (vendor == cpu_to_le16(PCI_VENDOR_ID_INTEL) |
|| vendor == cpu_to_le16(PCI_VENDOR_ID_COMPAQ))) { |
a->debug("...outside the Asylum at 0/%02x/0", |
d.dev); |
return 1; |
} |
} |
} |
a->debug("...insane"); |
return 0; |
a->debug("...insane"); |
return 0; |
} |
/* |
102,75 → 103,72 |
#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3)) |
static int |
conf1_detect(struct pci_access *a) |
static int conf1_detect(struct pci_access *a) |
{ |
unsigned int tmp; |
int res = 0; |
unsigned int tmp; |
int res = 0; |
outb (0x01, 0xCFB); |
tmp = inl (0xCF8); |
outl (0x80000000, 0xCF8); |
if (inl (0xCF8) == 0x80000000) |
res = 1; |
outl (tmp, 0xCF8); |
if (res) |
res = intel_sanity_check(a, &pm_intel_conf1); |
return res; |
outb(0x01, 0xCFB); |
tmp = inl(0xCF8); |
outl(0x80000000, 0xCF8); |
if (inl(0xCF8) == 0x80000000) |
res = 1; |
outl(tmp, 0xCF8); |
if (res) |
res = intel_sanity_check(a, &pm_intel_conf1); |
return res; |
} |
static int |
conf1_read(struct pci_dev *d, int pos, byte *buf, int len) |
static int conf1_read(struct pci_dev *d, int pos, byte * buf, int len) |
{ |
int addr = 0xcfc + (pos&3); |
int addr = 0xcfc + (pos & 3); |
if (pos >= 256) |
return 0; |
if (pos >= 256) |
return 0; |
outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8); |
outl(0x80000000 | ((d->bus & 0xff) << 16) | |
(PCI_DEVFN(d->dev, d->func) << 8) | (pos & ~3), 0xcf8); |
switch (len) |
{ |
case 1: |
buf[0] = inb(addr); |
break; |
case 2: |
((u16 *) buf)[0] = cpu_to_le16(inw(addr)); |
break; |
case 4: |
((u32 *) buf)[0] = cpu_to_le32(inl(addr)); |
break; |
default: |
return pci_generic_block_read(d, pos, buf, len); |
} |
return 1; |
switch (len) { |
case 1: |
buf[0] = inb(addr); |
break; |
case 2: |
((u16 *) buf)[0] = cpu_to_le16(inw(addr)); |
break; |
case 4: |
((u32 *) buf)[0] = cpu_to_le32(inl(addr)); |
break; |
default: |
return pci_generic_block_read(d, pos, buf, len); |
} |
return 1; |
} |
static int |
conf1_write(struct pci_dev *d, int pos, byte *buf, int len) |
static int conf1_write(struct pci_dev *d, int pos, byte * buf, int len) |
{ |
int addr = 0xcfc + (pos&3); |
int addr = 0xcfc + (pos & 3); |
if (pos >= 256) |
return 0; |
if (pos >= 256) |
return 0; |
outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8); |
outl(0x80000000 | ((d->bus & 0xff) << 16) | |
(PCI_DEVFN(d->dev, d->func) << 8) | (pos & ~3), 0xcf8); |
switch (len) |
{ |
case 1: |
outb(buf[0], addr); |
break; |
case 2: |
outw(le16_to_cpu(((u16 *) buf)[0]), addr); |
break; |
case 4: |
outl(le32_to_cpu(((u32 *) buf)[0]), addr); |
break; |
default: |
return pci_generic_block_write(d, pos, buf, len); |
} |
return 1; |
switch (len) { |
case 1: |
outb(buf[0], addr); |
break; |
case 2: |
outw(le16_to_cpu(((u16 *) buf)[0]), addr); |
break; |
case 4: |
outl(le32_to_cpu(((u32 *) buf)[0]), addr); |
break; |
default: |
return pci_generic_block_write(d, pos, buf, len); |
} |
return 1; |
} |
/* |
177,107 → 175,103 |
* Configuration type 2. Obsolete and brain-damaged, but existing. |
*/ |
static int |
conf2_detect(struct pci_access *a) |
static int conf2_detect(struct pci_access *a) |
{ |
/* This is ugly and tends to produce false positives. Beware. */ |
/* This is ugly and tends to produce false positives. Beware. */ |
outb(0x00, 0xCFB); |
outb(0x00, 0xCF8); |
outb(0x00, 0xCFA); |
if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) |
return intel_sanity_check(a, &pm_intel_conf2); |
else |
return 0; |
outb(0x00, 0xCFB); |
outb(0x00, 0xCF8); |
outb(0x00, 0xCFA); |
if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) |
return intel_sanity_check(a, &pm_intel_conf2); |
else |
return 0; |
} |
static int |
conf2_read(struct pci_dev *d, int pos, byte *buf, int len) |
static int conf2_read(struct pci_dev *d, int pos, byte * buf, int len) |
{ |
int addr = 0xc000 | (d->dev << 8) | pos; |
int addr = 0xc000 | (d->dev << 8) | pos; |
if (pos >= 256) |
return 0; |
if (pos >= 256) |
return 0; |
if (d->dev >= 16) |
/* conf2 supports only 16 devices per bus */ |
return 0; |
outb((d->func << 1) | 0xf0, 0xcf8); |
outb(d->bus, 0xcfa); |
switch (len) |
{ |
case 1: |
buf[0] = inb(addr); |
break; |
case 2: |
((u16 *) buf)[0] = cpu_to_le16(inw(addr)); |
break; |
case 4: |
((u32 *) buf)[0] = cpu_to_le32(inl(addr)); |
break; |
default: |
outb(0, 0xcf8); |
return pci_generic_block_read(d, pos, buf, len); |
} |
outb(0, 0xcf8); |
return 1; |
if (d->dev >= 16) |
/* conf2 supports only 16 devices per bus */ |
return 0; |
outb((d->func << 1) | 0xf0, 0xcf8); |
outb(d->bus, 0xcfa); |
switch (len) { |
case 1: |
buf[0] = inb(addr); |
break; |
case 2: |
((u16 *) buf)[0] = cpu_to_le16(inw(addr)); |
break; |
case 4: |
((u32 *) buf)[0] = cpu_to_le32(inl(addr)); |
break; |
default: |
outb(0, 0xcf8); |
return pci_generic_block_read(d, pos, buf, len); |
} |
outb(0, 0xcf8); |
return 1; |
} |
static int |
conf2_write(struct pci_dev *d, int pos, byte *buf, int len) |
static int conf2_write(struct pci_dev *d, int pos, byte * buf, int len) |
{ |
int addr = 0xc000 | (d->dev << 8) | pos; |
int addr = 0xc000 | (d->dev << 8) | pos; |
if (pos >= 256) |
return 0; |
if (pos >= 256) |
return 0; |
if (d->dev >= 16) |
d->access->error("conf2_write: only first 16 devices exist."); |
outb((d->func << 1) | 0xf0, 0xcf8); |
outb(d->bus, 0xcfa); |
switch (len) |
{ |
case 1: |
outb(buf[0], addr); |
break; |
case 2: |
outw(le16_to_cpu(* (u16 *) buf), addr); |
break; |
case 4: |
outl(le32_to_cpu(* (u32 *) buf), addr); |
break; |
default: |
outb(0, 0xcf8); |
return pci_generic_block_write(d, pos, buf, len); |
} |
outb(0, 0xcf8); |
return 1; |
if (d->dev >= 16) |
d->access-> |
error("conf2_write: only first 16 devices exist."); |
outb((d->func << 1) | 0xf0, 0xcf8); |
outb(d->bus, 0xcfa); |
switch (len) { |
case 1: |
outb(buf[0], addr); |
break; |
case 2: |
outw(le16_to_cpu(*(u16 *) buf), addr); |
break; |
case 4: |
outl(le32_to_cpu(*(u32 *) buf), addr); |
break; |
default: |
outb(0, 0xcf8); |
return pci_generic_block_write(d, pos, buf, len); |
} |
outb(0, 0xcf8); |
return 1; |
} |
struct pci_methods pm_intel_conf1 = { |
"Intel-conf1", |
NULL, /* config */ |
conf1_detect, |
conf12_init, |
conf12_cleanup, |
pci_generic_scan, |
pci_generic_fill_info, |
conf1_read, |
conf1_write, |
NULL, /* init_dev */ |
NULL /* cleanup_dev */ |
"Intel-conf1", |
NULL, /* config */ |
conf1_detect, |
conf12_init, |
conf12_cleanup, |
pci_generic_scan, |
pci_generic_fill_info, |
conf1_read, |
conf1_write, |
NULL, /* init_dev */ |
NULL /* cleanup_dev */ |
}; |
struct pci_methods pm_intel_conf2 = { |
"Intel-conf2", |
NULL, /* config */ |
conf2_detect, |
conf12_init, |
conf12_cleanup, |
pci_generic_scan, |
pci_generic_fill_info, |
conf2_read, |
conf2_write, |
NULL, /* init_dev */ |
NULL /* cleanup_dev */ |
"Intel-conf2", |
NULL, /* config */ |
conf2_detect, |
conf12_init, |
conf12_cleanup, |
pci_generic_scan, |
pci_generic_fill_info, |
conf2_read, |
conf2_write, |
NULL, /* init_dev */ |
NULL /* cleanup_dev */ |
}; |
/uspace/trunk/pci/libpci/pci.h |
---|
23,36 → 23,36 |
struct pci_methods; |
enum pci_access_type { |
/* Known access methods, remember to update access.c as well */ |
PCI_ACCESS_I386_TYPE1, /* i386 ports, type 1 (params: none) */ |
PCI_ACCESS_I386_TYPE2, /* i386 ports, type 2 (params: none) */ |
PCI_ACCESS_MAX |
/* Known access methods, remember to update access.c as well */ |
PCI_ACCESS_I386_TYPE1, /* i386 ports, type 1 (params: none) */ |
PCI_ACCESS_I386_TYPE2, /* i386 ports, type 2 (params: none) */ |
PCI_ACCESS_MAX |
}; |
struct pci_access { |
/* Options you can change: */ |
unsigned int method; /* Access method */ |
char *method_params[PCI_ACCESS_MAX]; /* Parameters for the methods */ |
int writeable; /* Open in read/write mode */ |
int buscentric; /* Bus-centric view of the world */ |
int numeric_ids; /* Don't resolve device IDs to names */ |
int debugging; /* Turn on debugging messages */ |
/* Options you can change: */ |
unsigned int method; /* Access method */ |
char *method_params[PCI_ACCESS_MAX]; /* Parameters for the methods */ |
int writeable; /* Open in read/write mode */ |
int buscentric; /* Bus-centric view of the world */ |
int numeric_ids; /* Don't resolve device IDs to names */ |
int debugging; /* Turn on debugging messages */ |
/* Functions you can override: */ |
void (*error)(char *msg, ...); /* Write error message and quit */ |
void (*warning)(char *msg, ...); /* Write a warning message */ |
void (*debug)(char *msg, ...); /* Write a debugging message */ |
/* Functions you can override: */ |
void (*error) (char *msg, ...); /* Write error message and quit */ |
void (*warning) (char *msg, ...); /* Write a warning message */ |
void (*debug) (char *msg, ...); /* Write a debugging message */ |
struct pci_dev *devices; /* Devices found on this bus */ |
struct pci_dev *devices; /* Devices found on this bus */ |
/* Fields used internally: */ |
struct pci_methods *methods; |
struct id_entry **id_hash; /* names.c */ |
struct id_bucket *current_id_bucket; |
int fd; /* proc: fd */ |
int fd_rw; /* proc: fd opened read-write */ |
struct pci_dev *cached_dev; /* proc: device the fd is for */ |
int fd_pos; /* proc: current position */ |
/* Fields used internally: */ |
struct pci_methods *methods; |
struct id_entry **id_hash; /* names.c */ |
struct id_bucket *current_id_bucket; |
int fd; /* proc: fd */ |
int fd_rw; /* proc: fd opened read-write */ |
struct pci_dev *cached_dev; /* proc: device the fd is for */ |
int fd_pos; /* proc: current position */ |
}; |
/* Initialize PCI access */ |
62,7 → 62,7 |
/* Scanning of devices */ |
void pci_scan_bus(struct pci_access *acc); |
struct pci_dev *pci_get_dev(struct pci_access *acc, int domain, int bus, int dev, int func); /* Raw access to specified device */ |
struct pci_dev *pci_get_dev(struct pci_access *acc, int domain, int bus, int dev, int func); /* Raw access to specified device */ |
void pci_free_dev(struct pci_dev *); |
/* |
70,41 → 70,41 |
*/ |
struct pci_dev { |
struct pci_dev *next; /* Next device in the chain */ |
u16 domain; /* PCI domain (host bridge) */ |
u8 bus, dev, func; /* Bus inside domain, device and function */ |
struct pci_dev *next; /* Next device in the chain */ |
u16 domain; /* PCI domain (host bridge) */ |
u8 bus, dev, func; /* Bus inside domain, device and function */ |
/* These fields are set by pci_fill_info() */ |
int known_fields; /* Set of info fields already known */ |
u16 vendor_id, device_id; /* Identity of the device */ |
int irq; /* IRQ number */ |
pciaddr_t base_addr[6]; /* Base addresses */ |
pciaddr_t size[6]; /* Region sizes */ |
pciaddr_t rom_base_addr; /* Expansion ROM base address */ |
pciaddr_t rom_size; /* Expansion ROM size */ |
/* These fields are set by pci_fill_info() */ |
int known_fields; /* Set of info fields already known */ |
u16 vendor_id, device_id; /* Identity of the device */ |
int irq; /* IRQ number */ |
pciaddr_t base_addr[6]; /* Base addresses */ |
pciaddr_t size[6]; /* Region sizes */ |
pciaddr_t rom_base_addr; /* Expansion ROM base address */ |
pciaddr_t rom_size; /* Expansion ROM size */ |
/* Fields used internally: */ |
struct pci_access *access; |
struct pci_methods *methods; |
u8 *cache; /* Cached config registers */ |
int cache_len; |
int hdrtype; /* Cached low 7 bits of header type, -1 if unknown */ |
void *aux; /* Auxillary data */ |
/* Fields used internally: */ |
struct pci_access *access; |
struct pci_methods *methods; |
u8 *cache; /* Cached config registers */ |
int cache_len; |
int hdrtype; /* Cached low 7 bits of header type, -1 if unknown */ |
void *aux; /* Auxillary data */ |
}; |
#define PCI_ADDR_IO_MASK (~(pciaddr_t) 0x3) |
#define PCI_ADDR_MEM_MASK (~(pciaddr_t) 0xf) |
u8 pci_read_byte(struct pci_dev *, int pos); /* Access to configuration space */ |
u8 pci_read_byte(struct pci_dev *, int pos); /* Access to configuration space */ |
u16 pci_read_word(struct pci_dev *, int pos); |
u32 pci_read_long(struct pci_dev *, int pos); |
int pci_read_block(struct pci_dev *, int pos, u8 *buf, int len); |
u32 pci_read_long(struct pci_dev *, int pos); |
int pci_read_block(struct pci_dev *, int pos, u8 * buf, int len); |
int pci_write_byte(struct pci_dev *, int pos, u8 data); |
int pci_write_word(struct pci_dev *, int pos, u16 data); |
int pci_write_long(struct pci_dev *, int pos, u32 data); |
int pci_write_block(struct pci_dev *, int pos, u8 *buf, int len); |
int pci_write_block(struct pci_dev *, int pos, u8 * buf, int len); |
int pci_fill_info(struct pci_dev *, int flags); /* Fill in device information */ |
int pci_fill_info(struct pci_dev *, int flags); /* Fill in device information */ |
#define PCI_FILL_IDENT 1 |
#define PCI_FILL_IRQ 2 |
113,7 → 113,7 |
#define PCI_FILL_SIZES 16 |
#define PCI_FILL_RESCAN 0x10000 |
void pci_setup_cache(struct pci_dev *, u8 *cache, int len); |
void pci_setup_cache(struct pci_dev *, u8 * cache, int len); |
/* |
* Filters |
120,8 → 120,8 |
*/ |
struct pci_filter { |
int domain, bus, slot, func; /* -1 = ANY */ |
int vendor, device; |
int domain, bus, slot, func; /* -1 = ANY */ |
int vendor, device; |
}; |
void pci_filter_init(struct pci_access *, struct pci_filter *); |
145,19 → 145,20 |
* PROGIF (classID, progif) -> programming interface |
*/ |
char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, ...); |
char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, |
...); |
int pci_load_name_list(struct pci_access *a); /* Called automatically by pci_lookup_*() when needed; returns success */ |
void pci_free_name_list(struct pci_access *a); /* Called automatically by pci_cleanup() */ |
enum pci_lookup_mode { |
PCI_LOOKUP_VENDOR = 1, /* Vendor name (args: vendorID) */ |
PCI_LOOKUP_DEVICE = 2, /* Device name (args: vendorID, deviceID) */ |
PCI_LOOKUP_CLASS = 4, /* Device class (args: classID) */ |
PCI_LOOKUP_SUBSYSTEM = 8, |
PCI_LOOKUP_PROGIF = 16, /* Programming interface (args: classID, prog_if) */ |
PCI_LOOKUP_NUMERIC = 0x10000, /* Want only formatted numbers; default if access->numeric_ids is set */ |
PCI_LOOKUP_NO_NUMBERS = 0x20000 /* Return NULL if not found in the database; default is to print numerically */ |
PCI_LOOKUP_VENDOR = 1, /* Vendor name (args: vendorID) */ |
PCI_LOOKUP_DEVICE = 2, /* Device name (args: vendorID, deviceID) */ |
PCI_LOOKUP_CLASS = 4, /* Device class (args: classID) */ |
PCI_LOOKUP_SUBSYSTEM = 8, |
PCI_LOOKUP_PROGIF = 16, /* Programming interface (args: classID, prog_if) */ |
PCI_LOOKUP_NUMERIC = 0x10000, /* Want only formatted numbers; default if access->numeric_ids is set */ |
PCI_LOOKUP_NO_NUMBERS = 0x20000 /* Return NULL if not found in the database; default is to print numerically */ |
}; |
#endif |
/uspace/trunk/pci/libpci/access.c |
---|
16,281 → 16,257 |
#include "internal.h" |
static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = { |
&pm_intel_conf1, |
&pm_intel_conf2, |
&pm_intel_conf1, |
&pm_intel_conf2, |
}; |
struct pci_access * |
pci_alloc(void) |
struct pci_access *pci_alloc(void) |
{ |
struct pci_access *a = malloc(sizeof(struct pci_access)); |
int i; |
struct pci_access *a = malloc(sizeof(struct pci_access)); |
int i; |
bzero(a, sizeof(*a)); |
for(i=0; i<PCI_ACCESS_MAX; i++) |
if (pci_methods[i] && pci_methods[i]->config) |
pci_methods[i]->config(a); |
return a; |
bzero(a, sizeof(*a)); |
for (i = 0; i < PCI_ACCESS_MAX; i++) |
if (pci_methods[i] && pci_methods[i]->config) |
pci_methods[i]->config(a); |
return a; |
} |
void * |
pci_malloc(struct pci_access *a, int size) |
void *pci_malloc(struct pci_access *a, int size) |
{ |
void *x = malloc(size); |
void *x = malloc(size); |
if (!x) |
a->error("Out of memory (allocation of %d bytes failed)", size); |
return x; |
if (!x) |
a->error("Out of memory (allocation of %d bytes failed)", |
size); |
return x; |
} |
void |
pci_mfree(void *x) |
void pci_mfree(void *x) |
{ |
if (x) |
free(x); |
if (x) |
free(x); |
} |
static void |
pci_generic_error(char *msg, ...) |
static void pci_generic_error(char *msg, ...) |
{ |
va_list args; |
va_list args; |
va_start(args, msg); |
puts("pcilib: "); |
vprintf(msg, args); |
putchar('\n'); |
exit(1); |
va_start(args, msg); |
puts("pcilib: "); |
vprintf(msg, args); |
putchar('\n'); |
exit(1); |
} |
static void |
pci_generic_warn(char *msg, ...) |
static void pci_generic_warn(char *msg, ...) |
{ |
va_list args; |
va_list args; |
va_start(args, msg); |
puts("pcilib: "); |
vprintf(msg, args); |
putchar('\n'); |
va_start(args, msg); |
puts("pcilib: "); |
vprintf(msg, args); |
putchar('\n'); |
} |
static void |
pci_generic_debug(char *msg, ...) |
static void pci_generic_debug(char *msg, ...) |
{ |
va_list args; |
va_list args; |
va_start(args, msg); |
vprintf(msg, args); |
va_end(args); |
va_start(args, msg); |
vprintf(msg, args); |
va_end(args); |
} |
static void |
pci_null_debug(char *msg UNUSED, ...) |
static void pci_null_debug(char *msg UNUSED, ...) |
{ |
} |
void |
pci_init(struct pci_access *a) |
void pci_init(struct pci_access *a) |
{ |
if (!a->error) |
a->error = pci_generic_error; |
if (!a->warning) |
a->warning = pci_generic_warn; |
if (!a->debug) |
a->debug = pci_generic_debug; |
if (!a->debugging) |
a->debug = pci_null_debug; |
if (!a->error) |
a->error = pci_generic_error; |
if (!a->warning) |
a->warning = pci_generic_warn; |
if (!a->debug) |
a->debug = pci_generic_debug; |
if (!a->debugging) |
a->debug = pci_null_debug; |
if (a->method) |
{ |
if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method]) |
a->error("This access method is not supported."); |
a->methods = pci_methods[a->method]; |
} |
else |
{ |
unsigned int i; |
for(i=0; i<PCI_ACCESS_MAX; i++) |
if (pci_methods[i]) |
{ |
a->debug("Trying method %d...", i); |
if (pci_methods[i]->detect(a)) |
{ |
a->debug("...OK\n"); |
a->methods = pci_methods[i]; |
a->method = i; |
break; |
} |
a->debug("...No.\n"); |
} |
if (!a->methods) |
a->error("Cannot find any working access method."); |
} |
a->debug("Decided to use %s\n", a->methods->name); |
a->methods->init(a); |
if (a->method) { |
if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method]) |
a->error("This access method is not supported."); |
a->methods = pci_methods[a->method]; |
} else { |
unsigned int i; |
for (i = 0; i < PCI_ACCESS_MAX; i++) |
if (pci_methods[i]) { |
a->debug("Trying method %d...", i); |
if (pci_methods[i]->detect(a)) { |
a->debug("...OK\n"); |
a->methods = pci_methods[i]; |
a->method = i; |
break; |
} |
a->debug("...No.\n"); |
} |
if (!a->methods) |
a->error("Cannot find any working access method."); |
} |
a->debug("Decided to use %s\n", a->methods->name); |
a->methods->init(a); |
} |
void |
pci_cleanup(struct pci_access *a) |
void pci_cleanup(struct pci_access *a) |
{ |
struct pci_dev *d, *e; |
struct pci_dev *d, *e; |
for(d=a->devices; d; d=e) |
{ |
e = d->next; |
pci_free_dev(d); |
} |
if (a->methods) |
a->methods->cleanup(a); |
pci_free_name_list(a); |
pci_mfree(a); |
for (d = a->devices; d; d = e) { |
e = d->next; |
pci_free_dev(d); |
} |
if (a->methods) |
a->methods->cleanup(a); |
pci_free_name_list(a); |
pci_mfree(a); |
} |
void |
pci_scan_bus(struct pci_access *a) |
void pci_scan_bus(struct pci_access *a) |
{ |
a->methods->scan(a); |
a->methods->scan(a); |
} |
struct pci_dev * |
pci_alloc_dev(struct pci_access *a) |
struct pci_dev *pci_alloc_dev(struct pci_access *a) |
{ |
struct pci_dev *d = pci_malloc(a, sizeof(struct pci_dev)); |
struct pci_dev *d = pci_malloc(a, sizeof(struct pci_dev)); |
bzero(d, sizeof(*d)); |
d->access = a; |
d->methods = a->methods; |
d->hdrtype = -1; |
if (d->methods->init_dev) |
d->methods->init_dev(d); |
return d; |
bzero(d, sizeof(*d)); |
d->access = a; |
d->methods = a->methods; |
d->hdrtype = -1; |
if (d->methods->init_dev) |
d->methods->init_dev(d); |
return d; |
} |
int |
pci_link_dev(struct pci_access *a, struct pci_dev *d) |
int pci_link_dev(struct pci_access *a, struct pci_dev *d) |
{ |
d->next = a->devices; |
a->devices = d; |
d->next = a->devices; |
a->devices = d; |
return 1; |
return 1; |
} |
struct pci_dev * |
pci_get_dev(struct pci_access *a, int domain, int bus, int dev, int func) |
struct pci_dev *pci_get_dev(struct pci_access *a, int domain, int bus, |
int dev, int func) |
{ |
struct pci_dev *d = pci_alloc_dev(a); |
struct pci_dev *d = pci_alloc_dev(a); |
d->domain = domain; |
d->bus = bus; |
d->dev = dev; |
d->func = func; |
return d; |
d->domain = domain; |
d->bus = bus; |
d->dev = dev; |
d->func = func; |
return d; |
} |
void pci_free_dev(struct pci_dev *d) |
{ |
if (d->methods->cleanup_dev) |
d->methods->cleanup_dev(d); |
pci_mfree(d); |
if (d->methods->cleanup_dev) |
d->methods->cleanup_dev(d); |
pci_mfree(d); |
} |
static inline void |
pci_read_data(struct pci_dev *d, void *buf, int pos, int len) |
{ |
if (pos & (len-1)) |
d->access->error("Unaligned read: pos=%02x, len=%d", pos, len); |
if (pos + len <= d->cache_len) |
memcpy(buf, d->cache + pos, len); |
else if (!d->methods->read(d, pos, buf, len)) |
memset(buf, 0xff, len); |
if (pos & (len - 1)) |
d->access->error("Unaligned read: pos=%02x, len=%d", pos, |
len); |
if (pos + len <= d->cache_len) |
memcpy(buf, d->cache + pos, len); |
else if (!d->methods->read(d, pos, buf, len)) |
memset(buf, 0xff, len); |
} |
byte |
pci_read_byte(struct pci_dev *d, int pos) |
byte pci_read_byte(struct pci_dev *d, int pos) |
{ |
byte buf; |
pci_read_data(d, &buf, pos, 1); |
return buf; |
byte buf; |
pci_read_data(d, &buf, pos, 1); |
return buf; |
} |
word |
pci_read_word(struct pci_dev *d, int pos) |
word pci_read_word(struct pci_dev * d, int pos) |
{ |
word buf; |
pci_read_data(d, &buf, pos, 2); |
return le16_to_cpu(buf); |
word buf; |
pci_read_data(d, &buf, pos, 2); |
return le16_to_cpu(buf); |
} |
u32 |
pci_read_long(struct pci_dev *d, int pos) |
u32 pci_read_long(struct pci_dev * d, int pos) |
{ |
u32 buf; |
pci_read_data(d, &buf, pos, 4); |
return le32_to_cpu(buf); |
u32 buf; |
pci_read_data(d, &buf, pos, 4); |
return le32_to_cpu(buf); |
} |
int |
pci_read_block(struct pci_dev *d, int pos, byte *buf, int len) |
int pci_read_block(struct pci_dev *d, int pos, byte * buf, int len) |
{ |
return d->methods->read(d, pos, buf, len); |
return d->methods->read(d, pos, buf, len); |
} |
static inline int |
pci_write_data(struct pci_dev *d, void *buf, int pos, int len) |
{ |
if (pos & (len-1)) |
d->access->error("Unaligned write: pos=%02x,len=%d", pos, len); |
if (pos + len <= d->cache_len) |
memcpy(d->cache + pos, buf, len); |
return d->methods->write(d, pos, buf, len); |
if (pos & (len - 1)) |
d->access->error("Unaligned write: pos=%02x,len=%d", pos, |
len); |
if (pos + len <= d->cache_len) |
memcpy(d->cache + pos, buf, len); |
return d->methods->write(d, pos, buf, len); |
} |
int |
pci_write_byte(struct pci_dev *d, int pos, byte data) |
int pci_write_byte(struct pci_dev *d, int pos, byte data) |
{ |
return pci_write_data(d, &data, pos, 1); |
return pci_write_data(d, &data, pos, 1); |
} |
int |
pci_write_word(struct pci_dev *d, int pos, word data) |
int pci_write_word(struct pci_dev *d, int pos, word data) |
{ |
word buf = cpu_to_le16(data); |
return pci_write_data(d, &buf, pos, 2); |
word buf = cpu_to_le16(data); |
return pci_write_data(d, &buf, pos, 2); |
} |
int |
pci_write_long(struct pci_dev *d, int pos, u32 data) |
int pci_write_long(struct pci_dev *d, int pos, u32 data) |
{ |
u32 buf = cpu_to_le32(data); |
return pci_write_data(d, &buf, pos, 4); |
u32 buf = cpu_to_le32(data); |
return pci_write_data(d, &buf, pos, 4); |
} |
int |
pci_write_block(struct pci_dev *d, int pos, byte *buf, int len) |
int pci_write_block(struct pci_dev *d, int pos, byte * buf, int len) |
{ |
if (pos < d->cache_len) |
{ |
int l = (pos + len >= d->cache_len) ? (d->cache_len - pos) : len; |
memcpy(d->cache + pos, buf, l); |
} |
return d->methods->write(d, pos, buf, len); |
if (pos < d->cache_len) { |
int l = |
(pos + len >= |
d->cache_len) ? (d->cache_len - pos) : len; |
memcpy(d->cache + pos, buf, l); |
} |
return d->methods->write(d, pos, buf, len); |
} |
int |
pci_fill_info(struct pci_dev *d, int flags) |
int pci_fill_info(struct pci_dev *d, int flags) |
{ |
if (flags & PCI_FILL_RESCAN) |
{ |
flags &= ~PCI_FILL_RESCAN; |
d->known_fields = 0; |
} |
if (flags & ~d->known_fields) |
d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields); |
return d->known_fields; |
if (flags & PCI_FILL_RESCAN) { |
flags &= ~PCI_FILL_RESCAN; |
d->known_fields = 0; |
} |
if (flags & ~d->known_fields) |
d->known_fields |= |
d->methods->fill_info(d, flags & ~d->known_fields); |
return d->known_fields; |
} |
void |
pci_setup_cache(struct pci_dev *d, byte *cache, int len) |
void pci_setup_cache(struct pci_dev *d, byte * cache, int len) |
{ |
d->cache = cache; |
d->cache_len = len; |
d->cache = cache; |
d->cache_len = len; |
} |
/uspace/trunk/pci/libpci/internal.h |
---|
12,24 → 12,25 |
#include "sysdep.h" |
struct pci_methods { |
char *name; |
void (*config)(struct pci_access *); |
int (*detect)(struct pci_access *); |
void (*init)(struct pci_access *); |
void (*cleanup)(struct pci_access *); |
void (*scan)(struct pci_access *); |
int (*fill_info)(struct pci_dev *, int flags); |
int (*read)(struct pci_dev *, int pos, byte *buf, int len); |
int (*write)(struct pci_dev *, int pos, byte *buf, int len); |
void (*init_dev)(struct pci_dev *); |
void (*cleanup_dev)(struct pci_dev *); |
char *name; |
void (*config) (struct pci_access *); |
int (*detect) (struct pci_access *); |
void (*init) (struct pci_access *); |
void (*cleanup) (struct pci_access *); |
void (*scan) (struct pci_access *); |
int (*fill_info) (struct pci_dev *, int flags); |
int (*read) (struct pci_dev *, int pos, byte * buf, int len); |
int (*write) (struct pci_dev *, int pos, byte * buf, int len); |
void (*init_dev) (struct pci_dev *); |
void (*cleanup_dev) (struct pci_dev *); |
}; |
void pci_generic_scan_bus(struct pci_access *, byte *busmap, int bus); |
void pci_generic_scan_bus(struct pci_access *, byte * busmap, int bus); |
void pci_generic_scan(struct pci_access *); |
int pci_generic_fill_info(struct pci_dev *, int flags); |
int pci_generic_block_read(struct pci_dev *, int pos, byte *buf, int len); |
int pci_generic_block_write(struct pci_dev *, int pos, byte *buf, int len); |
int pci_generic_block_read(struct pci_dev *, int pos, byte * buf, int len); |
int pci_generic_block_write(struct pci_dev *, int pos, byte * buf, |
int len); |
void *pci_malloc(struct pci_access *, int); |
void pci_mfree(void *); |
38,5 → 39,5 |
int pci_link_dev(struct pci_access *, struct pci_dev *); |
extern struct pci_methods pm_intel_conf1, pm_intel_conf2, pm_linux_proc, |
pm_fbsd_device, pm_aix_device, pm_nbsd_libpci, pm_obsd_device, |
pm_dump, pm_linux_sysfs; |
pm_fbsd_device, pm_aix_device, pm_nbsd_libpci, pm_obsd_device, |
pm_dump, pm_linux_sysfs; |
/uspace/trunk/pci/libpci/names.c |
---|
18,26 → 18,26 |
#include "pci_ids.h" |
struct id_entry { |
struct id_entry *next; |
u32 id12, id34; |
byte cat; |
byte name[1]; |
struct id_entry *next; |
u32 id12, id34; |
byte cat; |
byte name[1]; |
}; |
enum id_entry_type { |
ID_UNKNOWN, |
ID_VENDOR, |
ID_DEVICE, |
ID_SUBSYSTEM, |
ID_GEN_SUBSYSTEM, |
ID_CLASS, |
ID_SUBCLASS, |
ID_PROGIF |
ID_UNKNOWN, |
ID_VENDOR, |
ID_DEVICE, |
ID_SUBSYSTEM, |
ID_GEN_SUBSYSTEM, |
ID_CLASS, |
ID_SUBCLASS, |
ID_PROGIF |
}; |
struct id_bucket { |
struct id_bucket *next; |
unsigned int full; |
struct id_bucket *next; |
unsigned int full; |
}; |
#define MAX_LINE 1024 |
48,8 → 48,8 |
#define BUCKET_ALIGNMENT __alignof__(struct id_bucket) |
#else |
union id_align { |
struct id_bucket *next; |
unsigned int full; |
struct id_bucket *next; |
unsigned int full; |
}; |
#define BUCKET_ALIGNMENT sizeof(union id_align) |
#endif |
57,422 → 57,435 |
static void *id_alloc(struct pci_access *a, unsigned int size) |
{ |
struct id_bucket *buck = a->current_id_bucket; |
unsigned int pos; |
if (!buck || buck->full + size > BUCKET_SIZE) |
{ |
buck = pci_malloc(a, BUCKET_SIZE); |
buck->next = a->current_id_bucket; |
a->current_id_bucket = buck; |
buck->full = BUCKET_ALIGN(sizeof(struct id_bucket)); |
} |
pos = buck->full; |
buck->full = BUCKET_ALIGN(buck->full + size); |
return (byte *)buck + pos; |
struct id_bucket *buck = a->current_id_bucket; |
unsigned int pos; |
if (!buck || buck->full + size > BUCKET_SIZE) { |
buck = pci_malloc(a, BUCKET_SIZE); |
buck->next = a->current_id_bucket; |
a->current_id_bucket = buck; |
buck->full = BUCKET_ALIGN(sizeof(struct id_bucket)); |
} |
pos = buck->full; |
buck->full = BUCKET_ALIGN(buck->full + size); |
return (byte *) buck + pos; |
} |
static inline u32 id_pair(unsigned int x, unsigned int y) |
{ |
return ((x << 16) | y); |
return ((x << 16) | y); |
} |
static inline unsigned int id_hash(int cat, u32 id12, u32 id34) |
{ |
unsigned int h; |
unsigned int h; |
h = id12 ^ (id34 << 3) ^ (cat << 5); |
return h % HASH_SIZE; |
h = id12 ^ (id34 << 3) ^ (cat << 5); |
return h % HASH_SIZE; |
} |
static struct id_entry *id_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4) |
static struct id_entry *id_lookup(struct pci_access *a, int cat, int id1, |
int id2, int id3, int id4) |
{ |
struct id_entry *n; |
u32 id12 = id_pair(id1, id2); |
u32 id34 = id_pair(id3, id4); |
struct id_entry *n; |
u32 id12 = id_pair(id1, id2); |
u32 id34 = id_pair(id3, id4); |
n = a->id_hash[id_hash(cat, id12, id34)]; |
while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) |
n = n->next; |
return n; |
n = a->id_hash[id_hash(cat, id12, id34)]; |
while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) |
n = n->next; |
return n; |
} |
static int id_insert(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, byte *text) |
static int id_insert(struct pci_access *a, int cat, int id1, int id2, |
int id3, int id4, byte * text) |
{ |
u32 id12 = id_pair(id1, id2); |
u32 id34 = id_pair(id3, id4); |
unsigned int h = id_hash(cat, id12, id34); |
struct id_entry *n = a->id_hash[h]; |
int len = strlen((char *) text); |
u32 id12 = id_pair(id1, id2); |
u32 id34 = id_pair(id3, id4); |
unsigned int h = id_hash(cat, id12, id34); |
struct id_entry *n = a->id_hash[h]; |
int len = strlen((char *) text); |
while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) |
n = n->next; |
if (n) |
return 1; |
n = id_alloc(a, sizeof(struct id_entry) + len); |
n->id12 = id12; |
n->id34 = id34; |
n->cat = cat; |
memcpy(n->name, text, len+1); |
n->next = a->id_hash[h]; |
a->id_hash[h] = n; |
return 0; |
while (n && (n->id12 != id12 || n->id34 != id34 || n->cat != cat)) |
n = n->next; |
if (n) |
return 1; |
n = id_alloc(a, sizeof(struct id_entry) + len); |
n->id12 = id12; |
n->id34 = id34; |
n->cat = cat; |
memcpy(n->name, text, len + 1); |
n->next = a->id_hash[h]; |
a->id_hash[h] = n; |
return 0; |
} |
static int id_hex(byte *p, int cnt) |
static int id_hex(byte * p, int cnt) |
{ |
int x = 0; |
while (cnt--) |
{ |
x <<= 4; |
if (*p >= '0' && *p <= '9') |
x += (*p - '0'); |
else if (*p >= 'a' && *p <= 'f') |
x += (*p - 'a' + 10); |
else if (*p >= 'A' && *p <= 'F') |
x += (*p - 'A' + 10); |
else |
return -1; |
p++; |
} |
return x; |
int x = 0; |
while (cnt--) { |
x <<= 4; |
if (*p >= '0' && *p <= '9') |
x += (*p - '0'); |
else if (*p >= 'a' && *p <= 'f') |
x += (*p - 'a' + 10); |
else if (*p >= 'A' && *p <= 'F') |
x += (*p - 'A' + 10); |
else |
return -1; |
p++; |
} |
return x; |
} |
static inline int id_white_p(int c) |
{ |
return (c == ' ') || (c == '\t'); |
return (c == ' ') || (c == '\t'); |
} |
static const char *id_parse_list(struct pci_access *a, int *lino) |
{ |
byte *line; |
byte *p; |
int id1=0, id2=0, id3=0, id4=0; |
int cat = -1; |
int nest; |
static const char parse_error[] = "Parse error"; |
int i; |
byte *line; |
byte *p; |
int id1 = 0, id2 = 0, id3 = 0, id4 = 0; |
int cat = -1; |
int nest; |
static const char parse_error[] = "Parse error"; |
int i; |
*lino = 0; |
for (i = 0; i < sizeof(pci_ids)/sizeof(char *); i++) { |
line = (byte *) pci_ids[i]; |
(*lino)++; |
p = line; |
while (*p) |
p++; |
if (p > line && (p[-1] == ' ' || p[-1] == '\t')) |
*--p = 0; |
*lino = 0; |
for (i = 0; i < sizeof(pci_ids) / sizeof(char *); i++) { |
line = (byte *) pci_ids[i]; |
(*lino)++; |
p = line; |
while (*p) |
p++; |
if (p > line && (p[-1] == ' ' || p[-1] == '\t')) |
*--p = 0; |
p = line; |
while (id_white_p(*p)) |
p++; |
if (!*p || *p == '#') |
continue; |
p = line; |
while (id_white_p(*p)) |
p++; |
if (!*p || *p == '#') |
continue; |
p = line; |
while (*p == '\t') |
p++; |
nest = p - line; |
p = line; |
while (*p == '\t') |
p++; |
nest = p - line; |
if (!nest) /* Top-level entries */ |
{ |
if (p[0] == 'C' && p[1] == ' ') /* Class block */ |
{ |
if ((id1 = id_hex(p+2, 2)) < 0 || !id_white_p(p[4])) |
return parse_error; |
cat = ID_CLASS; |
p += 5; |
} |
else if (p[0] == 'S' && p[1] == ' ') |
{ /* Generic subsystem block */ |
if ((id1 = id_hex(p+2, 4)) < 0 || p[6]) |
return parse_error; |
if (!id_lookup(a, ID_VENDOR, id1, 0, 0, 0)) |
return "Vendor does not exist"; |
cat = ID_GEN_SUBSYSTEM; |
continue; |
} |
else if (p[0] >= 'A' && p[0] <= 'Z' && p[1] == ' ') |
{ /* Unrecognized block (RFU) */ |
cat = ID_UNKNOWN; |
continue; |
} |
else /* Vendor ID */ |
{ |
if ((id1 = id_hex(p, 4)) < 0 || !id_white_p(p[4])) |
return parse_error; |
cat = ID_VENDOR; |
p += 5; |
} |
id2 = id3 = id4 = 0; |
if (!nest) { /* Top-level entries */ |
if (p[0] == 'C' && p[1] == ' ') { /* Class block */ |
if ((id1 = id_hex(p + 2, 2)) < 0 |
|| !id_white_p(p[4])) |
return parse_error; |
cat = ID_CLASS; |
p += 5; |
} else if (p[0] == 'S' && p[1] == ' ') { /* Generic subsystem block */ |
if ((id1 = id_hex(p + 2, 4)) < 0 || p[6]) |
return parse_error; |
if (!id_lookup(a, ID_VENDOR, id1, 0, 0, 0)) |
return "Vendor does not exist"; |
cat = ID_GEN_SUBSYSTEM; |
continue; |
} else if (p[0] >= 'A' && p[0] <= 'Z' && p[1] == ' ') { /* Unrecognized block (RFU) */ |
cat = ID_UNKNOWN; |
continue; |
} else { /* Vendor ID */ |
if ((id1 = id_hex(p, 4)) < 0 |
|| !id_white_p(p[4])) |
return parse_error; |
cat = ID_VENDOR; |
p += 5; |
} |
id2 = id3 = id4 = 0; |
} else if (cat == ID_UNKNOWN) /* Nested entries in RFU blocks are skipped */ |
continue; |
else if (nest == 1) /* Nesting level 1 */ |
switch (cat) { |
case ID_VENDOR: |
case ID_DEVICE: |
case ID_SUBSYSTEM: |
if ((id2 = id_hex(p, 4)) < 0 |
|| !id_white_p(p[4])) |
return parse_error; |
p += 5; |
cat = ID_DEVICE; |
id3 = id4 = 0; |
break; |
case ID_GEN_SUBSYSTEM: |
if ((id2 = id_hex(p, 4)) < 0 |
|| !id_white_p(p[4])) |
return parse_error; |
p += 5; |
id3 = id4 = 0; |
break; |
case ID_CLASS: |
case ID_SUBCLASS: |
case ID_PROGIF: |
if ((id2 = id_hex(p, 2)) < 0 |
|| !id_white_p(p[2])) |
return parse_error; |
p += 3; |
cat = ID_SUBCLASS; |
id3 = id4 = 0; |
break; |
default: |
return parse_error; |
} else if (nest == 2) /* Nesting level 2 */ |
switch (cat) { |
case ID_DEVICE: |
case ID_SUBSYSTEM: |
if ((id3 = id_hex(p, 4)) < 0 |
|| !id_white_p(p[4]) |
|| (id4 = id_hex(p + 5, 4)) < 0 |
|| !id_white_p(p[9])) |
return parse_error; |
p += 10; |
cat = ID_SUBSYSTEM; |
break; |
case ID_CLASS: |
case ID_SUBCLASS: |
case ID_PROGIF: |
if ((id3 = id_hex(p, 2)) < 0 |
|| !id_white_p(p[2])) |
return parse_error; |
p += 3; |
cat = ID_PROGIF; |
id4 = 0; |
break; |
default: |
return parse_error; |
} else /* Nesting level 3 or more */ |
return parse_error; |
while (id_white_p(*p)) |
p++; |
if (!*p) |
return parse_error; |
if (id_insert(a, cat, id1, id2, id3, id4, p)) |
return "Duplicate entry"; |
} |
else if (cat == ID_UNKNOWN) /* Nested entries in RFU blocks are skipped */ |
continue; |
else if (nest == 1) /* Nesting level 1 */ |
switch (cat) |
{ |
case ID_VENDOR: |
case ID_DEVICE: |
case ID_SUBSYSTEM: |
if ((id2 = id_hex(p, 4)) < 0 || !id_white_p(p[4])) |
return parse_error; |
p += 5; |
cat = ID_DEVICE; |
id3 = id4 = 0; |
break; |
case ID_GEN_SUBSYSTEM: |
if ((id2 = id_hex(p, 4)) < 0 || !id_white_p(p[4])) |
return parse_error; |
p += 5; |
id3 = id4 = 0; |
break; |
case ID_CLASS: |
case ID_SUBCLASS: |
case ID_PROGIF: |
if ((id2 = id_hex(p, 2)) < 0 || !id_white_p(p[2])) |
return parse_error; |
p += 3; |
cat = ID_SUBCLASS; |
id3 = id4 = 0; |
break; |
default: |
return parse_error; |
} |
else if (nest == 2) /* Nesting level 2 */ |
switch (cat) |
{ |
case ID_DEVICE: |
case ID_SUBSYSTEM: |
if ((id3 = id_hex(p, 4)) < 0 || !id_white_p(p[4]) || (id4 = id_hex(p+5, 4)) < 0 || !id_white_p(p[9])) |
return parse_error; |
p += 10; |
cat = ID_SUBSYSTEM; |
break; |
case ID_CLASS: |
case ID_SUBCLASS: |
case ID_PROGIF: |
if ((id3 = id_hex(p, 2)) < 0 || !id_white_p(p[2])) |
return parse_error; |
p += 3; |
cat = ID_PROGIF; |
id4 = 0; |
break; |
default: |
return parse_error; |
} |
else /* Nesting level 3 or more */ |
return parse_error; |
while (id_white_p(*p)) |
p++; |
if (!*p) |
return parse_error; |
if (id_insert(a, cat, id1, id2, id3, id4, p)) |
return "Duplicate entry"; |
} |
return NULL; |
return NULL; |
} |
int |
pci_load_name_list(struct pci_access *a) |
int pci_load_name_list(struct pci_access *a) |
{ |
int lino; |
const char *err; |
int lino; |
const char *err; |
pci_free_name_list(a); |
a->id_hash = pci_malloc(a, sizeof(struct id_entry *) * HASH_SIZE); |
bzero(a->id_hash, sizeof(struct id_entry *) * HASH_SIZE); |
err = id_parse_list(a, &lino); |
if (err) |
a->error("%s at %s, element %d\n", err, "pci_ids.h", lino); |
return 1; |
pci_free_name_list(a); |
a->id_hash = pci_malloc(a, sizeof(struct id_entry *) * HASH_SIZE); |
bzero(a->id_hash, sizeof(struct id_entry *) * HASH_SIZE); |
err = id_parse_list(a, &lino); |
if (err) |
a->error("%s at %s, element %d\n", err, "pci_ids.h", lino); |
return 1; |
} |
void |
pci_free_name_list(struct pci_access *a) |
void pci_free_name_list(struct pci_access *a) |
{ |
pci_mfree(a->id_hash); |
a->id_hash = NULL; |
while (a->current_id_bucket) |
{ |
struct id_bucket *buck = a->current_id_bucket; |
a->current_id_bucket = buck->next; |
pci_mfree(buck); |
} |
pci_mfree(a->id_hash); |
a->id_hash = NULL; |
while (a->current_id_bucket) { |
struct id_bucket *buck = a->current_id_bucket; |
a->current_id_bucket = buck->next; |
pci_mfree(buck); |
} |
} |
static struct id_entry *id_lookup_subsys(struct pci_access *a, int iv, int id, int isv, int isd) |
static struct id_entry *id_lookup_subsys(struct pci_access *a, int iv, |
int id, int isv, int isd) |
{ |
struct id_entry *d = NULL; |
if (iv > 0 && id > 0) /* Per-device lookup */ |
d = id_lookup(a, ID_SUBSYSTEM, iv, id, isv, isd); |
if (!d) /* Generic lookup */ |
d = id_lookup(a, ID_GEN_SUBSYSTEM, isv, isd, 0, 0); |
if (!d && iv == isv && id == isd) /* Check for subsystem == device */ |
d = id_lookup(a, ID_DEVICE, iv, id, 0, 0); |
return d; |
struct id_entry *d = NULL; |
if (iv > 0 && id > 0) /* Per-device lookup */ |
d = id_lookup(a, ID_SUBSYSTEM, iv, id, isv, isd); |
if (!d) /* Generic lookup */ |
d = id_lookup(a, ID_GEN_SUBSYSTEM, isv, isd, 0, 0); |
if (!d && iv == isv && id == isd) /* Check for subsystem == device */ |
d = id_lookup(a, ID_DEVICE, iv, id, 0, 0); |
return d; |
} |
char * |
pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, ...) |
char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, |
...) |
{ |
va_list args; |
int num, res, synth; |
struct id_entry *v, *d, *cls, *pif; |
int iv, id, isv, isd, icls, ipif; |
va_list args; |
int num, res, synth; |
struct id_entry *v, *d, *cls, *pif; |
int iv, id, isv, isd, icls, ipif; |
va_start(args, flags); |
va_start(args, flags); |
num = 0; |
if ((flags & PCI_LOOKUP_NUMERIC) || a->numeric_ids) |
{ |
flags &= ~PCI_LOOKUP_NUMERIC; |
num = 1; |
} |
else if (!a->id_hash) |
{ |
if (!pci_load_name_list(a)) |
num = a->numeric_ids = 1; |
} |
num = 0; |
if ((flags & PCI_LOOKUP_NUMERIC) || a->numeric_ids) { |
flags &= ~PCI_LOOKUP_NUMERIC; |
num = 1; |
} else if (!a->id_hash) { |
if (!pci_load_name_list(a)) |
num = a->numeric_ids = 1; |
} |
if (flags & PCI_LOOKUP_NO_NUMBERS) |
{ |
flags &= ~PCI_LOOKUP_NO_NUMBERS; |
synth = 0; |
if (num) |
return NULL; |
} |
else |
synth = 1; |
if (flags & PCI_LOOKUP_NO_NUMBERS) { |
flags &= ~PCI_LOOKUP_NO_NUMBERS; |
synth = 0; |
if (num) |
return NULL; |
} else |
synth = 1; |
switch (flags) |
{ |
case PCI_LOOKUP_VENDOR: |
iv = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", iv); |
else if (v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0)) |
return (char *) v->name; |
else |
res = snprintf(buf, size, "Unknown vendor %04x", iv); |
break; |
case PCI_LOOKUP_DEVICE: |
iv = va_arg(args, int); |
id = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", id); |
else if (d = id_lookup(a, ID_DEVICE, iv, id, 0, 0)) |
return (char *) d->name; |
else if (synth) |
res = snprintf(buf, size, "Unknown device %04x", id); |
else |
return NULL; |
break; |
case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE: |
iv = va_arg(args, int); |
id = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x:%04x", iv, id); |
else |
{ |
v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0); |
d = id_lookup(a, ID_DEVICE, iv, id, 0, 0); |
if (v && d) |
res = snprintf(buf, size, "%s %s", v->name, d->name); |
else if (!synth) |
return NULL; |
else if (!v) |
res = snprintf(buf, size, "Unknown device %04x:%04x", iv, id); |
else /* !d */ |
res = snprintf(buf, size, "%s Unknown device %04x", v->name, id); |
switch (flags) { |
case PCI_LOOKUP_VENDOR: |
iv = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", iv); |
else if (v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0)) |
return (char *) v->name; |
else |
res = |
snprintf(buf, size, "Unknown vendor %04x", iv); |
break; |
case PCI_LOOKUP_DEVICE: |
iv = va_arg(args, int); |
id = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", id); |
else if (d = id_lookup(a, ID_DEVICE, iv, id, 0, 0)) |
return (char *) d->name; |
else if (synth) |
res = |
snprintf(buf, size, "Unknown device %04x", id); |
else |
return NULL; |
break; |
case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE: |
iv = va_arg(args, int); |
id = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x:%04x", iv, id); |
else { |
v = id_lookup(a, ID_VENDOR, iv, 0, 0, 0); |
d = id_lookup(a, ID_DEVICE, iv, id, 0, 0); |
if (v && d) |
res = |
snprintf(buf, size, "%s %s", v->name, |
d->name); |
else if (!synth) |
return NULL; |
else if (!v) |
res = |
snprintf(buf, size, |
"Unknown device %04x:%04x", |
iv, id); |
else /* !d */ |
res = |
snprintf(buf, size, |
"%s Unknown device %04x", |
v->name, id); |
} |
break; |
case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR: |
isv = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", isv); |
else if (v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0)) |
return (char *) v->name; |
else if (synth) |
res = |
snprintf(buf, size, "Unknown vendor %04x", |
isv); |
else |
return NULL; |
break; |
case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE: |
iv = va_arg(args, int); |
id = va_arg(args, int); |
isv = va_arg(args, int); |
isd = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", isd); |
else if (d = id_lookup_subsys(a, iv, id, isv, isd)) |
return (char *) d->name; |
else if (synth) |
res = |
snprintf(buf, size, "Unknown device %04x", |
isd); |
else |
return NULL; |
break; |
case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM: |
iv = va_arg(args, int); |
id = va_arg(args, int); |
isv = va_arg(args, int); |
isd = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x:%04x", isv, isd); |
else { |
v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0); |
d = id_lookup_subsys(a, iv, id, isv, isd); |
if (v && d) |
res = |
snprintf(buf, size, "%s %s", v->name, |
d->name); |
else if (!synth) |
return NULL; |
else if (!v) |
res = |
snprintf(buf, size, |
"Unknown device %04x:%04x", |
isv, isd); |
else /* !d */ |
res = |
snprintf(buf, size, |
"%s Unknown device %04x", |
v->name, isd); |
} |
break; |
case PCI_LOOKUP_CLASS: |
icls = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", icls); |
else if (cls = |
id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, |
0, 0)) |
return (char *) cls->name; |
else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0)) |
res = |
snprintf(buf, size, "%s [%04x]", cls->name, |
icls); |
else if (synth) |
res = snprintf(buf, size, "Class %04x", icls); |
else |
return NULL; |
break; |
case PCI_LOOKUP_PROGIF: |
icls = va_arg(args, int); |
ipif = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%02x", ipif); |
else if (pif = |
id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, |
ipif, 0)) |
return (char *) pif->name; |
else if (icls == 0x0101 && !(ipif & 0x70)) { |
/* IDE controllers have complex prog-if semantics */ |
res = snprintf(buf, size, "%s%s%s%s%s", |
(ipif & 0x80) ? "Master " : "", |
(ipif & 0x08) ? "SecP " : "", |
(ipif & 0x04) ? "SecO " : "", |
(ipif & 0x02) ? "PriP " : "", |
(ipif & 0x01) ? "PriO " : ""); |
if (res > 0 && res < size) |
buf[--res] = 0; |
} else if (synth) |
res = snprintf(buf, size, "ProgIf %02x", ipif); |
else |
return NULL; |
break; |
default: |
return "<pci_lookup_name: invalid request>"; |
} |
break; |
case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR: |
isv = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", isv); |
else if (v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0)) |
return (char *) v->name; |
else if (synth) |
res = snprintf(buf, size, "Unknown vendor %04x", isv); |
else |
return NULL; |
break; |
case PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE: |
iv = va_arg(args, int); |
id = va_arg(args, int); |
isv = va_arg(args, int); |
isd = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", isd); |
else if (d = id_lookup_subsys(a, iv, id, isv, isd)) |
return (char *) d->name; |
else if (synth) |
res = snprintf(buf, size, "Unknown device %04x", isd); |
else |
return NULL; |
break; |
case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM: |
iv = va_arg(args, int); |
id = va_arg(args, int); |
isv = va_arg(args, int); |
isd = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x:%04x", isv, isd); |
else |
{ |
v = id_lookup(a, ID_VENDOR, isv, 0, 0, 0); |
d = id_lookup_subsys(a, iv, id, isv, isd); |
if (v && d) |
res = snprintf(buf, size, "%s %s", v->name, d->name); |
else if (!synth) |
return NULL; |
else if (!v) |
res = snprintf(buf, size, "Unknown device %04x:%04x", isv, isd); |
else /* !d */ |
res = snprintf(buf, size, "%s Unknown device %04x", v->name, isd); |
} |
break; |
case PCI_LOOKUP_CLASS: |
icls = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%04x", icls); |
else if (cls = id_lookup(a, ID_SUBCLASS, icls >> 8, icls & 0xff, 0, 0)) |
return (char *) cls->name; |
else if (cls = id_lookup(a, ID_CLASS, icls, 0, 0, 0)) |
res = snprintf(buf, size, "%s [%04x]", cls->name, icls); |
else if (synth) |
res = snprintf(buf, size, "Class %04x", icls); |
else |
return NULL; |
break; |
case PCI_LOOKUP_PROGIF: |
icls = va_arg(args, int); |
ipif = va_arg(args, int); |
if (num) |
res = snprintf(buf, size, "%02x", ipif); |
else if (pif = id_lookup(a, ID_PROGIF, icls >> 8, icls & 0xff, ipif, 0)) |
return (char *) pif->name; |
else if (icls == 0x0101 && !(ipif & 0x70)) |
{ |
/* IDE controllers have complex prog-if semantics */ |
res = snprintf(buf, size, "%s%s%s%s%s", |
(ipif & 0x80) ? "Master " : "", |
(ipif & 0x08) ? "SecP " : "", |
(ipif & 0x04) ? "SecO " : "", |
(ipif & 0x02) ? "PriP " : "", |
(ipif & 0x01) ? "PriO " : ""); |
if (res > 0 && res < size) |
buf[--res] = 0; |
} |
else if (synth) |
res = snprintf(buf, size, "ProgIf %02x", ipif); |
else |
return NULL; |
break; |
default: |
return "<pci_lookup_name: invalid request>"; |
} |
if (res < 0 || res >= size) |
return "<pci_lookup_name: buffer too small>"; |
else |
return buf; |
if (res < 0 || res >= size) |
return "<pci_lookup_name: buffer too small>"; |
else |
return buf; |
} |
/uspace/trunk/pci/libpci/types.h |
---|
27,7 → 27,7 |
#endif |
#endif |
#endif /* PCI_HAVE_Uxx_TYPES */ |
#endif /* PCI_HAVE_Uxx_TYPES */ |
#ifdef PCI_HAVE_64BIT_ADDRESS |
typedef u64 pciaddr_t; |
/uspace/trunk/pci/libpci/generic.c |
---|
12,195 → 12,215 |
#include "internal.h" |
void |
pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus) |
void pci_generic_scan_bus(struct pci_access *a, byte * busmap, int bus) |
{ |
int dev, multi, ht; |
struct pci_dev *t; |
int dev, multi, ht; |
struct pci_dev *t; |
a->debug("Scanning bus %02x for devices...\n", bus); |
if (busmap[bus]) |
{ |
a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus); |
return; |
} |
busmap[bus] = 1; |
t = pci_alloc_dev(a); |
t->bus = bus; |
for(dev=0; dev<32; dev++) |
{ |
t->dev = dev; |
multi = 0; |
for(t->func=0; !t->func || multi && t->func<8; t->func++) |
{ |
u32 vd = pci_read_long(t, PCI_VENDOR_ID); |
struct pci_dev *d; |
a->debug("Scanning bus %02x for devices...\n", bus); |
if (busmap[bus]) { |
a->warning("Bus %02x seen twice (firmware bug). Ignored.", |
bus); |
return; |
} |
busmap[bus] = 1; |
t = pci_alloc_dev(a); |
t->bus = bus; |
for (dev = 0; dev < 32; dev++) { |
t->dev = dev; |
multi = 0; |
for (t->func = 0; !t->func || multi && t->func < 8; |
t->func++) { |
u32 vd = pci_read_long(t, PCI_VENDOR_ID); |
struct pci_dev *d; |
if (!vd || vd == 0xffffffff) |
continue; |
ht = pci_read_byte(t, PCI_HEADER_TYPE); |
if (!t->func) |
multi = ht & 0x80; |
ht &= 0x7f; |
d = pci_alloc_dev(a); |
d->bus = t->bus; |
d->dev = t->dev; |
d->func = t->func; |
d->vendor_id = vd & 0xffff; |
d->device_id = vd >> 16U; |
d->known_fields = PCI_FILL_IDENT; |
d->hdrtype = ht; |
pci_link_dev(a, d); |
switch (ht) |
{ |
case PCI_HEADER_TYPE_NORMAL: |
break; |
case PCI_HEADER_TYPE_BRIDGE: |
case PCI_HEADER_TYPE_CARDBUS: |
pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS)); |
break; |
default: |
a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht); |
} |
if (!vd || vd == 0xffffffff) |
continue; |
ht = pci_read_byte(t, PCI_HEADER_TYPE); |
if (!t->func) |
multi = ht & 0x80; |
ht &= 0x7f; |
d = pci_alloc_dev(a); |
d->bus = t->bus; |
d->dev = t->dev; |
d->func = t->func; |
d->vendor_id = vd & 0xffff; |
d->device_id = vd >> 16U; |
d->known_fields = PCI_FILL_IDENT; |
d->hdrtype = ht; |
pci_link_dev(a, d); |
switch (ht) { |
case PCI_HEADER_TYPE_NORMAL: |
break; |
case PCI_HEADER_TYPE_BRIDGE: |
case PCI_HEADER_TYPE_CARDBUS: |
pci_generic_scan_bus(a, busmap, |
pci_read_byte(t, |
PCI_SECONDARY_BUS)); |
break; |
default: |
a->debug |
("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", |
d->domain, d->bus, d->dev, d->func, |
ht); |
} |
} |
} |
} |
pci_free_dev(t); |
pci_free_dev(t); |
} |
void |
pci_generic_scan(struct pci_access *a) |
void pci_generic_scan(struct pci_access *a) |
{ |
byte busmap[256]; |
byte busmap[256]; |
bzero(busmap, sizeof(busmap)); |
pci_generic_scan_bus(a, busmap, 0); |
bzero(busmap, sizeof(busmap)); |
pci_generic_scan_bus(a, busmap, 0); |
} |
int |
pci_generic_fill_info(struct pci_dev *d, int flags) |
int pci_generic_fill_info(struct pci_dev *d, int flags) |
{ |
struct pci_access *a = d->access; |
struct pci_access *a = d->access; |
if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0) |
d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f; |
if (flags & PCI_FILL_IDENT) |
{ |
d->vendor_id = pci_read_word(d, PCI_VENDOR_ID); |
d->device_id = pci_read_word(d, PCI_DEVICE_ID); |
} |
if (flags & PCI_FILL_IRQ) |
d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE); |
if (flags & PCI_FILL_BASES) |
{ |
int cnt = 0, i; |
bzero(d->base_addr, sizeof(d->base_addr)); |
switch (d->hdrtype) |
{ |
case PCI_HEADER_TYPE_NORMAL: |
cnt = 6; |
break; |
case PCI_HEADER_TYPE_BRIDGE: |
cnt = 2; |
break; |
case PCI_HEADER_TYPE_CARDBUS: |
cnt = 1; |
break; |
if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) |
&& d->hdrtype < 0) |
d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f; |
if (flags & PCI_FILL_IDENT) { |
d->vendor_id = pci_read_word(d, PCI_VENDOR_ID); |
d->device_id = pci_read_word(d, PCI_DEVICE_ID); |
} |
if (cnt) |
{ |
for(i=0; i<cnt; i++) |
{ |
u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4); |
if (!x || x == (u32) ~0) |
continue; |
if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) |
d->base_addr[i] = x; |
else |
{ |
if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64) |
d->base_addr[i] = x; |
else if (i >= cnt-1) |
a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.", d->domain, d->bus, d->dev, d->func, i); |
else |
{ |
u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4); |
if (flags & PCI_FILL_IRQ) |
d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE); |
if (flags & PCI_FILL_BASES) { |
int cnt = 0, i; |
bzero(d->base_addr, sizeof(d->base_addr)); |
switch (d->hdrtype) { |
case PCI_HEADER_TYPE_NORMAL: |
cnt = 6; |
break; |
case PCI_HEADER_TYPE_BRIDGE: |
cnt = 2; |
break; |
case PCI_HEADER_TYPE_CARDBUS: |
cnt = 1; |
break; |
} |
if (cnt) { |
for (i = 0; i < cnt; i++) { |
u32 x = |
pci_read_long(d, |
PCI_BASE_ADDRESS_0 + |
i * 4); |
if (!x || x == (u32) ~ 0) |
continue; |
if ((x & PCI_BASE_ADDRESS_SPACE) == |
PCI_BASE_ADDRESS_SPACE_IO) |
d->base_addr[i] = x; |
else { |
if ((x & |
PCI_BASE_ADDRESS_MEM_TYPE_MASK) |
!= |
PCI_BASE_ADDRESS_MEM_TYPE_64) |
d->base_addr[i] = x; |
else if (i >= cnt - 1) |
a->warning |
("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.", |
d->domain, d->bus, |
d->dev, d->func, i); |
else { |
u32 y = |
pci_read_long(d, |
PCI_BASE_ADDRESS_0 |
+ |
(++i) * |
4); |
#ifdef PCI_HAVE_64BIT_ADDRESS |
d->base_addr[i-1] = x | (((pciaddr_t) y) << 32); |
d->base_addr[i - 1] = |
x | (((pciaddr_t) y) << |
32); |
#else |
if (y) |
a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func); |
else |
d->base_addr[i-1] = x; |
if (y) |
a->warning |
("%04x:%02x:%02x.%d 64-bit device address ignored.", |
d->domain, |
d->bus, |
d->dev, |
d->func); |
else |
d->base_addr[i - |
1] = |
x; |
#endif |
} |
} |
} |
} |
} |
} |
} |
} |
if (flags & PCI_FILL_ROM_BASE) |
{ |
int reg = 0; |
d->rom_base_addr = 0; |
switch (d->hdrtype) |
{ |
case PCI_HEADER_TYPE_NORMAL: |
reg = PCI_ROM_ADDRESS; |
break; |
case PCI_HEADER_TYPE_BRIDGE: |
reg = PCI_ROM_ADDRESS1; |
break; |
if (flags & PCI_FILL_ROM_BASE) { |
int reg = 0; |
d->rom_base_addr = 0; |
switch (d->hdrtype) { |
case PCI_HEADER_TYPE_NORMAL: |
reg = PCI_ROM_ADDRESS; |
break; |
case PCI_HEADER_TYPE_BRIDGE: |
reg = PCI_ROM_ADDRESS1; |
break; |
} |
if (reg) { |
u32 u = pci_read_long(d, reg); |
if (u != 0xffffffff) |
d->rom_base_addr = u; |
} |
} |
if (reg) |
{ |
u32 u = pci_read_long(d, reg); |
if (u != 0xffffffff) |
d->rom_base_addr = u; |
} |
} |
return flags & ~PCI_FILL_SIZES; |
return flags & ~PCI_FILL_SIZES; |
} |
static int |
pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len, |
int (*r)(struct pci_dev *d, int pos, byte *buf, int len)) |
pci_generic_block_op(struct pci_dev *d, int pos, byte * buf, int len, |
int (*r) (struct pci_dev * d, int pos, byte * buf, |
int len)) |
{ |
if ((pos & 1) && len >= 1) |
{ |
if (!r(d, pos, buf, 1)) |
return 0; |
pos++; buf++; len--; |
} |
if ((pos & 3) && len >= 2) |
{ |
if (!r(d, pos, buf, 2)) |
return 0; |
pos += 2; buf += 2; len -= 2; |
} |
while (len >= 4) |
{ |
if (!r(d, pos, buf, 4)) |
return 0; |
pos += 4; buf += 4; len -= 4; |
} |
if (len >= 2) |
{ |
if (!r(d, pos, buf, 2)) |
return 0; |
pos += 2; buf += 2; len -= 2; |
} |
if (len && !r(d, pos, buf, 1)) |
return 0; |
return 1; |
if ((pos & 1) && len >= 1) { |
if (!r(d, pos, buf, 1)) |
return 0; |
pos++; |
buf++; |
len--; |
} |
if ((pos & 3) && len >= 2) { |
if (!r(d, pos, buf, 2)) |
return 0; |
pos += 2; |
buf += 2; |
len -= 2; |
} |
while (len >= 4) { |
if (!r(d, pos, buf, 4)) |
return 0; |
pos += 4; |
buf += 4; |
len -= 4; |
} |
if (len >= 2) { |
if (!r(d, pos, buf, 2)) |
return 0; |
pos += 2; |
buf += 2; |
len -= 2; |
} |
if (len && !r(d, pos, buf, 1)) |
return 0; |
return 1; |
} |
int |
pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len) |
int pci_generic_block_read(struct pci_dev *d, int pos, byte * buf, int len) |
{ |
return pci_generic_block_op(d, pos, buf, len, d->access->methods->read); |
return pci_generic_block_op(d, pos, buf, len, |
d->access->methods->read); |
} |
int |
pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len) |
int pci_generic_block_write(struct pci_dev *d, int pos, byte * buf, int len) |
{ |
return pci_generic_block_op(d, pos, buf, len, d->access->methods->write); |
return pci_generic_block_op(d, pos, buf, len, |
d->access->methods->write); |
} |
/uspace/trunk/pci/libpci/header.h |
---|
33,20 → 33,20 |
#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ |
#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ |
#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ |
#define PCI_STATUS_DEVSEL_FAST 0x000 |
#define PCI_STATUS_DEVSEL_FAST 0x000 |
#define PCI_STATUS_DEVSEL_MEDIUM 0x200 |
#define PCI_STATUS_DEVSEL_SLOW 0x400 |
#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ |
#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ |
#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ |
#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ |
#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ |
#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ |
#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ |
#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ |
#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ |
#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ |
#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 |
revision */ |
#define PCI_REVISION_ID 0x08 /* Revision ID */ |
#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ |
#define PCI_CLASS_DEVICE 0x0a /* Device class */ |
#define PCI_REVISION_ID 0x08 /* Revision ID */ |
#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ |
#define PCI_CLASS_DEVICE 0x0a /* Device class */ |
#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ |
#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ |
87,7 → 87,7 |
/* Header type 0 (normal devices) */ |
#define PCI_CARDBUS_CIS 0x28 |
#define PCI_SUBSYSTEM_VENDOR_ID 0x2c |
#define PCI_SUBSYSTEM_ID 0x2e |
#define PCI_SUBSYSTEM_ID 0x2e |
#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ |
#define PCI_ROM_ADDRESS_ENABLE 0x01 |
#define PCI_ROM_ADDRESS_MASK (~(pciaddr_t)0x7ff) |
135,7 → 135,7 |
#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */ |
#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */ |
#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */ |
#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */ |
#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */ |
#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */ |
#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */ |
185,8 → 185,8 |
#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */ |
#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ |
#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ |
#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ |
#define PCI_CAP_ID_HT 0x08 /* HyperTransport */ |
#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ |
#define PCI_CAP_ID_HT 0x08 /* HyperTransport */ |
#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific */ |
#define PCI_CAP_ID_DBG 0x0A /* Debug port */ |
#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */ |
249,14 → 249,14 |
#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported (8x in AGP3 mode) */ |
#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported (4x in AGP3 mode) */ |
#define PCI_AGP_COMMAND 8 /* Control register */ |
#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */ |
#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */ |
#define PCI_AGP_COMMAND_ARQSZ_MASK 0xe000 /* log2(optimum async req size in bytes) - 4 */ |
#define PCI_AGP_COMMAND_CAL_MASK 0x1c00 /* Calibration cycle timing */ |
#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */ |
#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */ |
#define PCI_AGP_COMMAND_GART64 0x0080 /* 64-bit GART entries enabled */ |
#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow generation of 64-bit addr cycles */ |
#define PCI_AGP_COMMAND_FW 0x0010 /* Enable FW transfers */ |
#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow generation of 64-bit addr cycles */ |
#define PCI_AGP_COMMAND_FW 0x0010 /* Enable FW transfers */ |
#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate (RFU in AGP3 mode) */ |
#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate (8x in AGP3 mode) */ |
#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate (4x in AGP3 mode) */ |
283,52 → 283,52 |
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ |
/* PCI-X */ |
#define PCI_PCIX_COMMAND 2 /* Command register offset */ |
#define PCI_PCIX_COMMAND_DPERE 0x0001 /* Data Parity Error Recover Enable */ |
#define PCI_PCIX_COMMAND_ERO 0x0002 /* Enable Relaxed Ordering */ |
#define PCI_PCIX_COMMAND_MAX_MEM_READ_BYTE_COUNT 0x000c /* Maximum Memory Read Byte Count */ |
#define PCI_PCIX_COMMAND_MAX_OUTSTANDING_SPLIT_TRANS 0x0070 |
#define PCI_PCIX_COMMAND 2 /* Command register offset */ |
#define PCI_PCIX_COMMAND_DPERE 0x0001 /* Data Parity Error Recover Enable */ |
#define PCI_PCIX_COMMAND_ERO 0x0002 /* Enable Relaxed Ordering */ |
#define PCI_PCIX_COMMAND_MAX_MEM_READ_BYTE_COUNT 0x000c /* Maximum Memory Read Byte Count */ |
#define PCI_PCIX_COMMAND_MAX_OUTSTANDING_SPLIT_TRANS 0x0070 |
#define PCI_PCIX_COMMAND_RESERVED 0xf80 |
#define PCI_PCIX_STATUS 4 /* Status register offset */ |
#define PCI_PCIX_STATUS 4 /* Status register offset */ |
#define PCI_PCIX_STATUS_FUNCTION 0x00000007 |
#define PCI_PCIX_STATUS_DEVICE 0x000000f8 |
#define PCI_PCIX_STATUS_BUS 0x0000ff00 |
#define PCI_PCIX_STATUS_64BIT 0x00010000 |
#define PCI_PCIX_STATUS_133MHZ 0x00020000 |
#define PCI_PCIX_STATUS_SC_DISCARDED 0x00040000 /* Split Completion Discarded */ |
#define PCI_PCIX_STATUS_UNEXPECTED_SC 0x00080000 /* Unexpected Split Completion */ |
#define PCI_PCIX_STATUS_DEVICE_COMPLEXITY 0x00100000 /* 0 = simple device, 1 = bridge device */ |
#define PCI_PCIX_STATUS_DESIGNED_MAX_MEM_READ_BYTE_COUNT 0x00600000 /* 0 = 512 bytes, 1 = 1024, 2 = 2048, 3 = 4096 */ |
#define PCI_PCIX_STATUS_SC_DISCARDED 0x00040000 /* Split Completion Discarded */ |
#define PCI_PCIX_STATUS_UNEXPECTED_SC 0x00080000 /* Unexpected Split Completion */ |
#define PCI_PCIX_STATUS_DEVICE_COMPLEXITY 0x00100000 /* 0 = simple device, 1 = bridge device */ |
#define PCI_PCIX_STATUS_DESIGNED_MAX_MEM_READ_BYTE_COUNT 0x00600000 /* 0 = 512 bytes, 1 = 1024, 2 = 2048, 3 = 4096 */ |
#define PCI_PCIX_STATUS_DESIGNED_MAX_OUTSTANDING_SPLIT_TRANS 0x03800000 |
#define PCI_PCIX_STATUS_DESIGNED_MAX_CUMULATIVE_READ_SIZE 0x1c000000 |
#define PCI_PCIX_STATUS_RCVD_SC_ERR_MESS 0x20000000 /* Received Split Completion Error Message */ |
#define PCI_PCIX_STATUS_266MHZ 0x40000000 /* 266 MHz capable */ |
#define PCI_PCIX_STATUS_533MHZ 0x80000000 /* 533 MHz capable */ |
#define PCI_PCIX_STATUS_RCVD_SC_ERR_MESS 0x20000000 /* Received Split Completion Error Message */ |
#define PCI_PCIX_STATUS_266MHZ 0x40000000 /* 266 MHz capable */ |
#define PCI_PCIX_STATUS_533MHZ 0x80000000 /* 533 MHz capable */ |
#define PCI_PCIX_SIZEOF 4 |
/* PCI-X Bridges */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS 2 /* Secondary bus status register offset */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS 2 /* Secondary bus status register offset */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS_64BIT 0x0001 |
#define PCI_PCIX_BRIDGE_SEC_STATUS_133MHZ 0x0002 |
#define PCI_PCIX_BRIDGE_SEC_STATUS_SC_DISCARDED 0x0004 /* Split Completion Discarded on secondary bus */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS_UNEXPECTED_SC 0x0008 /* Unexpected Split Completion on secondary bus */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS_SC_OVERRUN 0x0010 /* Split Completion Overrun on secondary bus */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS_SC_DISCARDED 0x0004 /* Split Completion Discarded on secondary bus */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS_UNEXPECTED_SC 0x0008 /* Unexpected Split Completion on secondary bus */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS_SC_OVERRUN 0x0010 /* Split Completion Overrun on secondary bus */ |
#define PCI_PCIX_BRIDGE_SEC_STATUS_SPLIT_REQUEST_DELAYED 0x0020 |
#define PCI_PCIX_BRIDGE_SEC_STATUS_CLOCK_FREQ 0x01c0 |
#define PCI_PCIX_BRIDGE_SEC_STATUS_RESERVED 0xfe00 |
#define PCI_PCIX_BRIDGE_STATUS 4 /* Primary bus status register offset */ |
#define PCI_PCIX_BRIDGE_STATUS 4 /* Primary bus status register offset */ |
#define PCI_PCIX_BRIDGE_STATUS_FUNCTION 0x00000007 |
#define PCI_PCIX_BRIDGE_STATUS_DEVICE 0x000000f8 |
#define PCI_PCIX_BRIDGE_STATUS_BUS 0x0000ff00 |
#define PCI_PCIX_BRIDGE_STATUS_64BIT 0x00010000 |
#define PCI_PCIX_BRIDGE_STATUS_133MHZ 0x00020000 |
#define PCI_PCIX_BRIDGE_STATUS_SC_DISCARDED 0x00040000 /* Split Completion Discarded */ |
#define PCI_PCIX_BRIDGE_STATUS_UNEXPECTED_SC 0x00080000 /* Unexpected Split Completion */ |
#define PCI_PCIX_BRIDGE_STATUS_SC_OVERRUN 0x00100000 /* Split Completion Overrun */ |
#define PCI_PCIX_BRIDGE_STATUS_SC_DISCARDED 0x00040000 /* Split Completion Discarded */ |
#define PCI_PCIX_BRIDGE_STATUS_UNEXPECTED_SC 0x00080000 /* Unexpected Split Completion */ |
#define PCI_PCIX_BRIDGE_STATUS_SC_OVERRUN 0x00100000 /* Split Completion Overrun */ |
#define PCI_PCIX_BRIDGE_STATUS_SPLIT_REQUEST_DELAYED 0x00200000 |
#define PCI_PCIX_BRIDGE_STATUS_RESERVED 0xffc00000 |
#define PCI_PCIX_BRIDGE_UPSTREAM_SPLIT_TRANS_CTRL 8 /* Upstream Split Transaction Register offset */ |
#define PCI_PCIX_BRIDGE_DOWNSTREAM_SPLIT_TRANS_CTRL 12 /* Downstream Split Transaction Register offset */ |
#define PCI_PCIX_BRIDGE_UPSTREAM_SPLIT_TRANS_CTRL 8 /* Upstream Split Transaction Register offset */ |
#define PCI_PCIX_BRIDGE_DOWNSTREAM_SPLIT_TRANS_CTRL 12 /* Downstream Split Transaction Register offset */ |
#define PCI_PCIX_BRIDGE_STR_CAPACITY 0x0000ffff |
#define PCI_PCIX_BRIDGE_STR_COMMITMENT_LIMIT 0xffff0000 |
#define PCI_PCIX_BRIDGE_SIZEOF 12 |
501,14 → 501,14 |
#define PCI_HT_SW_CMD_VIBNFT 0x0400 /* VIB Nonfatal */ |
#define PCI_HT_SW_PMASK 4 /* Partition Mask Register */ |
#define PCI_HT_SW_SWINF 8 /* Switch Info Register */ |
#define PCI_HT_SW_SWINF_DP 0x0000001f /* Default Port */ |
#define PCI_HT_SW_SWINF_EN 0x00000020 /* Enable Decode */ |
#define PCI_HT_SW_SWINF_CR 0x00000040 /* Cold Reset */ |
#define PCI_HT_SW_SWINF_PCIDX 0x00000f00 /* Performance Counter Index */ |
#define PCI_HT_SW_SWINF_BLRIDX 0x0003f000 /* Base/Limit Range Index */ |
#define PCI_HT_SW_SWINF_SBIDX 0x00002000 /* Secondary Base Range Index */ |
#define PCI_HT_SW_SWINF_HP 0x00040000 /* Hot Plug */ |
#define PCI_HT_SW_SWINF_HIDE 0x00080000 /* Hide Port */ |
#define PCI_HT_SW_SWINF_DP 0x0000001f /* Default Port */ |
#define PCI_HT_SW_SWINF_EN 0x00000020 /* Enable Decode */ |
#define PCI_HT_SW_SWINF_CR 0x00000040 /* Cold Reset */ |
#define PCI_HT_SW_SWINF_PCIDX 0x00000f00 /* Performance Counter Index */ |
#define PCI_HT_SW_SWINF_BLRIDX 0x0003f000 /* Base/Limit Range Index */ |
#define PCI_HT_SW_SWINF_SBIDX 0x00002000 /* Secondary Base Range Index */ |
#define PCI_HT_SW_SWINF_HP 0x00040000 /* Hot Plug */ |
#define PCI_HT_SW_SWINF_HIDE 0x00080000 /* Hide Port */ |
#define PCI_HT_SW_PCD 12 /* Performance Counter Data Register */ |
#define PCI_HT_SW_BLRD 16 /* Base/Limit Range Data Register */ |
#define PCI_HT_SW_SBD 20 /* Secondary Base Data Register */ |
545,19 → 545,19 |
/* Register indices */ |
#define PCI_HT_IDC_IDX_LINT 0x01 /* Last Interrupt Register */ |
#define PCI_HT_IDC_LINT 0x00ff0000 /* Last interrupt definition */ |
#define PCI_HT_IDC_LINT 0x00ff0000 /* Last interrupt definition */ |
#define PCI_HT_IDC_IDX_IDR 0x10 /* Interrupt Definition Registers */ |
/* Low part (at index) */ |
#define PCI_HT_IDC_IDR_MASK 0x10000001 /* Mask */ |
#define PCI_HT_IDC_IDR_POL 0x10000002 /* Polarity */ |
#define PCI_HT_IDC_IDR_II_2 0x1000001c /* IntrInfo[4:2]: Message Type */ |
#define PCI_HT_IDC_IDR_II_5 0x10000020 /* IntrInfo[5]: Request EOI */ |
#define PCI_HT_IDC_IDR_II_6 0x00ffffc0 /* IntrInfo[23:6] */ |
#define PCI_HT_IDC_IDR_II_24 0xff000000 /* IntrInfo[31:24] */ |
#define PCI_HT_IDC_IDR_MASK 0x10000001 /* Mask */ |
#define PCI_HT_IDC_IDR_POL 0x10000002 /* Polarity */ |
#define PCI_HT_IDC_IDR_II_2 0x1000001c /* IntrInfo[4:2]: Message Type */ |
#define PCI_HT_IDC_IDR_II_5 0x10000020 /* IntrInfo[5]: Request EOI */ |
#define PCI_HT_IDC_IDR_II_6 0x00ffffc0 /* IntrInfo[23:6] */ |
#define PCI_HT_IDC_IDR_II_24 0xff000000 /* IntrInfo[31:24] */ |
/* High part (at index + 1) */ |
#define PCI_HT_IDC_IDR_II_32 0x00ffffff /* IntrInfo[55:32] */ |
#define PCI_HT_IDC_IDR_PASSPW 0x40000000 /* PassPW setting for messages */ |
#define PCI_HT_IDC_IDR_WEOI 0x80000000 /* Waiting for EOI */ |
#define PCI_HT_IDC_IDR_II_32 0x00ffffff /* IntrInfo[55:32] */ |
#define PCI_HT_IDC_IDR_PASSPW 0x40000000 /* PassPW setting for messages */ |
#define PCI_HT_IDC_IDR_WEOI 0x80000000 /* Waiting for EOI */ |
/* HyperTransport: Revision ID */ |
#define PCI_HT_RID_RID 2 /* Revision Register */ |
570,11 → 570,11 |
/* HyperTransport: Extended Configuration Space Access */ |
#define PCI_HT_ECSA_ADDR 4 /* Configuration Address Register */ |
#define PCI_HT_ECSA_ADDR_REG 0x00000ffc /* Register */ |
#define PCI_HT_ECSA_ADDR_FUN 0x00007000 /* Function */ |
#define PCI_HT_ECSA_ADDR_DEV 0x000f1000 /* Device */ |
#define PCI_HT_ECSA_ADDR_BUS 0x0ff00000 /* Bus Number */ |
#define PCI_HT_ECSA_ADDR_TYPE 0x10000000 /* Access Type */ |
#define PCI_HT_ECSA_ADDR_REG 0x00000ffc /* Register */ |
#define PCI_HT_ECSA_ADDR_FUN 0x00007000 /* Function */ |
#define PCI_HT_ECSA_ADDR_DEV 0x000f1000 /* Device */ |
#define PCI_HT_ECSA_ADDR_BUS 0x0ff00000 /* Bus Number */ |
#define PCI_HT_ECSA_ADDR_TYPE 0x10000000 /* Access Type */ |
#define PCI_HT_ECSA_DATA 8 /* Configuration Data Register */ |
#define PCI_HT_ECSA_SIZEOF 12 |
594,8 → 594,8 |
/* HyperTransport: 40-bit Address Mapping */ |
#define PCI_HT_AM40_SBNPW 4 /* Secondary Bus Non-Prefetchable Window Register */ |
#define PCI_HT_AM40_SBW_BASE 0x000fffff /* Window Base */ |
#define PCI_HT_AM40_SBW_CTR 0xf0000000 /* Window Control */ |
#define PCI_HT_AM40_SBW_BASE 0x000fffff /* Window Base */ |
#define PCI_HT_AM40_SBW_CTR 0xf0000000 /* Window Control */ |
#define PCI_HT_AM40_SBPW 8 /* Secondary Bus Prefetchable Window Register */ |
#define PCI_HT_AM40_DMA_PBASE0 12 /* DMA Window Primary Base 0 Register */ |
#define PCI_HT_AM40_DMA_CTR0 15 /* DMA Window Control 0 Register */ |
612,8 → 612,8 |
/* Register indices */ |
#define PCI_HT_AM64_IDX_SBNPW 0x00 /* Secondary Bus Non-Prefetchable Window Register */ |
#define PCI_HT_AM64_W_BASE_LO 0xfff00000 /* Window Base Lower */ |
#define PCI_HT_AM64_W_CTR 0x0000000f /* Window Control */ |
#define PCI_HT_AM64_W_BASE_LO 0xfff00000 /* Window Base Lower */ |
#define PCI_HT_AM64_W_CTR 0x0000000f /* Window Control */ |
#define PCI_HT_AM64_IDX_SBPW 0x01 /* Secondary Bus Prefetchable Window Register */ |
#define PCI_HT_AM64_IDX_PBNPW 0x02 /* Primary Bus Non-Prefetchable Window Register */ |
#define PCI_HT_AM64_IDX_DMAPB0 0x04 /* DMA Window Primary Base 0 Register */ |
638,8 → 638,8 |
/* Register indices */ |
#define PCI_HT_DR_IDX_BASE_LO 0x00 /* DirectRoute Base Lower Register */ |
#define PCI_HT_DR_OTNRD 0x00000001 /* Opposite to Normal Request Direction */ |
#define PCI_HT_DR_BL_LO 0xffffff00 /* Base/Limit Lower */ |
#define PCI_HT_DR_OTNRD 0x00000001 /* Opposite to Normal Request Direction */ |
#define PCI_HT_DR_BL_LO 0xffffff00 /* Base/Limit Lower */ |
#define PCI_HT_DR_IDX_BASE_HI 0x01 /* DirectRoute Base Upper Register */ |
#define PCI_HT_DR_IDX_LIMIT_LO 0x02 /* DirectRoute Limit Lower Register */ |
#define PCI_HT_DR_IDX_LIMIT_HI 0x03 /* DirectRoute Limit Upper Register */ |
698,8 → 698,8 |
#define PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */ |
#define PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */ |
#define PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */ |
#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ |
#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ |
#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */ |
#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */ |
#define PCI_EXP_DEVCTL 0x8 /* Device Control */ |
#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ |
#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ |
725,7 → 725,7 |
#define PCI_EXP_LNKCAP_ASPM 0x00c00 /* Active State Power Management */ |
#define PCI_EXP_LNKCAP_L0S 0x07000 /* L0s Acceptable Latency */ |
#define PCI_EXP_LNKCAP_L1 0x38000 /* L1 Acceptable Latency */ |
#define PCI_EXP_LNKCAP_PORT 0xff000000 /* Port Number */ |
#define PCI_EXP_LNKCAP_PORT 0xff000000 /* Port Number */ |
#define PCI_EXP_LNKCTL 0x10 /* Link Control */ |
#define PCI_EXP_LNKCTL_ASPM 0x0003 /* ASPM Control */ |
#define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */ |
747,9 → 747,9 |
#define PCI_EXP_SLTCAP_PWRI 0x0010 /* Power Indicator Present */ |
#define PCI_EXP_SLTCAP_HPS 0x0020 /* Hot-Plug Surprise */ |
#define PCI_EXP_SLTCAP_HPC 0x0040 /* Hot-Plug Capable */ |
#define PCI_EXP_SLTCAP_PWR_VAL 0x00007f80 /* Slot Power Limit Value */ |
#define PCI_EXP_SLTCAP_PWR_SCL 0x00018000 /* Slot Power Limit Scale */ |
#define PCI_EXP_SLTCAP_PSN 0xfff80000 /* Physical Slot Number */ |
#define PCI_EXP_SLTCAP_PWR_VAL 0x00007f80 /* Slot Power Limit Value */ |
#define PCI_EXP_SLTCAP_PWR_SCL 0x00018000 /* Slot Power Limit Scale */ |
#define PCI_EXP_SLTCAP_PSN 0xfff80000 /* Physical Slot Number */ |
#define PCI_EXP_SLTCTL 0x18 /* Slot Control */ |
#define PCI_EXP_SLTCTL_ATNB 0x0001 /* Attention Button Pressed Enable */ |
#define PCI_EXP_SLTCTL_PWRF 0x0002 /* Power Fault Detected Enable */ |
825,12 → 825,12 |
/* Power Budgeting */ |
#define PCI_PWR_DSR 4 /* Data Select Register */ |
#define PCI_PWR_DATA 8 /* Data Register */ |
#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */ |
#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */ |
#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */ |
#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */ |
#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */ |
#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ |
#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */ |
#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */ |
#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */ |
#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */ |
#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */ |
#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */ |
#define PCI_PWR_CAP 12 /* Capability */ |
#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ |