From: Lionel Sambuc Date: Tue, 14 Oct 2014 19:38:39 +0000 (+0200) Subject: PCI driver cleanup X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/man.named.html?a=commitdiff_plain;h=6e7bb628533a753e81d9db8e675d04cc02ff2532;p=minix.git PCI driver cleanup - Moved to KNF - Whitespace cleanup - Removed useless static functions prototypes - Renamed some file private functions by prepending '__' - Renamed some server-specific function by prepending '_' - Fixed compilation warning for WARNS= 3 Change-Id: Ie44d35839177d5ee0630cdf576660c852452ab80 --- diff --git a/minix/drivers/bus/pci/Makefile b/minix/drivers/bus/pci/Makefile index 50af8a580..d1e4cf882 100644 --- a/minix/drivers/bus/pci/Makefile +++ b/minix/drivers/bus/pci/Makefile @@ -5,4 +5,6 @@ SRCS= main.c pci.c pci_table.c DPADD+= ${LIBSYS} ${LIBTIMERS} LDADD+= -lsys -ltimers +WARNS?= 3 + .include diff --git a/minix/drivers/bus/pci/main.c b/minix/drivers/bus/pci/main.c index 1e76f02ce..780029021 100644 --- a/minix/drivers/bus/pci/main.c +++ b/minix/drivers/bus/pci/main.c @@ -1,96 +1,13 @@ -/* -main.c -*/ +#include +#include #include "pci.h" +int debug = 0; struct pci_acl pci_acl[NR_DRIVERS]; -static void do_init(message *mp); -static void do_first_dev(message *mp); -static void do_next_dev(message *mp); -static void do_find_dev(message *mp); -static void do_ids(message *mp); -static void do_dev_name_s(message *mp); -static void do_slot_name_s(message *mp); -static void do_set_acl(message *mp); -static void do_del_acl(message *mp); -static void do_reserve(message *mp); -static void do_attr_r8(message *mp); -static void do_attr_r16(message *mp); -static void do_attr_r32(message *mp); -static void do_attr_w8(message *mp); -static void do_attr_w16(message *mp); -static void do_attr_w32(message *mp); -static void do_get_bar(message *mp); -static void do_rescan_bus(message *mp); -static void reply(message *mp, int result); -static struct rs_pci *find_acl(int endpoint); - -extern int debug; - -/* SEF functions and variables. */ -static void sef_local_startup(void); - -int main(void) -{ - int r; - message m; - int ipc_status; - - /* SEF local startup. */ - sef_local_startup(); - - for(;;) - { - r= driver_receive(ANY, &m, &ipc_status); - if (r < 0) - { - printf("PCI: driver_receive failed: %d\n", r); - break; - } - - if (is_ipc_notify(ipc_status)) { - printf("PCI: got notify from %d\n", m.m_source); - - /* done, get a new message */ - continue; - } - - switch(m.m_type) - { - case BUSC_PCI_INIT: do_init(&m); break; - case BUSC_PCI_FIRST_DEV: do_first_dev(&m); break; - case BUSC_PCI_NEXT_DEV: do_next_dev(&m); break; - case BUSC_PCI_FIND_DEV: do_find_dev(&m); break; - case BUSC_PCI_IDS: do_ids(&m); break; - case BUSC_PCI_RESERVE: do_reserve(&m); break; - case BUSC_PCI_ATTR_R8: do_attr_r8(&m); break; - case BUSC_PCI_ATTR_R16: do_attr_r16(&m); break; - case BUSC_PCI_ATTR_R32: do_attr_r32(&m); break; - case BUSC_PCI_ATTR_W8: do_attr_w8(&m); break; - case BUSC_PCI_ATTR_W16: do_attr_w16(&m); break; - case BUSC_PCI_ATTR_W32: do_attr_w32(&m); break; - case BUSC_PCI_RESCAN: do_rescan_bus(&m); break; - case BUSC_PCI_DEV_NAME_S: do_dev_name_s(&m); break; - case BUSC_PCI_SLOT_NAME_S: do_slot_name_s(&m); break; - case BUSC_PCI_SET_ACL: do_set_acl(&m); break; - case BUSC_PCI_DEL_ACL: do_del_acl(&m); break; - case BUSC_PCI_GET_BAR: do_get_bar(&m); break; - default: - printf("PCI: got message from %d, type %d\n", - m.m_source, m.m_type); - break; - } - } - - return 0; -} - -/*===========================================================================* - * sef_local_startup * - *===========================================================================*/ -static void sef_local_startup() +static void +sef_local_startup() { /* Register init callbacks. */ sef_setcb_init_fresh(sef_cb_init_fresh); @@ -105,8 +22,37 @@ static void sef_local_startup() sef_startup(); } -static void do_init(mp) -message *mp; +static struct rs_pci * +find_acl(int endpoint) +{ + int i; + + /* Find ACL entry for caller */ + for (i= 0; im_source, &m); + if (r != 0) + printf("reply: unable to send to %d: %d\n", mp->m_source, r); +} + + +static void +do_init(message *mp) { int r; @@ -121,7 +67,8 @@ message *mp; mp->m_source, r); } -static void do_first_dev(message *mp) +static void +do_first_dev(message *mp) { int r, devind; u16_t vid, did; @@ -133,7 +80,7 @@ static void do_first_dev(message *mp) printf("PCI: do_first_dev: no acl for caller %d\n", mp->m_source); - r= pci_first_dev_a(aclp, &devind, &vid, &did); + r= _pci_first_dev(aclp, &devind, &vid, &did); if (r == 1) { mp->m1_i1= devind; @@ -149,7 +96,8 @@ static void do_first_dev(message *mp) } } -static void do_next_dev(message *mp) +static void +do_next_dev(message *mp) { int r, devind; u16_t vid, did; @@ -158,7 +106,7 @@ static void do_next_dev(message *mp) devind= mp->m1_i1; aclp= find_acl(mp->m_source); - r= pci_next_dev_a(aclp, &devind, &vid, &did); + r= _pci_next_dev(aclp, &devind, &vid, &did); if (r == 1) { mp->m1_i1= devind; @@ -174,8 +122,8 @@ static void do_next_dev(message *mp) } } -static void do_find_dev(mp) -message *mp; +static void +do_find_dev(message *mp) { int r, devind; u8_t bus, dev, func; @@ -184,7 +132,7 @@ message *mp; dev= mp->m1_i2; func= mp->m1_i3; - r= pci_find_dev(bus, dev, func, &devind); + r= _pci_find_dev(bus, dev, func, &devind); if (r == 1) mp->m1_i1= devind; mp->m_type= r; @@ -196,15 +144,15 @@ message *mp; } } -static void do_ids(mp) -message *mp; +static void +do_ids(message *mp) { int r, devind; u16_t vid, did; devind= mp->m1_i1; - r= pci_ids_s(devind, &vid, &did); + r= _pci_ids(devind, &vid, &did); if (r != OK) { printf("pci:do_ids: failed for devind %d: %d\n", @@ -222,20 +170,20 @@ message *mp; } } -static void do_dev_name_s(mp) -message *mp; +static void +do_dev_name(message *mp) { int r, name_len, len; u16_t vid, did; cp_grant_id_t name_gid; - char *name; + const char *name; vid= mp->m7_i1; did= mp->m7_i2; name_len= mp->m7_i3; name_gid= mp->m7_i4; - name= pci_dev_name(vid, did); + name= _pci_dev_name(vid, did); if (name == NULL) { /* No name */ @@ -259,8 +207,8 @@ message *mp; } } -static void do_slot_name_s(mp) -message *mp; +static void +do_slot_name(message *mp) { int r, devind, name_len, len; cp_grant_id_t gid; @@ -270,7 +218,7 @@ message *mp; name_len= mp->m1_i2; gid= mp->m1_i3; - r= pci_slot_name_s(devind, &name); + r= _pci_slot_name(devind, &name); if (r != OK) { printf("pci:do_slot_name_s: failed for devind %d: %d\n", @@ -295,8 +243,8 @@ message *mp; } } -static void do_set_acl(mp) -message *mp; +static void +do_set_acl(message *mp) { int i, r, gid; @@ -338,7 +286,8 @@ message *mp; reply(mp, OK); } -static void do_del_acl(message *mp) +static void +do_del_acl(message *mp) { int i, proc_nr; @@ -373,12 +322,13 @@ static void do_del_acl(message *mp) #endif /* Also release all devices held by this process */ - pci_release(proc_nr); + _pci_release(proc_nr); reply(mp, OK); } -static void do_reserve(message *mp) +static void +do_reserve(message *mp) { struct rs_pci *aclp; int r, devind; @@ -387,7 +337,7 @@ static void do_reserve(message *mp) aclp= find_acl(mp->m_source); - mp->m_type= pci_reserve_a(devind, mp->m_source, aclp); + mp->m_type= _pci_reserve(devind, mp->m_source, aclp); r= ipc_send(mp->m_source, mp); if (r != 0) { @@ -396,8 +346,8 @@ static void do_reserve(message *mp) } } -static void do_attr_r8(mp) -message *mp; +static void +do_attr_r8(message *mp) { int r, devind, port; u8_t v; @@ -405,11 +355,11 @@ message *mp; devind= mp->m2_i1; port= mp->m2_i2; - r= pci_attr_r8_s(devind, port, &v); + r= _pci_attr_r8(devind, port, &v); if (r != OK) { printf( - "pci:do_attr_r8: pci_attr_r8_s(%d, %d, ...) failed: %d\n", + "pci:do_attr_r8: pci_attr_r8(%d, %d, ...) failed: %d\n", devind, port, r); } mp->m2_l1= v; @@ -422,16 +372,22 @@ message *mp; } } -static void do_attr_r16(mp) -message *mp; +static void +do_attr_r16(message *mp) { int r, devind, port; - u32_t v; + u16_t v; devind= mp->m2_i1; port= mp->m2_i2; - v= pci_attr_r16(devind, port); + r= _pci_attr_r16(devind, port, &v); + if (r != OK) + { + printf( + "pci:do_attr_r16: pci_attr_r16(%d, %d, ...) failed: %d\n", + devind, port, r); + } mp->m2_l1= v; mp->m_type= OK; r= ipc_send(mp->m_source, mp); @@ -442,8 +398,8 @@ message *mp; } } -static void do_attr_r32(mp) -message *mp; +static void +do_attr_r32(message *mp) { int r, devind, port; u32_t v; @@ -451,11 +407,11 @@ message *mp; devind= mp->m2_i1; port= mp->m2_i2; - r= pci_attr_r32_s(devind, port, &v); + r= _pci_attr_r32(devind, port, &v); if (r != OK) { printf( - "pci:do_attr_r32: pci_attr_r32_s(%d, %d, ...) failed: %d\n", + "pci:do_attr_r32: pci_attr_r32(%d, %d, ...) failed: %d\n", devind, port, r); } mp->m2_l1= v; @@ -468,8 +424,8 @@ message *mp; } } -static void do_attr_w8(mp) -message *mp; +static void +do_attr_w8(message *mp) { int r, devind, port; u8_t v; @@ -478,7 +434,7 @@ message *mp; port= mp->m2_i2; v= mp->m2_l1; - pci_attr_w8(devind, port, v); + _pci_attr_w8(devind, port, v); mp->m_type= OK; r= ipc_send(mp->m_source, mp); if (r != 0) @@ -488,8 +444,8 @@ message *mp; } } -static void do_attr_w16(mp) -message *mp; +static void +do_attr_w16(message *mp) { int r, devind, port; u16_t v; @@ -498,7 +454,7 @@ message *mp; port= mp->m2_i2; v= mp->m2_l1; - pci_attr_w16(devind, port, v); + _pci_attr_w16(devind, port, v); mp->m_type= OK; r= ipc_send(mp->m_source, mp); if (r != 0) @@ -508,8 +464,8 @@ message *mp; } } -static void do_attr_w32(mp) -message *mp; +static void +do_attr_w32(message *mp) { int r, devind, port; u32_t v; @@ -518,7 +474,7 @@ message *mp; port= mp->m2_i2; v= mp->m2_l1; - pci_attr_w32(devind, port, v); + _pci_attr_w32(devind, port, v); mp->m_type= OK; r= ipc_send(mp->m_source, mp); if (r != 0) @@ -528,8 +484,8 @@ message *mp; } } -static void do_get_bar(mp) -message *mp; +static void +do_get_bar(message *mp) { int r, devind, port, ioflag; u32_t base, size; @@ -537,7 +493,7 @@ message *mp; devind= mp->m_lsys_pci_busc_get_bar.devind; port= mp->m_lsys_pci_busc_get_bar.port; - mp->m_type= pci_get_bar_s(devind, port, &base, &size, &ioflag); + mp->m_type= _pci_get_bar(devind, port, &base, &size, &ioflag); if (mp->m_type == OK) { @@ -554,14 +510,14 @@ message *mp; } } -static void do_rescan_bus(mp) -message *mp; +static void +do_rescan_bus(message *mp) { int r, busnr; busnr= mp->m2_i1; - pci_rescan_bus(busnr); + _pci_rescan_bus(busnr); mp->m_type= OK; r= ipc_send(mp->m_source, mp); if (r != 0) @@ -571,33 +527,58 @@ message *mp; } } - -static void reply(mp, result) -message *mp; -int result; +int +main(void) { int r; message m; + int ipc_status; - m.m_type= result; - r= ipc_send(mp->m_source, &m); - if (r != 0) - printf("reply: unable to send to %d: %d\n", mp->m_source, r); -} + /* SEF local startup. */ + sef_local_startup(); + for(;;) + { + r= driver_receive(ANY, &m, &ipc_status); + if (r < 0) + { + printf("PCI: driver_receive failed: %d\n", r); + break; + } -static struct rs_pci *find_acl(endpoint) -int endpoint; -{ - int i; + if (is_ipc_notify(ipc_status)) { + printf("PCI: got notify from %d\n", m.m_source); - /* Find ACL entry for caller */ - for (i= 0; i */ -#include -#include -#include -#include -#include -#include -#include +#include + +#include #include +#include +#include -#include "pci.h" +#include #include #include #include #include -#if __minix_vmd -#include "config.h" -#endif - -#if !__minix_vmd -#define irq_mode_pci(irq) ((void)0) -#endif +#include #include #include -#include -#include + +#include "pci.h" + +#define irq_mode_pci(irq) ((void)0) #define PBT_INTEL_HOST 1 #define PBT_PCIBRIDGE 2 @@ -39,7 +33,7 @@ Created: Jan 2000 by Philip Homburg #define BAM_NR 6 /* Number of base-address registers */ -int debug= 0; +struct pci_acl pci_acl[NR_DRIVERS]; static struct pcibus { @@ -88,1189 +82,986 @@ static struct pcidev int pd_bar_nr; } pcidev[NR_PCIDEV]; -EXTERN struct pci_acl pci_acl[NR_DRIVERS]; - /* pb_flags */ #define PBF_IO 1 /* I/O else memory */ #define PBF_INCOMPLETE 2 /* not allocated */ static int nr_pcidev= 0; -static void pci_intel_init(void); -static void probe_bus(int busind); -static int is_duplicate(u8_t busnr, u8_t dev, u8_t func); -static void record_irq(int devind); -static void record_bars_normal(int devind); -static void record_bars_bridge(int devind); -static void record_bars_cardbus(int devind); -static void record_bars(int devind, int last_reg); -static int record_bar(int devind, int bar_nr, int last); -static void complete_bridges(void); -static void complete_bars(void); -static void update_bridge4dev_io(int devind, u32_t io_base, u32_t - io_size); -static int get_freebus(void); -static int do_isabridge(int busind); -static void do_pcibridge(int busind); -static int get_busind(int busnr); -static int do_piix(int devind); -static int do_amd_isabr(int devind); -static int do_sis_isabr(int devind); -static int do_via_isabr(int devind); -#if 0 -static void report_vga(int devind); -#endif -static char *pci_vid_name(u16_t vid); -static char *pci_baseclass_name(u8_t baseclass); -static char *pci_subclass_name(u8_t baseclass, u8_t subclass, u8_t - infclass); -static void ntostr(unsigned n, char **str, const char *end); - -static u8_t pci_attr_r8_u(int devind, int port); -static u32_t pci_attr_r32_u(int devind, int port); - -static u16_t pci_attr_rsts(int devind); -static void pci_attr_wsts(int devind, u16_t value); -static u16_t pcibr_std_rsts(int busind); -static void pcibr_std_wsts(int busind, u16_t value); -static u16_t pcibr_cb_rsts(int busind); -static void pcibr_cb_wsts(int busind, u16_t value); -static u16_t pcibr_via_rsts(int busind); -static void pcibr_via_wsts(int busind, u16_t value); -static u8_t pcii_rreg8(int busind, int devind, int port); -static u16_t pcii_rreg16(int busind, int devind, int port); -static u32_t pcii_rreg32(int busind, int devind, int port); -static void pcii_wreg8(int busind, int devind, int port, u8_t value); -static void pcii_wreg16(int busind, int devind, int port, u16_t value); -static void pcii_wreg32(int busind, int devind, int port, u32_t value); -static u16_t pcii_rsts(int busind); -static void pcii_wsts(int busind, u16_t value); -static void print_capabilities(int devind); -static int visible(struct rs_pci *aclp, int devind); -static void print_hyper_cap(int devind, u8_t capptr); - static struct machine machine; static endpoint_t acpi_ep; -/*===========================================================================* - * sef_cb_init_fresh * - *===========================================================================*/ -int sef_cb_init_fresh(int type, sef_init_info_t *info) -{ -/* Initialize the pci driver. */ - long v; - int i, r; - struct rprocpub rprocpub[NR_BOOT_PROCS]; - - v= 0; - env_parse("pci_debug", "d", 0, &v, 0, 1); - debug= v; - - if (sys_getmachine(&machine)) { - printf("PCI: no machine\n"); - return ENODEV; - } - if (machine.apic_enabled && - ds_retrieve_label_endpt("acpi", &acpi_ep) != OK) { - panic("PCI: Cannot use APIC mode without ACPI!\n"); - } - - /* Only Intel (compatible) PCI controllers are supported at the - * moment. - */ - pci_intel_init(); - - /* Map all the services in the boot image. */ - if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, - (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) { - panic("sys_safecopyfrom failed: %d", r); - } - for(i=0;i < NR_BOOT_PROCS;i++) { - if(rprocpub[i].in_use) { - if((r = map_service(&rprocpub[i])) != OK) { - panic("unable to map service: %d", r); - } - } - } - - return(OK); -} - -/*===========================================================================* - * map_service * - *===========================================================================*/ -int map_service(rpub) -struct rprocpub *rpub; -{ -/* Map a new service by registering a new acl entry if required. */ - int i; - - /* Stop right now if no pci device or class is found. */ - if(rpub->pci_acl.rsp_nr_device == 0 - && rpub->pci_acl.rsp_nr_class == 0) { - return(OK); - } - - /* Find a free acl slot. */ - for (i= 0; i= NR_DRIVERS) - { - printf("PCI: map_service: table is full\n"); - return ENOMEM; - } - - /* Initialize acl slot. */ - pci_acl[i].inuse = 1; - pci_acl[i].acl = rpub->pci_acl; - - return(OK); -} - /*===========================================================================* * helper functions for I/O * *===========================================================================*/ -unsigned pci_inb(u16_t port) { +static unsigned +pci_inb(u16_t port) { u32_t value; int s; if ((s=sys_inb(port, &value)) !=OK) printf("PCI: warning, sys_inb failed: %d\n", s); return value; } -unsigned pci_inw(u16_t port) { + +static unsigned +pci_inw(u16_t port) { u32_t value; int s; if ((s=sys_inw(port, &value)) !=OK) printf("PCI: warning, sys_inw failed: %d\n", s); return value; } -unsigned pci_inl(u16_t port) { + +static unsigned +pci_inl(u16_t port) { u32_t value; int s; if ((s=sys_inl(port, &value)) !=OK) printf("PCI: warning, sys_inl failed: %d\n", s); return value; } -void pci_outb(u16_t port, u8_t value) { + +static void +pci_outb(u16_t port, u8_t value) { int s; if ((s=sys_outb(port, value)) !=OK) printf("PCI: warning, sys_outb failed: %d\n", s); } -void pci_outw(u16_t port, u16_t value) { + +static void +pci_outw(u16_t port, u16_t value) { int s; if ((s=sys_outw(port, value)) !=OK) printf("PCI: warning, sys_outw failed: %d\n", s); } -void pci_outl(u16_t port, u32_t value) { + +static void +pci_outl(u16_t port, u32_t value) { int s; if ((s=sys_outl(port, value)) !=OK) printf("PCI: warning, sys_outl failed: %d\n", s); } -/*===========================================================================* - * pci_find_dev * - *===========================================================================*/ -int pci_find_dev(u8_t bus, u8_t dev, u8_t func, int *devindp) +static u8_t +pcii_rreg8(int busind, int devind, int port) { - int devind; + u8_t v; + int s; - for (devind= 0; devind < nr_pcidev; devind++) - { - if (pcidev[devind].pd_busnr == bus && - pcidev[devind].pd_dev == dev && - pcidev[devind].pd_func == func) - { - break; - } - } - if (devind >= nr_pcidev) - return 0; + v= PCII_RREG8_(pcibus[busind].pb_busnr, + pcidev[devind].pd_dev, pcidev[devind].pd_func, + port); + if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) + printf("PCI: warning, sys_outl failed: %d\n", s); #if 0 - if (pcidev[devind].pd_inuse) - return 0; + printf("pcii_rreg8(%d, %d, 0x%X): %d.%d.%d= 0x%X\n", + busind, devind, port, + pcibus[busind].pb_bus, pcidev[devind].pd_dev, + pcidev[devind].pd_func, v); #endif - *devindp= devind; - return 1; + return v; } -/*===========================================================================* - * pci_first_dev_a * - *===========================================================================*/ -int pci_first_dev_a( - struct rs_pci *aclp, - int *devindp, - u16_t *vidp, - u16_t *didp -) +static u16_t +pcii_rreg16(int busind, int devind, int port) { - int devind; + u16_t v; + int s; - for (devind= 0; devind < nr_pcidev; devind++) - { + v= PCII_RREG16_(pcibus[busind].pb_busnr, + pcidev[devind].pd_dev, pcidev[devind].pd_func, + port); + if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) + printf("PCI: warning, sys_outl failed: %d\n", s); #if 0 - if (pcidev[devind].pd_inuse) - continue; + printf("pcii_rreg16(%d, %d, 0x%X): %d.%d.%d= 0x%X\n", + busind, devind, port, + pcibus[busind].pb_bus, pcidev[devind].pd_dev, + pcidev[devind].pd_func, v); #endif - if (!visible(aclp, devind)) - continue; - break; - } - if (devind >= nr_pcidev) - return 0; - *devindp= devind; - *vidp= pcidev[devind].pd_vid; - *didp= pcidev[devind].pd_did; - return 1; + return v; } -/*===========================================================================* - * pci_next_dev * - *===========================================================================*/ -int pci_next_dev_a( - struct rs_pci *aclp, - int *devindp, - u16_t *vidp, - u16_t *didp -) +static u32_t +pcii_rreg32(int busind, int devind, int port) { - int devind; + u32_t v; + int s; - for (devind= *devindp+1; devind < nr_pcidev; devind++) - { + v= PCII_RREG32_(pcibus[busind].pb_busnr, + pcidev[devind].pd_dev, pcidev[devind].pd_func, + port); + if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) + printf("PCI: warning, sys_outl failed: %d\n", s); #if 0 - if (pcidev[devind].pd_inuse) - continue; + printf("pcii_rreg32(%d, %d, 0x%X): %d.%d.%d= 0x%X\n", + busind, devind, port, + pcibus[busind].pb_bus, pcidev[devind].pd_dev, + pcidev[devind].pd_func, v); #endif - if (!visible(aclp, devind)) - continue; - break; - } - if (devind >= nr_pcidev) - return 0; - *devindp= devind; - *vidp= pcidev[devind].pd_vid; - *didp= pcidev[devind].pd_did; - return 1; + return v; +} + +static void +pcii_wreg8(int busind, int devind, int port, u8_t value) +{ + int s; +#if 0 + printf("pcii_wreg8(%d, %d, 0x%X, 0x%X): %d.%d.%d\n", + busind, devind, port, value, + pcibus[busind].pb_bus, pcidev[devind].pd_dev, + pcidev[devind].pd_func); +#endif + PCII_WREG8_(pcibus[busind].pb_busnr, + pcidev[devind].pd_dev, pcidev[devind].pd_func, + port, value); + if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) + printf("PCI: warning, sys_outl failed: %d\n", s); +} + +static void +pcii_wreg16(int busind, int devind, int port, u16_t value) +{ + int s; +#if 0 + printf("pcii_wreg16(%d, %d, 0x%X, 0x%X): %d.%d.%d\n", + busind, devind, port, value, + pcibus[busind].pb_bus, pcidev[devind].pd_dev, + pcidev[devind].pd_func); +#endif + PCII_WREG16_(pcibus[busind].pb_busnr, + pcidev[devind].pd_dev, pcidev[devind].pd_func, + port, value); + if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) + printf("PCI: warning, sys_outl failed: %d\n", s); +} + +static void +pcii_wreg32(int busind, int devind, int port, u32_t value) +{ + int s; +#if 0 + printf("pcii_wreg32(%d, %d, 0x%X, 0x%X): %d.%d.%d\n", + busind, devind, port, value, + pcibus[busind].pb_busnr, pcidev[devind].pd_dev, + pcidev[devind].pd_func); +#endif + PCII_WREG32_(pcibus[busind].pb_busnr, + pcidev[devind].pd_dev, pcidev[devind].pd_func, + port, value); + if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) + printf("PCI: warning, sys_outl failed: %d\n",s); } /*===========================================================================* - * pci_reserve_a * + * ntostr * *===========================================================================*/ -int pci_reserve_a(devind, proc, aclp) -int devind; -endpoint_t proc; -struct rs_pci *aclp; +static void +ntostr(unsigned int n, char **str, const char *end) { - int i, r; - int ilr; - struct io_range ior; - struct minix_mem_range mr; + char tmpstr[20]; + int i; - if (devind < 0 || devind >= nr_pcidev) + if (n == 0) { - printf("pci_reserve_a: bad devind: %d\n", devind); - return EINVAL; + tmpstr[0]= '0'; + i= 1; } - if (!visible(aclp, devind)) + else { - printf("pci_reserve_a: %u is not allowed to reserve %d\n", - proc, devind); - return EPERM; + for (i= 0; n; i++) + { + tmpstr[i]= '0' + (n%10); + n /= 10; + } } - - if(pcidev[devind].pd_inuse && pcidev[devind].pd_proc != proc) - return EBUSY; - pcidev[devind].pd_inuse= 1; - pcidev[devind].pd_proc= proc; - - for (i= 0; i0; i--) { - if(debug) printf("pci_reserve_a: adding IRQ %d\n", ilr); - r= sys_privctl(proc, SYS_PRIV_ADD_IRQ, &ilr); - if (r != OK) + if (*str == end) { - printf("sys_privctl failed for proc %d: %d\n", - proc, r); + break; } + **str= tmpstr[i-1]; + (*str)++; } - - return OK; + if (*str == end) + (*str)[-1]= '\0'; + else + **str= '\0'; } /*===========================================================================* - * pci_release * + * get_busind * *===========================================================================*/ -void pci_release(proc) -endpoint_t proc; +static int +get_busind(int busnr) { int i; - for (i= 0; i= nr_pcidev) - return EINVAL; - - *vidp= pcidev[devind].pd_vid; - *didp= pcidev[devind].pd_did; - return OK; -} - -/*===========================================================================* - * pci_rescan_bus * + * Unprotected helper functions * *===========================================================================*/ -void pci_rescan_bus(u8_t busnr) +static u8_t +__pci_attr_r8(int devind, int port) { - int busind; + int busnr, busind; + busnr= pcidev[devind].pd_busnr; busind= get_busind(busnr); - probe_bus(busind); - - /* Allocate bus numbers for uninitialized bridges */ - complete_bridges(); - - /* Allocate I/O and memory resources for uninitialized devices */ - complete_bars(); -} - -/*===========================================================================* - * pci_slot_name_s * - *===========================================================================*/ -int pci_slot_name_s(devind, cpp) -int devind; -char **cpp; -{ - static char label[]= "ddd.ddd.ddd"; - char *end; - char *p; - - if (devind < 0 || devind >= nr_pcidev) - return EINVAL; - - p= label; - end= label+sizeof(label); - - ntostr(pcidev[devind].pd_busnr, &p, end); - *p++= '.'; - - ntostr(pcidev[devind].pd_dev, &p, end); - *p++= '.'; - - ntostr(pcidev[devind].pd_func, &p, end); - - *cpp= label; - return OK; -} - -/*===========================================================================* - * pci_dev_name * - *===========================================================================*/ -char *pci_dev_name(u16_t vid, u16_t did) -{ - int i; - - for (i= 0; pci_device_table[i].name; i++) - { - if (pci_device_table[i].vid == vid && - pci_device_table[i].did == did) - { - return pci_device_table[i].name; - } - } - return NULL; -} - -/*===========================================================================* - * pci_get_bar_s * - *===========================================================================*/ -int pci_get_bar_s(int devind, int port, u32_t *base, u32_t *size, - int *ioflag) -{ - int i, reg; - - if (devind < 0 || devind >= nr_pcidev) - return EINVAL; - - for (i= 0; i < pcidev[devind].pd_bar_nr; i++) - { - reg= PCI_BAR+4*pcidev[devind].pd_bar[i].pb_nr; - - if (reg == port) - { - if (pcidev[devind].pd_bar[i].pb_flags & PBF_INCOMPLETE) - return EINVAL; - - *base= pcidev[devind].pd_bar[i].pb_base; - *size= pcidev[devind].pd_bar[i].pb_size; - *ioflag= - !!(pcidev[devind].pd_bar[i].pb_flags & PBF_IO); - return OK; - } - } - return EINVAL; -} - -/*===========================================================================* - * pci_attr_r8_s * - *===========================================================================*/ -int pci_attr_r8_s(int devind, int port, u8_t *vp) -{ - if (devind < 0 || devind >= nr_pcidev) - return EINVAL; - if (port < 0 || port > 255) - return EINVAL; - - *vp= pci_attr_r8_u(devind, port); - return OK; + return pcibus[busind].pb_rreg8(busind, devind, port); } -/*===========================================================================* - * pci_attr_r8_u * - *===========================================================================*/ -static u8_t pci_attr_r8_u(devind, port) -int devind; -int port; +static u16_t +__pci_attr_r16(int devind, int port) { int busnr, busind; busnr= pcidev[devind].pd_busnr; busind= get_busind(busnr); - return pcibus[busind].pb_rreg8(busind, devind, port); + return pcibus[busind].pb_rreg16(busind, devind, port); } -/*===========================================================================* - * pci_attr_r16 * - *===========================================================================*/ -u16_t pci_attr_r16(devind, port) -int devind; -int port; +static u32_t +__pci_attr_r32(int devind, int port) { int busnr, busind; busnr= pcidev[devind].pd_busnr; busind= get_busind(busnr); - return pcibus[busind].pb_rreg16(busind, devind, port); + return pcibus[busind].pb_rreg32(busind, devind, port); } -/*===========================================================================* - * pci_attr_r32_s * - *===========================================================================*/ -int pci_attr_r32_s(int devind, int port, u32_t *vp) +static void +__pci_attr_w8(int devind, int port, u8_t value) { - if (devind < 0 || devind >= nr_pcidev) - return EINVAL; - if (port < 0 || port > 256-4) - return EINVAL; + int busnr, busind; - *vp= pci_attr_r32_u(devind, port); - return OK; + busnr= pcidev[devind].pd_busnr; + busind= get_busind(busnr); + pcibus[busind].pb_wreg8(busind, devind, port, value); } -/*===========================================================================* - * pci_attr_r32_u * - *===========================================================================*/ -static u32_t pci_attr_r32_u(devind, port) -int devind; -int port; +static void +__pci_attr_w16(int devind, int port, u16_t value) { int busnr, busind; busnr= pcidev[devind].pd_busnr; busind= get_busind(busnr); - return pcibus[busind].pb_rreg32(busind, devind, port); + pcibus[busind].pb_wreg16(busind, devind, port, value); } -/*===========================================================================* - * pci_attr_w8 * - *===========================================================================*/ -void pci_attr_w8(int devind, int port, u8_t value) +static void +__pci_attr_w32(int devind, int port, u32_t value) { int busnr, busind; busnr= pcidev[devind].pd_busnr; busind= get_busind(busnr); - pcibus[busind].pb_wreg8(busind, devind, port, value); + pcibus[busind].pb_wreg32(busind, devind, port, value); } /*===========================================================================* - * pci_attr_w16 * + * helpers * *===========================================================================*/ -void pci_attr_w16(int devind, int port, u16_t value) +static u16_t +pci_attr_rsts(int devind) { int busnr, busind; busnr= pcidev[devind].pd_busnr; busind= get_busind(busnr); - pcibus[busind].pb_wreg16(busind, devind, port, value); + return pcibus[busind].pb_rsts(busind); } -/*===========================================================================* - * pci_attr_w32 * - *===========================================================================*/ -void pci_attr_w32(int devind, int port, u32_t value) +static void +pci_attr_wsts(int devind, u16_t value) { int busnr, busind; busnr= pcidev[devind].pd_busnr; busind= get_busind(busnr); - pcibus[busind].pb_wreg32(busind, devind, port, value); + pcibus[busind].pb_wsts(busind, value); } -/*===========================================================================* - * pci_intel_init * - *===========================================================================*/ -static void pci_intel_init() +static u16_t +pcii_rsts(int busind) { - /* Try to detect a know PCI controller. Read the Vendor ID and - * the Device ID for function 0 of device 0. - * Two times the value 0xffff suggests a system without a (compatible) - * PCI controller. - */ - u32_t bus, dev, func; - u16_t vid, did; - int s, i, r, busind, busnr; - char *dstr; + u16_t v; + int s; - bus= 0; - dev= 0; - func= 0; + v= PCII_RREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR); + if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) + printf("PCI: warning, sys_outl failed: %d\n", s); + return v; +} - vid= PCII_RREG16_(bus, dev, func, PCI_VID); - did= PCII_RREG16_(bus, dev, func, PCI_DID); +static void +pcii_wsts(int busind, u16_t value) +{ + int s; + PCII_WREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR, value); if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) printf("PCI: warning, sys_outl failed: %d\n", s); +} -#if 0 - if (vid == 0xffff && did == 0xffff) - return; /* Nothing here */ +static int +is_duplicate(u8_t busnr, u8_t dev, u8_t func) +{ + int i; - for (i= 0; pci_intel_ctrl[i].vid; i++) + for (i= 0; i= NR_PCIBUS) - panic("too many PCI busses: %d", nr_pcibus); - busind= nr_pcibus; - nr_pcibus++; - pcibus[busind].pb_type= PBT_INTEL_HOST; - pcibus[busind].pb_needinit= 0; - pcibus[busind].pb_isabridge_dev= -1; - pcibus[busind].pb_isabridge_type= 0; - pcibus[busind].pb_devind= -1; - pcibus[busind].pb_busnr= 0; - pcibus[busind].pb_rreg8= pcii_rreg8; - pcibus[busind].pb_rreg16= pcii_rreg16; - pcibus[busind].pb_rreg32= pcii_rreg32; - pcibus[busind].pb_wreg8= pcii_wreg8; - pcibus[busind].pb_wreg16= pcii_wreg16; - pcibus[busind].pb_wreg32= pcii_wreg32; - pcibus[busind].pb_rsts= pcii_rsts; - pcibus[busind].pb_wsts= pcii_wsts; - - dstr= pci_dev_name(vid, did); - if (!dstr) - dstr= "unknown device"; - if (debug) + freebus= 1; + for (i= 0; i= NR_PCIDEV) - panic("too many PCI devices: %d", nr_pcidev); - devind= nr_pcidev; + int i; - busnr= pcibus[busind].pb_busnr; - for (dev= 0; dev<32; dev++) + for (i= 0; pci_subclass_table[i].name; i++) { - - for (func= 0; func < 8; func++) + if (pci_subclass_table[i].baseclass != baseclass) + continue; + if (pci_subclass_table[i].subclass != subclass) + continue; + if (pci_subclass_table[i].infclass != infclass && + pci_subclass_table[i].infclass != (u16_t)-1) { - pcidev[devind].pd_busnr= busnr; - pcidev[devind].pd_dev= dev; - pcidev[devind].pd_func= func; + continue; + } + return pci_subclass_table[i].name; + } + return NULL; +} - pci_attr_wsts(devind, - PSR_SSE|PSR_RMAS|PSR_RTAS); - vid= pci_attr_r16(devind, PCI_VID); - did= pci_attr_r16(devind, PCI_DID); - headt= pci_attr_r8_u(devind, PCI_HEADT); - sts= pci_attr_rsts(devind); +static void +print_hyper_cap(int devind, u8_t capptr) +{ + u32_t v; + u16_t cmd; + int type0, type1; + printf("\n"); + v= __pci_attr_r32(devind, capptr); + printf("print_hyper_cap: @0x%x, off 0 (cap):", capptr); + cmd= (v >> 16) & 0xffff; #if 0 - printf("vid 0x%x, did 0x%x, headt 0x%x, sts 0x%x\n", - vid, did, headt, sts); + if (v & 0x10000) + { + printf(" WarmReset"); + v &= ~0x10000; + } + if (v & 0x20000) + { + printf(" DblEnded"); + v &= ~0x20000; + } + printf(" DevNum %d", (v & 0x7C0000) >> 18); + v &= ~0x7C0000; #endif + type0= (cmd & 0xE000) >> 13; + type1= (cmd & 0xF800) >> 11; + if (type0 == 0 || type0 == 1) + { + printf("Capability Type: %s\n", + type0 == 0 ? "Slave or Primary Interface" : + "Host or Secondary Interface"); + cmd &= ~0xE000; + } + else + { + printf(" Capability Type 0x%x", type1); + cmd &= ~0xF800; + } + if (cmd) + printf(" undecoded 0x%x\n", cmd); - if (vid == NO_VID && did == NO_VID) - { - if (func == 0) - break; /* Nothing here */ - - /* Scan all functions of a multifunction - * device. - */ - continue; - } - - if (sts & (PSR_SSE|PSR_RMAS|PSR_RTAS)) - { - static int warned = 0; - - if(!warned) { - printf( - "PCI: ignoring bad value 0x%x in sts for QEMU\n", - sts & (PSR_SSE|PSR_RMAS|PSR_RTAS)); - warned = 1; - } - } - - sub_vid= pci_attr_r16(devind, PCI_SUBVID); - sub_did= pci_attr_r16(devind, PCI_SUBDID); +#if 0 + printf("print_hyper_cap: off 4 (ctl): 0x%x\n", + __pci_attr_r32(devind, capptr+4)); + printf("print_hyper_cap: off 8 (freq/rev): 0x%x\n", + __pci_attr_r32(devind, capptr+8)); + printf("print_hyper_cap: off 12 (cap): 0x%x\n", + __pci_attr_r32(devind, capptr+12)); + printf("print_hyper_cap: off 16 (buf count): 0x%x\n", + __pci_attr_r32(devind, capptr+16)); + v= __pci_attr_r32(devind, capptr+20); + printf("print_hyper_cap: @0x%x, off 20 (bus nr): ", + capptr+20); + printf("prim %d", v & 0xff); + printf(", sec %d", (v >> 8) & 0xff); + printf(", sub %d", (v >> 16) & 0xff); + if (v >> 24) + printf(", reserved %d", (v >> 24) & 0xff); + printf("\n"); + printf("print_hyper_cap: off 24 (type): 0x%x\n", + __pci_attr_r32(devind, capptr+24)); +#endif +} - dstr= pci_dev_name(vid, did); - if (debug) - { - if (dstr) - { - printf("%d.%lu.%lu: %s (%04X:%04X)\n", - busnr, (unsigned long)dev, - (unsigned long)func, dstr, - vid, did); - } - else - { - printf( - "%d.%lu.%lu: Unknown device, vendor %04X (%s), device %04X\n", - busnr, (unsigned long)dev, - (unsigned long)func, vid, - pci_vid_name(vid), did); - } - printf("Device index: %d\n", devind); - printf("Subsystem: Vid 0x%x, did 0x%x\n", - sub_vid, sub_did); - } +static void +print_capabilities(int devind) +{ + u8_t status, capptr, type, next, subtype; + const char *str; - baseclass= pci_attr_r8_u(devind, PCI_BCR); - subclass= pci_attr_r8_u(devind, PCI_SCR); - infclass= pci_attr_r8_u(devind, PCI_PIFR); - s= pci_subclass_name(baseclass, subclass, infclass); - if (!s) - s= pci_baseclass_name(baseclass); - { - if (!s) - s= "(unknown class)"; - } - if (debug) - { - printf("\tclass %s (%X/%X/%X)\n", s, - baseclass, subclass, infclass); - } + /* Check capabilities bit in the device status register */ + status= __pci_attr_r16(devind, PCI_SR); + if (!(status & PSR_CAPPTR)) + return; - if (is_duplicate(busnr, dev, func)) - { - printf("\tduplicate!\n"); - if (func == 0 && !(headt & PHT_MULTIFUNC)) - break; - continue; - } + capptr= (__pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK); + while (capptr != 0) + { + type = __pci_attr_r8(devind, capptr+CAP_TYPE); + next= (__pci_attr_r8(devind, capptr+CAP_NEXT) & PCI_CP_MASK); + switch(type) + { + case 1: str= "PCI Power Management"; break; + case 2: str= "AGP"; break; + case 3: str= "Vital Product Data"; break; + case 4: str= "Slot Identification"; break; + case 5: str= "Message Signaled Interrupts"; break; + case 6: str= "CompactPCI Hot Swap"; break; + case 8: str= "AMD HyperTransport"; break; + case 0xf: str= "Secure Device"; break; + default: str= "(unknown type)"; break; + } - devind= nr_pcidev; - nr_pcidev++; - pcidev[devind].pd_baseclass= baseclass; - pcidev[devind].pd_subclass= subclass; - pcidev[devind].pd_infclass= infclass; - pcidev[devind].pd_vid= vid; - pcidev[devind].pd_did= did; - pcidev[devind].pd_sub_vid= sub_vid; - pcidev[devind].pd_sub_did= sub_did; - pcidev[devind].pd_inuse= 0; - pcidev[devind].pd_bar_nr= 0; - record_irq(devind); - switch(headt & PHT_MASK) + printf(" @0x%x (0x%08x): capability type 0x%x: %s", + capptr, __pci_attr_r32(devind, capptr), type, str); + if (type == 0x08) + print_hyper_cap(devind, capptr); + else if (type == 0x0f) + { + subtype= (__pci_attr_r8(devind, capptr+2) & 0x07); + switch(subtype) { - case PHT_NORMAL: - record_bars_normal(devind); - break; - case PHT_BRIDGE: - record_bars_bridge(devind); - break; - case PHT_CARDBUS: - record_bars_cardbus(devind); - break; - default: - printf("\t%d.%d.%d: unknown header type %d\n", - busind, dev, func, - headt & PHT_MASK); - break; + case 0: str= "Device Exclusion Vector"; break; + case 3: str= "IOMMU"; break; + default: str= "(unknown type)"; break; } - if (debug) - print_capabilities(devind); - - t3= ((baseclass << 16) | (subclass << 8) | infclass); -#if 0 - if (t3 == PCI_T3_VGA || t3 == PCI_T3_VGA_OLD) - report_vga(devind); -#endif - - if (nr_pcidev >= NR_PCIDEV) - panic("too many PCI devices: %d", nr_pcidev); - devind= nr_pcidev; - - if (func == 0 && !(headt & PHT_MULTIFUNC)) - break; + printf(", sub type 0%o: %s", subtype, str); } + printf("\n"); + capptr= next; } } /*===========================================================================* - * is_duplicate * + * ISA Bridge Helpers * *===========================================================================*/ -static int is_duplicate(u8_t busnr, u8_t dev, u8_t func) +static void +update_bridge4dev_io(int devind, u32_t io_base, u32_t io_size) { - int i; + int busnr, busind, type, br_devind; + u16_t v16; - for (i= 0; ihdr.request = ACPI_REQ_GET_IRQ; - ((struct acpi_get_irq_req *)&m)->bus = bus; - ((struct acpi_get_irq_req *)&m)->dev = dev; - ((struct acpi_get_irq_req *)&m)->pin = pin; - - if ((err = ipc_sendrec(acpi_ep, &m)) != OK) - panic("PCI: error %d while receiveing from ACPI\n", err); - - return ((struct acpi_get_irq_resp *)&m)->irq; -} - -static int derive_irq(struct pcidev * dev, int pin) -{ - struct pcidev * parent_bridge; - int slot; - - parent_bridge = &pcidev[pcibus[get_busind(dev->pd_busnr)].pb_devind]; + if (type != PBT_CARDBUS) + panic("update_bridge4dev_io: strange bus type: %d", type); - /* - * We don't support PCI-Express, no ARI, decode the slot of the device - * and mangle the pin as the device is behind a bridge - */ - slot = ((dev->pd_func) >> 3) & 0x1f; + if (debug) + { + printf("update_bridge4dev_io: adding 0x%x at 0x%x\n", + io_size, io_base); + } + br_devind= pcibus[busind].pb_devind; + __pci_attr_w32(br_devind, CBB_IOLIMIT_0, io_base+io_size-1); + __pci_attr_w32(br_devind, CBB_IOBASE_0, io_base); - return acpi_get_irq(parent_bridge->pd_busnr, - parent_bridge->pd_dev, (pin + slot) % 4); + /* Enable I/O access. Enable busmaster access as well. */ + v16= __pci_attr_r16(devind, PCI_CR); + __pci_attr_w16(devind, PCI_CR, v16 | PCI_CR_IO_EN | PCI_CR_MAST_EN); } -/*===========================================================================* - * record_irq * - *===========================================================================*/ -static void record_irq(devind) -int devind; +static int +do_piix(int devind) { - int ilr, ipr, busnr, busind, cb_devind; - - ilr= pci_attr_r8_u(devind, PCI_ILR); - ipr= pci_attr_r8_u(devind, PCI_IPR); - - if (ipr && machine.apic_enabled) { - int irq; - - irq = acpi_get_irq(pcidev[devind].pd_busnr, - pcidev[devind].pd_dev, ipr - 1); - - if (irq < 0) - irq = derive_irq(&pcidev[devind], ipr - 1); - - if (irq >= 0) { - ilr = irq; - pci_attr_w8(devind, PCI_ILR, ilr); - if (debug) - printf("PCI: ACPI IRQ %d for " - "device %d.%d.%d INT%c\n", - irq, - pcidev[devind].pd_busnr, - pcidev[devind].pd_dev, - pcidev[devind].pd_func, - 'A' + ipr-1); - } - else if (debug) { - printf("PCI: no ACPI IRQ routing for " - "device %d.%d.%d INT%c\n", - pcidev[devind].pd_busnr, - pcidev[devind].pd_dev, - pcidev[devind].pd_func, - 'A' + ipr-1); - } - } + int i, s, irqrc, irq; + u32_t elcr1, elcr2, elcr; - if (ilr == 0) +#if DEBUG + printf("in piix\n"); +#endif + if (OK != (s=sys_inb(PIIX_ELCR1, &elcr1))) + printf("Warning, sys_inb failed: %d\n", s); + if (OK != (s=sys_inb(PIIX_ELCR2, &elcr2))) + printf("Warning, sys_inb failed: %d\n", s); + elcr= elcr1 | (elcr2 << 8); + for (i= 0; i<4; i++) { - static int first= 1; - if (ipr && first && debug) + irqrc= __pci_attr_r8(devind, PIIX_PIRQRCA+i); + if (irqrc & PIIX_IRQ_DI) { - first= 0; - printf("PCI: strange, BIOS assigned IRQ0\n"); + if (debug) + printf("INT%c: disabled\n", 'A'+i); } - ilr= PCI_ILR_UNKNOWN; - } - pcidev[devind].pd_ilr= ilr; - if (ilr == PCI_ILR_UNKNOWN && !ipr) - { - } - else if (ilr != PCI_ILR_UNKNOWN && ipr) - { - if (debug) - printf("\tIRQ %d for INT%c\n", ilr, 'A' + ipr-1); - } - else if (ilr != PCI_ILR_UNKNOWN) - { - printf( - "PCI: IRQ %d is assigned, but device %d.%d.%d does not need it\n", - ilr, pcidev[devind].pd_busnr, pcidev[devind].pd_dev, - pcidev[devind].pd_func); - } - else - { - /* Check for cardbus devices */ - busnr= pcidev[devind].pd_busnr; - busind= get_busind(busnr); - if (pcibus[busind].pb_type == PBT_CARDBUS) + else { - cb_devind= pcibus[busind].pb_devind; - ilr= pcidev[cb_devind].pd_ilr; - if (ilr != PCI_ILR_UNKNOWN) + irq= irqrc & PIIX_IRQ_MASK; + if (debug) + printf("INT%c: %d\n", 'A'+i, irq); + if (!(elcr & (1 << irq))) { if (debug) { printf( - "assigning IRQ %d to Cardbus device\n", - ilr); + "(warning) IRQ %d is not level triggered\n", + irq); } - pci_attr_w8(devind, PCI_ILR, ilr); - pcidev[devind].pd_ilr= ilr; - return; } - } - if(debug) { - printf( - "PCI: device %d.%d.%d uses INT%c but is not assigned any IRQ\n", - pcidev[devind].pd_busnr, pcidev[devind].pd_dev, - pcidev[devind].pd_func, 'A' + ipr-1); + irq_mode_pci(irq); } } + return 0; } -/*===========================================================================* - * record_bars_normal * - *===========================================================================*/ -static void record_bars_normal(devind) -int devind; +static int +do_amd_isabr(int devind) { - int i, j, clear_01, clear_23, pb_nr; + int i, busnr, dev, func, xdevind, irq, edge; + u8_t levmask; + u16_t pciirq; - /* The BAR area of normal devices is six DWORDs in size. */ - record_bars(devind, PCI_BAR_6); + /* Find required function */ + func= AMD_ISABR_FUNC; + busnr= pcidev[devind].pd_busnr; + dev= pcidev[devind].pd_dev; - /* Special case code for IDE controllers in compatibility mode */ - if (pcidev[devind].pd_baseclass == PCI_BCR_MASS_STORAGE && - pcidev[devind].pd_subclass == PCI_MS_IDE) + /* Fake a device with the required function */ + if (nr_pcidev >= NR_PCIDEV) + panic("too many PCI devices: %d", nr_pcidev); + xdevind= nr_pcidev; + pcidev[xdevind].pd_busnr= busnr; + pcidev[xdevind].pd_dev= dev; + pcidev[xdevind].pd_func= func; + pcidev[xdevind].pd_inuse= 1; + nr_pcidev++; + + levmask= __pci_attr_r8(xdevind, AMD_ISABR_PCIIRQ_LEV); + pciirq= __pci_attr_r16(xdevind, AMD_ISABR_PCIIRQ_ROUTE); + for (i= 0; i<4; i++) { - /* IDE device */ - clear_01= 0; - clear_23= 0; - if (!(pcidev[devind].pd_infclass & PCI_IDE_PRI_NATIVE)) + edge= (levmask >> i) & 1; + irq= (pciirq >> (4*i)) & 0xf; + if (!irq) { if (debug) - { - printf( - "primary channel is not in native mode, clearing BARs 0 and 1\n"); - } - clear_01= 1; + printf("INT%c: disabled\n", 'A'+i); } - if (!(pcidev[devind].pd_infclass & PCI_IDE_SEC_NATIVE)) + else { if (debug) + printf("INT%c: %d\n", 'A'+i, irq); + if (edge && debug) { printf( - "secondary channel is not in native mode, clearing BARs 2 and 3\n"); + "(warning) IRQ %d is not level triggered\n", + irq); } - clear_23= 1; + irq_mode_pci(irq); } + } + nr_pcidev--; + return 0; +} - j= 0; - for (i= 0; i> 4; + break; + case 1: + edge= (levmask & VIA_ISABR_EL_INTB); + irq= __pci_attr_r8(devind, VIA_ISABR_IRQ_R2); + break; + case 2: + edge= (levmask & VIA_ISABR_EL_INTC); + irq= __pci_attr_r8(devind, VIA_ISABR_IRQ_R3) >> 4; + break; + case 3: + edge= (levmask & VIA_ISABR_EL_INTD); + irq= __pci_attr_r8(devind, VIA_ISABR_IRQ_R1) >> 4; + break; + default: + panic("PCI: VIA ISA Bridge IRQ Detection Failed"); + } + irq &= 0xf; + if (!irq) + { + if (debug) + printf("INT%c: disabled\n", 'A'+i); + } + else + { + if (debug) + printf("INT%c: %d\n", 'A'+i, irq); + if (edge && debug) { - j++; - continue; /* No need to copy */ + printf( + "(warning) IRQ %d is not level triggered\n", + irq); } - pcidev[devind].pd_bar[j]= - pcidev[devind].pd_bar[i]; - j++; + irq_mode_pci(irq); } - pcidev[devind].pd_bar_nr= j; } + return 0; } -/*===========================================================================* - * record_bars_bridge * - *===========================================================================*/ -static void record_bars_bridge(devind) -int devind; +static int +do_isabridge(int busind) { - u32_t base, limit, size; - - /* The generic BAR area of PCI-to-PCI bridges is two DWORDs in size. - * It may contain up to two 32-bit BARs, or one 64-bit BAR. - */ - record_bars(devind, PCI_BAR_2); + int i, j, r, type, busnr, unknown_bridge, bridge_dev; + u16_t vid, did; + u32_t t3; + const char *dstr; - base= ((pci_attr_r8_u(devind, PPB_IOBASE) & PPB_IOB_MASK) << 8) | - (pci_attr_r16(devind, PPB_IOBASEU16) << 16); - limit= 0xff | - ((pci_attr_r8_u(devind, PPB_IOLIMIT) & PPB_IOL_MASK) << 8) | - ((~PPB_IOL_MASK & 0xff) << 8) | - (pci_attr_r16(devind, PPB_IOLIMITU16) << 16); - size= limit-base + 1; - if (debug) + unknown_bridge= -1; + bridge_dev= -1; + j= 0; /* lint */ + vid= did= 0; /* lint */ + busnr= pcibus[busind].pb_busnr; + for (i= 0; i< nr_pcidev; i++) { - printf("\tI/O window: base 0x%x, limit 0x%x, size %d\n", - base, limit, size); + if (pcidev[i].pd_busnr != busnr) + continue; + t3= ((pcidev[i].pd_baseclass << 16) | + (pcidev[i].pd_subclass << 8) | pcidev[i].pd_infclass); + if (t3 == PCI_T3_ISA) + { + /* ISA bridge. Report if no supported bridge is + * found. + */ + unknown_bridge= i; + } + + vid= pcidev[i].pd_vid; + did= pcidev[i].pd_did; + for (j= 0; pci_isabridge[j].vid != 0; j++) + { + if (pci_isabridge[j].vid != vid) + continue; + if (pci_isabridge[j].did != did) + continue; + if (pci_isabridge[j].checkclass && + unknown_bridge != i) + { + /* This part of multifunction device is + * not the bridge. + */ + continue; + } + break; + } + if (pci_isabridge[j].vid) + { + bridge_dev= i; + break; + } } - base= ((pci_attr_r16(devind, PPB_MEMBASE) & PPB_MEMB_MASK) << 16); - limit= 0xffff | - ((pci_attr_r16(devind, PPB_MEMLIMIT) & PPB_MEML_MASK) << 16) | - ((~PPB_MEML_MASK & 0xffff) << 16); - size= limit-base + 1; - if (debug) + if (bridge_dev != -1) { - printf("\tMemory window: base 0x%x, limit 0x%x, size 0x%x\n", - base, limit, size); + dstr= _pci_dev_name(vid, did); + if (!dstr) + dstr= "unknown device"; + if (debug) + { + printf("found ISA bridge (%04X:%04X) %s\n", + vid, did, dstr); + } + pcibus[busind].pb_isabridge_dev= bridge_dev; + type= pci_isabridge[j].type; + pcibus[busind].pb_isabridge_type= type; + switch(type) + { + case PCI_IB_PIIX: + r= do_piix(bridge_dev); + break; + case PCI_IB_VIA: + r= do_via_isabr(bridge_dev); + break; + case PCI_IB_AMD: + r= do_amd_isabr(bridge_dev); + break; + case PCI_IB_SIS: + r= do_sis_isabr(bridge_dev); + break; + default: + panic("unknown ISA bridge type: %d", type); + } + return r; } - /* Ignore the upper 32 bits */ - base= ((pci_attr_r16(devind, PPB_PFMEMBASE) & PPB_PFMEMB_MASK) << 16); - limit= 0xffff | - ((pci_attr_r16(devind, PPB_PFMEMLIMIT) & - PPB_PFMEML_MASK) << 16) | - ((~PPB_PFMEML_MASK & 0xffff) << 16); - size= limit-base + 1; + if (unknown_bridge == -1) + { + if (debug) + { + printf("(warning) no ISA bridge found on bus %d\n", + busind); + } + return 0; + } if (debug) { printf( - "\tPrefetchable memory window: base 0x%x, limit 0x%x, size 0x%x\n", - base, limit, size); + "(warning) unsupported ISA bridge %04X:%04X for bus %d\n", + pcidev[unknown_bridge].pd_vid, + pcidev[unknown_bridge].pd_did, busind); } + return 0; } /*===========================================================================* - * record_bars_cardbus * + * IRQ handling * *===========================================================================*/ -static void record_bars_cardbus(devind) -int devind; +static int +acpi_get_irq(unsigned bus, unsigned dev, unsigned pin) { - u32_t base, limit, size; + int err; + message m; - /* The generic BAR area of CardBus devices is one DWORD in size. */ - record_bars(devind, PCI_BAR); + ((struct acpi_get_irq_req *)&m)->hdr.request = ACPI_REQ_GET_IRQ; + ((struct acpi_get_irq_req *)&m)->bus = bus; + ((struct acpi_get_irq_req *)&m)->dev = dev; + ((struct acpi_get_irq_req *)&m)->pin = pin; - base= pci_attr_r32_u(devind, CBB_MEMBASE_0); - limit= pci_attr_r32_u(devind, CBB_MEMLIMIT_0) | - (~CBB_MEML_MASK & 0xffffffff); - size= limit-base + 1; - if (debug) - { - printf("\tMemory window 0: base 0x%x, limit 0x%x, size %d\n", - base, limit, size); + if ((err = ipc_sendrec(acpi_ep, &m)) != OK) + panic("PCI: error %d while receiveing from ACPI\n", err); + + return ((struct acpi_get_irq_resp *)&m)->irq; +} + +static int +derive_irq(struct pcidev * dev, int pin) +{ + struct pcidev * parent_bridge; + int slot; + + parent_bridge = &pcidev[pcibus[get_busind(dev->pd_busnr)].pb_devind]; + + /* + * We don't support PCI-Express, no ARI, decode the slot of the device + * and mangle the pin as the device is behind a bridge + */ + slot = ((dev->pd_func) >> 3) & 0x1f; + + return acpi_get_irq(parent_bridge->pd_busnr, + parent_bridge->pd_dev, (pin + slot) % 4); +} + +static void +record_irq(int devind) +{ + int ilr, ipr, busnr, busind, cb_devind; + + ilr= __pci_attr_r8(devind, PCI_ILR); + ipr= __pci_attr_r8(devind, PCI_IPR); + + if (ipr && machine.apic_enabled) { + int irq; + + irq = acpi_get_irq(pcidev[devind].pd_busnr, + pcidev[devind].pd_dev, ipr - 1); + + if (irq < 0) + irq = derive_irq(&pcidev[devind], ipr - 1); + + if (irq >= 0) { + ilr = irq; + __pci_attr_w8(devind, PCI_ILR, ilr); + if (debug) + printf("PCI: ACPI IRQ %d for " + "device %d.%d.%d INT%c\n", + irq, + pcidev[devind].pd_busnr, + pcidev[devind].pd_dev, + pcidev[devind].pd_func, + 'A' + ipr-1); + } + else if (debug) { + printf("PCI: no ACPI IRQ routing for " + "device %d.%d.%d INT%c\n", + pcidev[devind].pd_busnr, + pcidev[devind].pd_dev, + pcidev[devind].pd_func, + 'A' + ipr-1); + } } - base= pci_attr_r32_u(devind, CBB_MEMBASE_1); - limit= pci_attr_r32_u(devind, CBB_MEMLIMIT_1) | - (~CBB_MEML_MASK & 0xffffffff); - size= limit-base + 1; - if (debug) + if (ilr == 0) { - printf("\tMemory window 1: base 0x%x, limit 0x%x, size %d\n", - base, limit, size); + static int first= 1; + if (ipr && first && debug) + { + first= 0; + printf("PCI: strange, BIOS assigned IRQ0\n"); + } + ilr= PCI_ILR_UNKNOWN; } - - base= pci_attr_r32_u(devind, CBB_IOBASE_0); - limit= pci_attr_r32_u(devind, CBB_IOLIMIT_0) | - (~CBB_IOL_MASK & 0xffffffff); - size= limit-base + 1; - if (debug) + pcidev[devind].pd_ilr= ilr; + if (ilr == PCI_ILR_UNKNOWN && !ipr) { - printf("\tI/O window 0: base 0x%x, limit 0x%x, size %d\n", - base, limit, size); } - - base= pci_attr_r32_u(devind, CBB_IOBASE_1); - limit= pci_attr_r32_u(devind, CBB_IOLIMIT_1) | - (~CBB_IOL_MASK & 0xffffffff); - size= limit-base + 1; - if (debug) + else if (ilr != PCI_ILR_UNKNOWN && ipr) { - printf("\tI/O window 1: base 0x%x, limit 0x%x, size %d\n", - base, limit, size); + if (debug) + printf("\tIRQ %d for INT%c\n", ilr, 'A' + ipr-1); } -} - -/*===========================================================================* - * record_bars * - *===========================================================================*/ -static void record_bars(int devind, int last_reg) -{ - int i, reg, width; - - for (i= 0, reg= PCI_BAR; reg <= last_reg; i += width, reg += 4 * width) + else if (ilr != PCI_ILR_UNKNOWN) { - width = record_bar(devind, i, reg == last_reg); + printf( + "PCI: IRQ %d is assigned, but device %d.%d.%d does not need it\n", + ilr, pcidev[devind].pd_busnr, pcidev[devind].pd_dev, + pcidev[devind].pd_func); + } + else + { + /* Check for cardbus devices */ + busnr= pcidev[devind].pd_busnr; + busind= get_busind(busnr); + if (pcibus[busind].pb_type == PBT_CARDBUS) + { + cb_devind= pcibus[busind].pb_devind; + ilr= pcidev[cb_devind].pd_ilr; + if (ilr != PCI_ILR_UNKNOWN) + { + if (debug) + { + printf( + "assigning IRQ %d to Cardbus device\n", + ilr); + } + __pci_attr_w8(devind, PCI_ILR, ilr); + pcidev[devind].pd_ilr= ilr; + return; + } + } + if(debug) { + printf( + "PCI: device %d.%d.%d uses INT%c but is not assigned any IRQ\n", + pcidev[devind].pd_busnr, pcidev[devind].pd_dev, + pcidev[devind].pd_func, 'A' + ipr-1); + } } } /*===========================================================================* - * record_bar * + * BAR helpers * *===========================================================================*/ -static int record_bar(devind, bar_nr, last) -int devind; -int bar_nr; -int last; +static int +record_bar(int devind, int bar_nr, int last) { int reg, prefetch, type, dev_bar_nr, width; u32_t bar, bar2; @@ -1281,20 +1072,20 @@ int last; reg= PCI_BAR+4*bar_nr; - bar= pci_attr_r32_u(devind, reg); + bar= __pci_attr_r32(devind, reg); if (bar & PCI_BAR_IO) { /* Disable I/O access before probing for BAR's size */ - cmd = pci_attr_r16(devind, PCI_CR); - pci_attr_w16(devind, PCI_CR, cmd & ~PCI_CR_IO_EN); + cmd = __pci_attr_r16(devind, PCI_CR); + __pci_attr_w16(devind, PCI_CR, cmd & ~PCI_CR_IO_EN); /* Probe BAR's size */ - pci_attr_w32(devind, reg, 0xffffffff); - bar2= pci_attr_r32_u(devind, reg); + __pci_attr_w32(devind, reg, 0xffffffff); + bar2= __pci_attr_r32(devind, reg); /* Restore original state */ - pci_attr_w32(devind, reg, bar); - pci_attr_w16(devind, PCI_CR, cmd); + __pci_attr_w32(devind, reg, bar); + __pci_attr_w16(devind, PCI_CR, cmd); bar &= PCI_BAR_IO_MASK; /* Clear non-address bits */ bar2 &= PCI_BAR_IO_MASK; @@ -1312,7 +1103,7 @@ int last; pcidev[devind].pd_bar[dev_bar_nr].pb_nr= bar_nr; if (bar == 0) { - pcidev[devind].pd_bar[dev_bar_nr].pb_flags |= + pcidev[devind].pd_bar[dev_bar_nr].pb_flags |= PBF_INCOMPLETE; } } @@ -1339,7 +1130,7 @@ int last; } width++; - bar2= pci_attr_r32_u(devind, reg+4); + bar2= __pci_attr_r32(devind, reg+4); /* If the upper 32 bits of the BAR are not zero, the * memory is inaccessible to us; ignore the BAR. @@ -1369,16 +1160,16 @@ int last; } /* Disable mem access before probing for BAR's size */ - cmd = pci_attr_r16(devind, PCI_CR); - pci_attr_w16(devind, PCI_CR, cmd & ~PCI_CR_MEM_EN); + cmd = __pci_attr_r16(devind, PCI_CR); + __pci_attr_w16(devind, PCI_CR, cmd & ~PCI_CR_MEM_EN); /* Probe BAR's size */ - pci_attr_w32(devind, reg, 0xffffffff); - bar2= pci_attr_r32_u(devind, reg); + __pci_attr_w32(devind, reg, 0xffffffff); + bar2= __pci_attr_r32(devind, reg); /* Restore original values */ - pci_attr_w32(devind, reg, bar); - pci_attr_w16(devind, PCI_CR, cmd); + __pci_attr_w32(devind, reg, bar); + __pci_attr_w16(devind, PCI_CR, cmd); if (bar2 == 0) return width; /* Reg. is not implemented */ @@ -1402,59 +1193,186 @@ int last; pcidev[devind].pd_bar[dev_bar_nr].pb_nr= bar_nr; if (bar == 0) { - pcidev[devind].pd_bar[dev_bar_nr].pb_flags |= + pcidev[devind].pd_bar[dev_bar_nr].pb_flags |= PBF_INCOMPLETE; } } - - return width; + + return width; +} + +static void +record_bars(int devind, int last_reg) +{ + int i, reg, width; + + for (i= 0, reg= PCI_BAR; reg <= last_reg; i += width, reg += 4 * width) + { + width = record_bar(devind, i, reg == last_reg); + } +} + +static void +record_bars_normal(int devind) +{ + int i, j, clear_01, clear_23, pb_nr; + + /* The BAR area of normal devices is six DWORDs in size. */ + record_bars(devind, PCI_BAR_6); + + /* Special case code for IDE controllers in compatibility mode */ + if (pcidev[devind].pd_baseclass == PCI_BCR_MASS_STORAGE && + pcidev[devind].pd_subclass == PCI_MS_IDE) + { + /* IDE device */ + clear_01= 0; + clear_23= 0; + if (!(pcidev[devind].pd_infclass & PCI_IDE_PRI_NATIVE)) + { + if (debug) + { + printf( + "primary channel is not in native mode, clearing BARs 0 and 1\n"); + } + clear_01= 1; + } + if (!(pcidev[devind].pd_infclass & PCI_IDE_SEC_NATIVE)) + { + if (debug) + { + printf( + "secondary channel is not in native mode, clearing BARs 2 and 3\n"); + } + clear_23= 1; + } + + j= 0; + for (i= 0; i= NR_PCIDEV) + panic("too many PCI devices: %d", nr_pcidev); + devind= nr_pcidev; + + busnr= pcibus[busind].pb_busnr; + for (dev= 0; dev<32; dev++) { - printf("update_bridge4dev_io: adding 0x%x at 0x%x\n", - io_size, io_base); + + for (func= 0; func < 8; func++) + { + pcidev[devind].pd_busnr= busnr; + pcidev[devind].pd_dev= dev; + pcidev[devind].pd_func= func; + + pci_attr_wsts(devind, + PSR_SSE|PSR_RMAS|PSR_RTAS); + vid= __pci_attr_r16(devind, PCI_VID); + did= __pci_attr_r16(devind, PCI_DID); + headt= __pci_attr_r8(devind, PCI_HEADT); + sts= pci_attr_rsts(devind); + +#if 0 + printf("vid 0x%x, did 0x%x, headt 0x%x, sts 0x%x\n", + vid, did, headt, sts); +#endif + + if (vid == NO_VID && did == NO_VID) + { + if (func == 0) + break; /* Nothing here */ + + /* Scan all functions of a multifunction + * device. + */ + continue; + } + + if (sts & (PSR_SSE|PSR_RMAS|PSR_RTAS)) + { + static int warned = 0; + + if(!warned) { + printf( + "PCI: ignoring bad value 0x%x in sts for QEMU\n", + sts & (PSR_SSE|PSR_RMAS|PSR_RTAS)); + warned = 1; + } + } + + sub_vid= __pci_attr_r16(devind, PCI_SUBVID); + sub_did= __pci_attr_r16(devind, PCI_SUBDID); + + dstr= _pci_dev_name(vid, did); + if (debug) + { + if (dstr) + { + printf("%d.%lu.%lu: %s (%04X:%04X)\n", + busnr, (unsigned long)dev, + (unsigned long)func, dstr, + vid, did); + } + else + { + printf( + "%d.%lu.%lu: Unknown device, vendor %04X (%s), device %04X\n", + busnr, (unsigned long)dev, + (unsigned long)func, vid, + pci_vid_name(vid), did); + } + printf("Device index: %d\n", devind); + printf("Subsystem: Vid 0x%x, did 0x%x\n", + sub_vid, sub_did); + } + + baseclass= __pci_attr_r8(devind, PCI_BCR); + subclass= __pci_attr_r8(devind, PCI_SCR); + infclass= __pci_attr_r8(devind, PCI_PIFR); + s= pci_subclass_name(baseclass, subclass, infclass); + if (!s) + s= pci_baseclass_name(baseclass); + { + if (!s) + s= "(unknown class)"; + } + if (debug) + { + printf("\tclass %s (%X/%X/%X)\n", s, + baseclass, subclass, infclass); + } + + if (is_duplicate(busnr, dev, func)) + { + printf("\tduplicate!\n"); + if (func == 0 && !(headt & PHT_MULTIFUNC)) + break; + continue; + } + + devind= nr_pcidev; + nr_pcidev++; + pcidev[devind].pd_baseclass= baseclass; + pcidev[devind].pd_subclass= subclass; + pcidev[devind].pd_infclass= infclass; + pcidev[devind].pd_vid= vid; + pcidev[devind].pd_did= did; + pcidev[devind].pd_sub_vid= sub_vid; + pcidev[devind].pd_sub_did= sub_did; + pcidev[devind].pd_inuse= 0; + pcidev[devind].pd_bar_nr= 0; + record_irq(devind); + switch(headt & PHT_MASK) + { + case PHT_NORMAL: + record_bars_normal(devind); + break; + case PHT_BRIDGE: + record_bars_bridge(devind); + break; + case PHT_CARDBUS: + record_bars_cardbus(devind); + break; + default: + printf("\t%d.%d.%d: unknown header type %d\n", + busind, dev, func, + headt & PHT_MASK); + break; + } + if (debug) + print_capabilities(devind); + + t3= ((baseclass << 16) | (subclass << 8) | infclass); +#if 0 + if (t3 == PCI_T3_VGA || t3 == PCI_T3_VGA_OLD) + report_vga(devind); +#endif + + if (nr_pcidev >= NR_PCIDEV) + panic("too many PCI devices: %d", nr_pcidev); + devind= nr_pcidev; + + if (func == 0 && !(headt & PHT_MULTIFUNC)) + break; + } } - br_devind= pcibus[busind].pb_devind; - pci_attr_w32(br_devind, CBB_IOLIMIT_0, io_base+io_size-1); - pci_attr_w32(br_devind, CBB_IOBASE_0, io_base); +} - /* Enable I/O access. Enable busmaster access as well. */ - v16= pci_attr_r16(devind, PCI_CR); - pci_attr_w16(devind, PCI_CR, v16 | PCI_CR_IO_EN | PCI_CR_MAST_EN); + +static u16_t +pcibr_std_rsts(int busind) +{ + int devind; + + devind= pcibus[busind].pb_devind; + return __pci_attr_r16(devind, PPB_SSTS); } -/*===========================================================================* - * get_freebus * - *===========================================================================*/ -static int get_freebus() +static void +pcibr_std_wsts(int busind, u16_t value) { - int i, freebus; + int devind; + devind= pcibus[busind].pb_devind; - freebus= 1; - for (i= 0; i= NR_PCIBUS) panic("too many PCI busses: %d", nr_pcibus); @@ -1967,235 +1979,140 @@ int busind; pcibus[ind].pb_wsts= pcibr_via_wsts; break; default: - panic("unknown PCI-PCI bridge type: %d", type); + panic("unknown PCI-PCI bridge type: %d", type); } if (machine.apic_enabled) - acpi_map_bridge(pcidev[devind].pd_busnr, - pcidev[devind].pd_dev, sbusn); - - if (debug) - { - printf( - "bus(table) = %d, bus(sec) = %d, bus(subord) = %d\n", - ind, sbusn, pci_attr_r8_u(devind, PPB_SUBORDBN)); - } - if (sbusn == 0) - { - printf("Secondary bus number not initialized\n"); - continue; - } - pcibus[ind].pb_needinit= 0; - - probe_bus(ind); - - /* Look for PCI bridges */ - do_pcibridge(ind); - } -} - -/*===========================================================================* - * get_busind * - *===========================================================================*/ -static int get_busind(busnr) -int busnr; -{ - int i; - - for (i= 0; i= NR_PCIDEV) - panic("too many PCI devices: %d", nr_pcidev); - xdevind= nr_pcidev; - pcidev[xdevind].pd_busnr= busnr; - pcidev[xdevind].pd_dev= dev; - pcidev[xdevind].pd_func= func; - pcidev[xdevind].pd_inuse= 1; - nr_pcidev++; - - levmask= pci_attr_r8_u(xdevind, AMD_ISABR_PCIIRQ_LEV); - pciirq= pci_attr_r16(xdevind, AMD_ISABR_PCIIRQ_ROUTE); - for (i= 0; i<4; i++) - { - edge= (levmask >> i) & 1; - irq= (pciirq >> (4*i)) & 0xf; - if (!irq) - { - if (debug) - printf("INT%c: disabled\n", 'A'+i); - } - else - { - if (debug) - printf("INT%c: %d\n", 'A'+i, irq); - if (edge && debug) - { - printf( - "(warning) IRQ %d is not level triggered\n", - irq); - } - irq_mode_pci(irq); - } - } - nr_pcidev--; - return 0; -} - -/*===========================================================================* - * do_sis_isabr * - *===========================================================================*/ -static int do_sis_isabr(int devind) -{ - int i, irq; - - irq= 0; /* lint */ - for (i= 0; i<4; i++) - { - irq= pci_attr_r8_u(devind, SIS_ISABR_IRQ_A+i); - if (irq & SIS_IRQ_DISABLED) + acpi_map_bridge(pcidev[devind].pd_busnr, + pcidev[devind].pd_dev, sbusn); + + if (debug) { - if (debug) - printf("INT%c: disabled\n", 'A'+i); + printf( + "bus(table) = %d, bus(sec) = %d, bus(subord) = %d\n", + ind, sbusn, __pci_attr_r8(devind, PPB_SUBORDBN)); } - else + if (sbusn == 0) { - irq &= SIS_IRQ_MASK; - if (debug) - printf("INT%c: %d\n", 'A'+i, irq); - irq_mode_pci(irq); + printf("Secondary bus number not initialized\n"); + continue; } + pcibus[ind].pb_needinit= 0; + + probe_bus(ind); + + /* Look for PCI bridges */ + do_pcibridge(ind); } - return 0; } /*===========================================================================* - * do_via_isabr * + * pci_intel_init * *===========================================================================*/ -static int do_via_isabr(int devind) +static void +pci_intel_init() { - int i, irq, edge; - u8_t levmask; + /* Try to detect a know PCI controller. Read the Vendor ID and + * the Device ID for function 0 of device 0. + * Two times the value 0xffff suggests a system without a (compatible) + * PCI controller. + */ + u32_t bus, dev, func; + u16_t vid, did; + int s, i, r, busind, busnr; + const char *dstr; - levmask= pci_attr_r8_u(devind, VIA_ISABR_EL); - irq= 0; /* lint */ - edge= 0; /* lint */ - for (i= 0; i<4; i++) + bus= 0; + dev= 0; + func= 0; + + vid= PCII_RREG16_(bus, dev, func, PCI_VID); + did= PCII_RREG16_(bus, dev, func, PCI_DID); + if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) + printf("PCI: warning, sys_outl failed: %d\n", s); + +#if 0 + if (vid == 0xffff && did == 0xffff) + return; /* Nothing here */ + + for (i= 0; pci_intel_ctrl[i].vid; i++) { - switch(i) + if (pci_intel_ctrl[i].vid == vid && + pci_intel_ctrl[i].did == did) { - case 0: - edge= (levmask & VIA_ISABR_EL_INTA); - irq= pci_attr_r8_u(devind, VIA_ISABR_IRQ_R2) >> 4; - break; - case 1: - edge= (levmask & VIA_ISABR_EL_INTB); - irq= pci_attr_r8_u(devind, VIA_ISABR_IRQ_R2); - break; - case 2: - edge= (levmask & VIA_ISABR_EL_INTC); - irq= pci_attr_r8_u(devind, VIA_ISABR_IRQ_R3) >> 4; - break; - case 3: - edge= (levmask & VIA_ISABR_EL_INTD); - irq= pci_attr_r8_u(devind, VIA_ISABR_IRQ_R1) >> 4; break; - default: - assert(0); - } - irq &= 0xf; - if (!irq) - { - if (debug) - printf("INT%c: disabled\n", 'A'+i); } - else + } + + if (!pci_intel_ctrl[i].vid) + { + printf("pci_intel_init (warning): unknown PCI-controller:\n" + "\tvendor %04X (%s), device %04X\n", + vid, pci_vid_name(vid), did); + } +#endif + + if (nr_pcibus >= NR_PCIBUS) + panic("too many PCI busses: %d", nr_pcibus); + busind= nr_pcibus; + nr_pcibus++; + pcibus[busind].pb_type= PBT_INTEL_HOST; + pcibus[busind].pb_needinit= 0; + pcibus[busind].pb_isabridge_dev= -1; + pcibus[busind].pb_isabridge_type= 0; + pcibus[busind].pb_devind= -1; + pcibus[busind].pb_busnr= 0; + pcibus[busind].pb_rreg8= pcii_rreg8; + pcibus[busind].pb_rreg16= pcii_rreg16; + pcibus[busind].pb_rreg32= pcii_rreg32; + pcibus[busind].pb_wreg8= pcii_wreg8; + pcibus[busind].pb_wreg16= pcii_wreg16; + pcibus[busind].pb_wreg32= pcii_wreg32; + pcibus[busind].pb_rsts= pcii_rsts; + pcibus[busind].pb_wsts= pcii_wsts; + + dstr= _pci_dev_name(vid, did); + if (!dstr) + dstr= "unknown device"; + if (debug) + { + printf("pci_intel_init: %s (%04X:%04X)\n", + dstr, vid, did); + } + + probe_bus(busind); + + r= do_isabridge(busind); + if (r != OK) + { + busnr= pcibus[busind].pb_busnr; + + /* Disable all devices for this bus */ + for (i= 0; irsp_nr_device; i++) { - if (pci_baseclass_table[i].baseclass == baseclass) - return pci_baseclass_table[i].name; + acl_sub_vid = aclp->rsp_device[i].sub_vid; + acl_sub_did = aclp->rsp_device[i].sub_did; + if (aclp->rsp_device[i].vid == pcidev[devind].pd_vid && + aclp->rsp_device[i].did == pcidev[devind].pd_did && + (acl_sub_vid == NO_SUB_VID || + acl_sub_vid == pcidev[devind].pd_sub_vid) && + (acl_sub_did == NO_SUB_DID || + acl_sub_did == pcidev[devind].pd_sub_did)) + { + return TRUE; + } } - return NULL; -} - -/*===========================================================================* - * pci_subclass_name * - *===========================================================================*/ -static char *pci_subclass_name(u8_t baseclass, u8_t subclass, u8_t infclass) -{ - int i; + if (!aclp->rsp_nr_class) + return FALSE; - for (i= 0; pci_subclass_table[i].name; i++) + class_id= (pcidev[devind].pd_baseclass << 16) | + (pcidev[devind].pd_subclass << 8) | + pcidev[devind].pd_infclass; + for (i= 0; irsp_nr_class; i++) { - if (pci_subclass_table[i].baseclass != baseclass) - continue; - if (pci_subclass_table[i].subclass != subclass) - continue; - if (pci_subclass_table[i].infclass != infclass && - pci_subclass_table[i].infclass != (u16_t)-1) + if (aclp->rsp_class[i].pciclass == + (class_id & aclp->rsp_class[i].mask)) { - continue; + return TRUE; } - return pci_subclass_table[i].name; } - return NULL; + + return FALSE; } /*===========================================================================* - * ntostr * + * sef_cb_init_fresh * *===========================================================================*/ -static void ntostr(n, str, end) -unsigned n; -char **str; -const char *end; +int +sef_cb_init_fresh(int type, sef_init_info_t *info) { - char tmpstr[20]; - int i; +/* Initialize the pci driver. */ + long v; + int i, r; + struct rprocpub rprocpub[NR_BOOT_PROCS]; - if (n == 0) - { - tmpstr[0]= '0'; - i= 1; + v= 0; + env_parse("pci_debug", "d", 0, &v, 0, 1); + debug= v; + + if (sys_getmachine(&machine)) { + printf("PCI: no machine\n"); + return ENODEV; } - else - { - for (i= 0; n; i++) - { - tmpstr[i]= '0' + (n%10); - n /= 10; - } + if (machine.apic_enabled && + ds_retrieve_label_endpt("acpi", &acpi_ep) != OK) { + panic("PCI: Cannot use APIC mode without ACPI!\n"); } - for (; i>0; i--) - { - if (*str == end) - { - break; + + /* Only Intel (compatible) PCI controllers are supported at the + * moment. + */ + pci_intel_init(); + + /* Map all the services in the boot image. */ + if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, + (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) { + panic("sys_safecopyfrom failed: %d", r); + } + for(i=0;i < NR_BOOT_PROCS;i++) { + if(rprocpub[i].in_use) { + if((r = map_service(&rprocpub[i])) != OK) { + panic("unable to map service: %d", r); + } } - **str= tmpstr[i-1]; - (*str)++; } - if (*str == end) - (*str)[-1]= '\0'; - else - **str= '\0'; + + return(OK); } /*===========================================================================* - * pci_attr_rsts * + * map_service * *===========================================================================*/ -static u16_t pci_attr_rsts(devind) -int devind; +int +map_service(struct rprocpub *rpub) { - int busnr, busind; +/* Map a new service by registering a new acl entry if required. */ + int i; - busnr= pcidev[devind].pd_busnr; - busind= get_busind(busnr); - return pcibus[busind].pb_rsts(busind); -} - + /* Stop right now if no pci device or class is found. */ + if(rpub->pci_acl.rsp_nr_device == 0 + && rpub->pci_acl.rsp_nr_class == 0) { + return(OK); + } -/*===========================================================================* - * pcibr_std_rsts * - *===========================================================================*/ -static u16_t pcibr_std_rsts(busind) -int busind; -{ - int devind; + /* Find a free acl slot. */ + for (i= 0; i= NR_DRIVERS) + { + printf("PCI: map_service: table is full\n"); + return ENOMEM; + } - devind= pcibus[busind].pb_devind; - return pci_attr_r16(devind, PPB_SSTS); + /* Initialize acl slot. */ + pci_acl[i].inuse = 1; + pci_acl[i].acl = rpub->pci_acl; + + return(OK); } /*===========================================================================* - * pcibr_std_wsts * + * _pci_find_dev * *===========================================================================*/ -static void pcibr_std_wsts(int busind, u16_t value) +int +_pci_find_dev(u8_t bus, u8_t dev, u8_t func, int *devindp) { int devind; - devind= pcibus[busind].pb_devind; + for (devind= 0; devind < nr_pcidev; devind++) + { + if (pcidev[devind].pd_busnr == bus && + pcidev[devind].pd_dev == dev && + pcidev[devind].pd_func == func) + { + break; + } + } + if (devind >= nr_pcidev) + return 0; #if 0 - printf("pcibr_std_wsts(%d, 0x%X), devind= %d\n", - busind, value, devind); + if (pcidev[devind].pd_inuse) + return 0; #endif - pci_attr_w16(devind, PPB_SSTS, value); -} - -/*===========================================================================* - * pcibr_cb_rsts * - *===========================================================================*/ -static u16_t pcibr_cb_rsts(busind) -int busind; -{ - int devind; - devind= pcibus[busind].pb_devind; - - return pci_attr_r16(devind, CBB_SSTS); + *devindp= devind; + return 1; } /*===========================================================================* - * pcibr_cb_wsts * + * _pci_first_dev * *===========================================================================*/ -static void pcibr_cb_wsts(int busind, u16_t value) +int +_pci_first_dev(struct rs_pci *aclp, int *devindp, u16_t *vidp, + u16_t *didp) { int devind; - devind= pcibus[busind].pb_devind; + for (devind= 0; devind < nr_pcidev; devind++) + { #if 0 - printf("pcibr_cb_wsts(%d, 0x%X), devind= %d\n", - busind, value, devind); + if (pcidev[devind].pd_inuse) + continue; #endif - pci_attr_w16(devind, CBB_SSTS, value); -} - -/*===========================================================================* - * pcibr_via_rsts * - *===========================================================================*/ -static u16_t pcibr_via_rsts(int busind) -{ - return 0; + if (!visible(aclp, devind)) + continue; + break; + } + if (devind >= nr_pcidev) + return 0; + *devindp= devind; + *vidp= pcidev[devind].pd_vid; + *didp= pcidev[devind].pd_did; + return 1; } /*===========================================================================* - * pcibr_via_wsts * + * _pci_next_dev * *===========================================================================*/ -static void pcibr_via_wsts(int busind, u16_t value) +int +_pci_next_dev(struct rs_pci *aclp, int *devindp, u16_t *vidp, u16_t *didp) { int devind; - devind= pcibus[busind].pb_devind; + for (devind= *devindp+1; devind < nr_pcidev; devind++) + { #if 0 - printf("pcibr_via_wsts(%d, 0x%X), devind= %d (not implemented)\n", - busind, value, devind); + if (pcidev[devind].pd_inuse) + continue; #endif + if (!visible(aclp, devind)) + continue; + break; + } + if (devind >= nr_pcidev) + return 0; + *devindp= devind; + *vidp= pcidev[devind].pd_vid; + *didp= pcidev[devind].pd_did; + return 1; } /*===========================================================================* - * pci_attr_wsts * + * _pci_reserve * *===========================================================================*/ -static void pci_attr_wsts(int devind, u16_t value) +int +_pci_reserve(int devind, endpoint_t proc, struct rs_pci *aclp) { - int busnr, busind; - - busnr= pcidev[devind].pd_busnr; - busind= get_busind(busnr); - pcibus[busind].pb_wsts(busind, value); -} - + int i, r; + int ilr; + struct io_range ior; + struct minix_mem_range mr; -/*===========================================================================* - * pcii_rreg8 * - *===========================================================================*/ -static u8_t pcii_rreg8(busind, devind, port) -int busind; -int devind; -int port; -{ - u8_t v; - int s; + if (devind < 0 || devind >= nr_pcidev) + { + printf("pci_reserve_a: bad devind: %d\n", devind); + return EINVAL; + } + if (!visible(aclp, devind)) + { + printf("pci_reserve_a: %u is not allowed to reserve %d\n", + proc, devind); + return EPERM; + } - v= PCII_RREG8_(pcibus[busind].pb_busnr, - pcidev[devind].pd_dev, pcidev[devind].pd_func, - port); - if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) - printf("PCI: warning, sys_outl failed: %d\n", s); -#if 0 - printf("pcii_rreg8(%d, %d, 0x%X): %d.%d.%d= 0x%X\n", - busind, devind, port, - pcibus[busind].pb_bus, pcidev[devind].pd_dev, - pcidev[devind].pd_func, v); -#endif - return v; -} + if(pcidev[devind].pd_inuse && pcidev[devind].pd_proc != proc) + return EBUSY; + pcidev[devind].pd_inuse= 1; + pcidev[devind].pd_proc= proc; -/*===========================================================================* - * pcii_rreg16 * - *===========================================================================*/ -static u16_t pcii_rreg16(int busind, int devind, int port) -{ - u16_t v; - int s; + for (i= 0; i= nr_pcidev) + return EINVAL; + + *vidp= pcidev[devind].pd_vid; + *didp= pcidev[devind].pd_did; + return OK; } /*===========================================================================* - * pcii_rsts * + * _pci_rescan_bus * *===========================================================================*/ -static u16_t pcii_rsts(int busind) +void +_pci_rescan_bus(u8_t busnr) { - u16_t v; - int s; + int busind; - v= PCII_RREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR); - if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) - printf("PCI: warning, sys_outl failed: %d\n", s); - return v; + busind= get_busind(busnr); + probe_bus(busind); + + /* Allocate bus numbers for uninitialized bridges */ + complete_bridges(); + + /* Allocate I/O and memory resources for uninitialized devices */ + complete_bars(); } /*===========================================================================* - * pcii_wsts * + * _pci_slot_name * *===========================================================================*/ -static void pcii_wsts(int busind, u16_t value) +int +_pci_slot_name(int devind, char **cpp) { - int s; - PCII_WREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR, value); - if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) - printf("PCI: warning, sys_outl failed: %d\n", s); -} + static char label[]= "ddd.ddd.ddd.ddd"; + char *end; + char *p; + if (devind < 0 || devind >= nr_pcidev) + return EINVAL; -/*===========================================================================* - * print_capabilities * - *===========================================================================*/ -static void print_capabilities(int devind) -{ - u8_t status, capptr, type, next, subtype; - char *str; + p= label; + end= label+sizeof(label); - /* Check capabilities bit in the device status register */ - status= pci_attr_r16(devind, PCI_SR); - if (!(status & PSR_CAPPTR)) - return; + /* FIXME: domain nb is always 0 on 32bit system, but we should + * retrieve it properly, somehow. */ + ntostr(0, &p, end); + *p++= '.'; - capptr= (pci_attr_r8_u(devind, PCI_CAPPTR) & PCI_CP_MASK); - while (capptr != 0) - { - type = pci_attr_r8_u(devind, capptr+CAP_TYPE); - next= (pci_attr_r8_u(devind, capptr+CAP_NEXT) & PCI_CP_MASK); - switch(type) - { - case 1: str= "PCI Power Management"; break; - case 2: str= "AGP"; break; - case 3: str= "Vital Product Data"; break; - case 4: str= "Slot Identification"; break; - case 5: str= "Message Signaled Interrupts"; break; - case 6: str= "CompactPCI Hot Swap"; break; - case 8: str= "AMD HyperTransport"; break; - case 0xf: str= "Secure Device"; break; - default: str= "(unknown type)"; break; - } + ntostr(pcidev[devind].pd_busnr, &p, end); + *p++= '.'; - printf(" @0x%x (0x%08x): capability type 0x%x: %s", - capptr, pci_attr_r32_u(devind, capptr), type, str); - if (type == 0x08) - print_hyper_cap(devind, capptr); - else if (type == 0x0f) - { - subtype= (pci_attr_r8_u(devind, capptr+2) & 0x07); - switch(subtype) - { - case 0: str= "Device Exclusion Vector"; break; - case 3: str= "IOMMU"; break; - default: str= "(unknown type)"; break; - } - printf(", sub type 0%o: %s", subtype, str); - } - printf("\n"); - capptr= next; - } -} + ntostr(pcidev[devind].pd_dev, &p, end); + *p++= '.'; + + ntostr(pcidev[devind].pd_func, &p, end); + *cpp= label; + return OK; +} /*===========================================================================* - * visible * + * _pci_dev_name * *===========================================================================*/ -static int visible(aclp, devind) -struct rs_pci *aclp; -int devind; +const char * +_pci_dev_name(u16_t vid, u16_t did) { - u16_t acl_sub_vid, acl_sub_did; int i; - u32_t class_id; - if (!aclp) - return TRUE; /* Should be changed when ACLs become - * mandatory. Do note that procfs relies - * on being able to see all devices. - */ - /* Check whether the caller is allowed to get this device. */ - for (i= 0; irsp_nr_device; i++) + for (i= 0; pci_device_table[i].name; i++) { - acl_sub_vid = aclp->rsp_device[i].sub_vid; - acl_sub_did = aclp->rsp_device[i].sub_did; - if (aclp->rsp_device[i].vid == pcidev[devind].pd_vid && - aclp->rsp_device[i].did == pcidev[devind].pd_did && - (acl_sub_vid == NO_SUB_VID || - acl_sub_vid == pcidev[devind].pd_sub_vid) && - (acl_sub_did == NO_SUB_DID || - acl_sub_did == pcidev[devind].pd_sub_did)) + if (pci_device_table[i].vid == vid && + pci_device_table[i].did == did) { - return TRUE; + return pci_device_table[i].name; } } - if (!aclp->rsp_nr_class) - return FALSE; + return NULL; +} - class_id= (pcidev[devind].pd_baseclass << 16) | - (pcidev[devind].pd_subclass << 8) | - pcidev[devind].pd_infclass; - for (i= 0; irsp_nr_class; i++) +/*===========================================================================* + * _pci_get_bar * + *===========================================================================*/ +int +_pci_get_bar(int devind, int port, u32_t *base, u32_t *size, + int *ioflag) +{ + int i, reg; + + if (devind < 0 || devind >= nr_pcidev) + return EINVAL; + + for (i= 0; i < pcidev[devind].pd_bar_nr; i++) { - if (aclp->rsp_class[i].pciclass == - (class_id & aclp->rsp_class[i].mask)) + reg= PCI_BAR+4*pcidev[devind].pd_bar[i].pb_nr; + + if (reg == port) { - return TRUE; + if (pcidev[devind].pd_bar[i].pb_flags & PBF_INCOMPLETE) + return EINVAL; + + *base= pcidev[devind].pd_bar[i].pb_base; + *size= pcidev[devind].pd_bar[i].pb_size; + *ioflag= + !!(pcidev[devind].pd_bar[i].pb_flags & PBF_IO); + return OK; } } + return EINVAL; +} - return FALSE; +/*===========================================================================* + * _pci_attr_r8 * + *===========================================================================*/ +int +_pci_attr_r8(int devind, int port, u8_t *vp) +{ + if (devind < 0 || devind >= nr_pcidev) + return EINVAL; + if (port < 0 || port > 256-1) + return EINVAL; + + *vp= __pci_attr_r8(devind, port); + return OK; } /*===========================================================================* - * print_hyper_cap * + * _pci_attr_r16 * *===========================================================================*/ -static void print_hyper_cap(int devind, u8_t capptr) -{ - u32_t v; - u16_t cmd; - int type0, type1; +int +_pci_attr_r16(int devind, int port, u16_t *vp) +{ + if (devind < 0 || devind >= nr_pcidev) + return EINVAL; + if (port < 0 || port > 256-2) + return EINVAL; - printf("\n"); - v= pci_attr_r32_u(devind, capptr); - printf("print_hyper_cap: @0x%x, off 0 (cap):", capptr); - cmd= (v >> 16) & 0xffff; -#if 0 - if (v & 0x10000) - { - printf(" WarmReset"); - v &= ~0x10000; - } - if (v & 0x20000) - { - printf(" DblEnded"); - v &= ~0x20000; - } - printf(" DevNum %d", (v & 0x7C0000) >> 18); - v &= ~0x7C0000; -#endif - type0= (cmd & 0xE000) >> 13; - type1= (cmd & 0xF800) >> 11; - if (type0 == 0 || type0 == 1) - { - printf("Capability Type: %s\n", - type0 == 0 ? "Slave or Primary Interface" : - "Host or Secondary Interface"); - cmd &= ~0xE000; - } - else - { - printf(" Capability Type 0x%x", type1); - cmd &= ~0xF800; - } - if (cmd) - printf(" undecoded 0x%x\n", cmd); + *vp= __pci_attr_r16(devind, port); + return OK; +} -#if 0 - printf("print_hyper_cap: off 4 (ctl): 0x%x\n", - pci_attr_r32_u(devind, capptr+4)); - printf("print_hyper_cap: off 8 (freq/rev): 0x%x\n", - pci_attr_r32_u(devind, capptr+8)); - printf("print_hyper_cap: off 12 (cap): 0x%x\n", - pci_attr_r32_u(devind, capptr+12)); - printf("print_hyper_cap: off 16 (buf count): 0x%x\n", - pci_attr_r32_u(devind, capptr+16)); - v= pci_attr_r32_u(devind, capptr+20); - printf("print_hyper_cap: @0x%x, off 20 (bus nr): ", - capptr+20); - printf("prim %d", v & 0xff); - printf(", sec %d", (v >> 8) & 0xff); - printf(", sub %d", (v >> 16) & 0xff); - if (v >> 24) - printf(", reserved %d", (v >> 24) & 0xff); - printf("\n"); - printf("print_hyper_cap: off 24 (type): 0x%x\n", - pci_attr_r32_u(devind, capptr+24)); -#endif +/*===========================================================================* + * _pci_attr_r32 * + *===========================================================================*/ +int +_pci_attr_r32(int devind, int port, u32_t *vp) +{ + if (devind < 0 || devind >= nr_pcidev) + return EINVAL; + if (port < 0 || port > 256-4) + return EINVAL; + + *vp= __pci_attr_r32(devind, port); + return OK; } -/* - * $PchId: pci.c,v 1.7 2003/08/07 09:06:51 philip Exp $ - */ +/*===========================================================================* + * _pci_attr_w8 * + *===========================================================================*/ +int +_pci_attr_w8(int devind, int port, u8_t value) +{ + if (devind < 0 || devind >= nr_pcidev) + return EINVAL; + if (port < 0 || port > 256-1) + return EINVAL; + + __pci_attr_w8(devind, port, value); + return OK; +} + +/*===========================================================================* + * _pci_attr_w16 * + *===========================================================================*/ +int +_pci_attr_w16(int devind, int port, u16_t value) +{ + if (devind < 0 || devind >= nr_pcidev) + return EINVAL; + if (port < 0 || port > 256-2) + return EINVAL; + + __pci_attr_w16(devind, port, value); + return OK; +} + +/*===========================================================================* + * _pci_attr_w32 * + *===========================================================================*/ +int +_pci_attr_w32(int devind, int port, u32_t value) +{ + if (devind < 0 || devind >= nr_pcidev) + return EINVAL; + if (port < 0 || port > 256-4) + return EINVAL; + + __pci_attr_w32(devind, port, value); + return OK; +} diff --git a/minix/drivers/bus/pci/pci.h b/minix/drivers/bus/pci/pci.h index 1aac8d373..e3c6fd383 100644 --- a/minix/drivers/bus/pci/pci.h +++ b/minix/drivers/bus/pci/pci.h @@ -4,36 +4,23 @@ pci.h Created: Jan 2000 by Philip Homburg */ -#include -#include -#include - -/* tempory functions: to be replaced later (see pci_intel.h) */ -unsigned pci_inb(u16_t port); -unsigned pci_inw(u16_t port); -unsigned pci_inl(u16_t port); - -void pci_outb(u16_t port, u8_t value); -void pci_outw(u16_t port, u16_t value); -void pci_outl(u16_t port, u32_t value); - struct pci_vendor { u16_t vid; - char *name; + const char *name; }; struct pci_device { u16_t vid; u16_t did; - char *name; + const char *name; }; struct pci_baseclass { u8_t baseclass; - char *name; + const char *name; }; struct pci_subclass @@ -41,7 +28,7 @@ struct pci_subclass u8_t baseclass; u8_t subclass; u16_t infclass; - char *name; + const char *name; }; struct pci_intel_ctrl @@ -83,6 +70,8 @@ struct pci_acl /* Still needed? */ #define PCI_AGPB_VIA 3 /* VIA compatible AGP bridge */ +extern int debug; + extern struct pci_vendor pci_vendor_table[]; extern struct pci_device pci_device_table[]; extern struct pci_baseclass pci_baseclass_table[]; @@ -92,24 +81,36 @@ extern struct pci_intel_ctrl pci_intel_ctrl[]; #endif extern struct pci_isabridge pci_isabridge[]; extern struct pci_pcibridge pci_pcibridge[]; +extern struct pci_acl pci_acl[NR_DRIVERS]; /* Function prototypes. */ int sef_cb_init_fresh(int type, sef_init_info_t *info); int map_service(struct rprocpub *rpub); -int pci_reserve_a(int devind, endpoint_t proc, struct rs_pci *aclp); -void pci_release(endpoint_t proc); -int pci_first_dev_a(struct rs_pci *aclp, int *devindp, u16_t *vidp, + +int _pci_reserve(int devind, endpoint_t proc, struct rs_pci *aclp); +void _pci_release(endpoint_t proc); + +int _pci_first_dev(struct rs_pci *aclp, int *devindp, u16_t *vidp, u16_t *didp); -int pci_next_dev_a(struct rs_pci *aclp, int *devindp, u16_t *vidp, u16_t +int _pci_next_dev(struct rs_pci *aclp, int *devindp, u16_t *vidp, u16_t *didp); +int _pci_find_dev(u8_t bus, u8_t dev, u8_t func, int *devindp); -int pci_attr_r8_s(int devind, int port, u8_t *vp); -int pci_attr_r32_s(int devind, int port, u32_t *vp); -int pci_get_bar_s(int devind, int port, u32_t *base, u32_t *size, int - *ioflag); -int pci_slot_name_s(int devind, char **cpp); -int pci_ids_s(int devind, u16_t *vidp, u16_t *didp); +void _pci_rescan_bus(u8_t busnr); +const char *_pci_dev_name(u16_t vid, u16_t did); -/* - * $PchId: pci.h,v 1.4 2001/12/06 20:21:22 philip Exp $ - */ + +int _pci_get_bar(int devind, int port, u32_t *base, u32_t *size, int + *ioflag); +int _pci_slot_name(int devind, char **cpp); +int _pci_ids(int devind, u16_t *vidp, u16_t *didp); + +/* PCI Config Read functions */ +int _pci_attr_r8(int devind, int port, u8_t *vp); +int _pci_attr_r16(int devind, int port, u16_t *vp); +int _pci_attr_r32(int devind, int port, u32_t *vp); + +/* PCI Config Write functions */ +int _pci_attr_w8(int devind, int port, u8_t value); +int _pci_attr_w16(int devind, int port, u16_t value); +int _pci_attr_w32(int devind, int port, u32_t value); diff --git a/minix/drivers/bus/pci/pci_table.c b/minix/drivers/bus/pci/pci_table.c index e468f2948..3182282ee 100644 --- a/minix/drivers/bus/pci/pci_table.c +++ b/minix/drivers/bus/pci/pci_table.c @@ -14,10 +14,9 @@ See the Linux PCI ID Repository . */ #include +#include + #include "pci.h" -#if __minix_vmd -#include "config.h" -#endif struct pci_vendor pci_vendor_table[]= {