📄 pci.c
字号:
#define USER_SPACE 1/*pci.cConfigure devices on the PCI busCreated: Jan 2000 by Philip Homburg <philip@cs.vu.nl>*/#include "../drivers.h"#define NDEBUG /* disable assertions */#include <assert.h>#include <minix/com.h>#include <minix/syslib.h>#include "pci.h"#include "pci_amd.h"#include "pci_intel.h"#include "pci_sis.h"#include "pci_via.h"#if __minix_vmd#include "config.h"#endif#if !__minix_vmd#define irq_mode_pci(irq) ((void)0)#endif#include <stdlib.h>#include <stdio.h>#include <string.h>#include <minix/sysutil.h>#define NR_PCIBUS 4#define NR_PCIDEV 40#define PBT_INTEL 1#define PBT_PCIBRIDGE 2PRIVATE int debug= 0;PRIVATE struct pcibus{ int pb_type; int pb_isabridge_dev; int pb_isabridge_type; int pb_devind; int pb_bus; u8_t (*pb_rreg8)(int busind, int devind, int port); u16_t (*pb_rreg16)(int busind, int devind, int port); u32_t (*pb_rreg32)(int busind, int devind, int port); void (*pb_wreg16)(int busind, int devind, int port, U16_t value); void (*pb_wreg32)(int busind, int devind, int port, u32_t value); u16_t (*pb_rsts)(int busind); void (*pb_wsts)(int busind, U16_t value);} pcibus[NR_PCIBUS];PRIVATE int nr_pcibus= 0;PRIVATE struct pcidev{ u8_t pd_busind; u8_t pd_dev; u8_t pd_func; u8_t pd_baseclass; u8_t pd_subclass; u8_t pd_infclass; u16_t pd_vid; u16_t pd_did; u8_t pd_inuse;} pcidev[NR_PCIDEV];PRIVATE int nr_pcidev= 0;/* Work around the limitation of the PCI emulation in QEMU 0.7.1 */PRIVATE int qemu_pci= 0;FORWARD _PROTOTYPE( void pci_intel_init, (void) );FORWARD _PROTOTYPE( void probe_bus, (int busind) );FORWARD _PROTOTYPE( int do_isabridge, (int busind) );FORWARD _PROTOTYPE( void do_pcibridge, (int busind) );FORWARD _PROTOTYPE( int do_piix, (int devind) );FORWARD _PROTOTYPE( int do_amd_isabr, (int devind) );FORWARD _PROTOTYPE( int do_sis_isabr, (int devind) );FORWARD _PROTOTYPE( int do_via_isabr, (int devind) );FORWARD _PROTOTYPE( char *pci_vid_name, (U16_t vid) );FORWARD _PROTOTYPE( char *pci_baseclass_name, (U8_t baseclass) );FORWARD _PROTOTYPE( char *pci_subclass_name, (U8_t baseclass, U8_t subclass, U8_t infclass) );FORWARD _PROTOTYPE( void ntostr, (unsigned n, char **str, char *end) );FORWARD _PROTOTYPE( u16_t pci_attr_rsts, (int devind) );FORWARD _PROTOTYPE( void pci_attr_wsts, (int devind, U16_t value) );FORWARD _PROTOTYPE( u16_t pcibr_intel_rsts, (int busind) );FORWARD _PROTOTYPE( void pcibr_intel_wsts, (int busind, U16_t value) );FORWARD _PROTOTYPE( u16_t pcibr_via_rsts, (int busind) );FORWARD _PROTOTYPE( void pcibr_via_wsts, (int busind, U16_t value) );FORWARD _PROTOTYPE( u8_t pcii_rreg8, (int busind, int devind, int port) );FORWARD _PROTOTYPE( u16_t pcii_rreg16, (int busind, int devind, int port) );FORWARD _PROTOTYPE( u32_t pcii_rreg32, (int busind, int devind, int port) );FORWARD _PROTOTYPE( void pcii_wreg16, (int busind, int devind, int port, U16_t value) );FORWARD _PROTOTYPE( void pcii_wreg32, (int busind, int devind, int port, u32_t value) );FORWARD _PROTOTYPE( u16_t pcii_rsts, (int busind) );FORWARD _PROTOTYPE( void pcii_wsts, (int busind, U16_t value) );/*===========================================================================* * helper functions for I/O * *===========================================================================*/PUBLIC unsigned pci_inb(U16_t port) { U8_t value; int s; if ((s=sys_inb(port, &value)) !=OK) printf("PCI: warning, sys_inb failed: %d\n", s); return value;}PUBLIC unsigned pci_inw(U16_t port) { U16_t value; int s; if ((s=sys_inw(port, &value)) !=OK) printf("PCI: warning, sys_inw failed: %d\n", s); return value;}PUBLIC 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;}PUBLIC 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);}PUBLIC 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);}PUBLIC 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_init * *===========================================================================*/PUBLIC void pci_init(){ static int first_time= 1; long v; if (!first_time) return; v= 0; env_parse("qemu_pci", "d", 0, &v, 0, 1); qemu_pci= v; v= 0; env_parse("pci_debug", "d", 0, &v, 0, 1); debug= v; /* We don't expect to interrupted */ assert(first_time == 1); first_time= -1; /* Only Intel (compatible) PCI controllers are supported at the * moment. */ pci_intel_init(); first_time= 0;}/*===========================================================================* * pci_find_dev * *===========================================================================*/PUBLIC int pci_find_dev(bus, dev, func, devindp)u8_t bus;u8_t dev;u8_t func;int *devindp;{ int devind; for (devind= 0; devind < nr_pcidev; devind++) { if (pcidev[devind].pd_busind == bus && pcidev[devind].pd_dev == dev && pcidev[devind].pd_func == func) { break; } } if (devind >= nr_pcidev) return 0; if (pcidev[devind].pd_inuse) return 0; *devindp= devind; return 1;}/*===========================================================================* * pci_first_dev * *===========================================================================*/PUBLIC int pci_first_dev(devindp, vidp, didp)int *devindp;u16_t *vidp;u16_t *didp;{ int devind; for (devind= 0; devind < nr_pcidev; devind++) { if (!pcidev[devind].pd_inuse) break; } if (devind >= nr_pcidev) return 0; *devindp= devind; *vidp= pcidev[devind].pd_vid; *didp= pcidev[devind].pd_did; return 1;}/*===========================================================================* * pci_next_dev * *===========================================================================*/PUBLIC int pci_next_dev(devindp, vidp, didp)int *devindp;u16_t *vidp;u16_t *didp;{ int devind; for (devind= *devindp+1; devind < nr_pcidev; devind++) { if (!pcidev[devind].pd_inuse) break; } if (devind >= nr_pcidev) return 0; *devindp= devind; *vidp= pcidev[devind].pd_vid; *didp= pcidev[devind].pd_did; return 1;}/*===========================================================================* * pci_reserve * *===========================================================================*/PUBLIC void pci_reserve(devind)int devind;{ assert(devind <= nr_pcidev); assert(!pcidev[devind].pd_inuse); pcidev[devind].pd_inuse= 1;}/*===========================================================================* * pci_ids * *===========================================================================*/PUBLIC void pci_ids(devind, vidp, didp)int devind;u16_t *vidp;u16_t *didp;{ assert(devind <= nr_pcidev); *vidp= pcidev[devind].pd_vid; *didp= pcidev[devind].pd_did;}/*===========================================================================* * pci_slot_name * *===========================================================================*/PUBLIC char *pci_slot_name(devind)int devind;{ static char label[]= "ddd.ddd.ddd"; char *end; char *p; p= label; end= label+sizeof(label); ntostr(pcidev[devind].pd_busind, &p, end); *p++= '.'; ntostr(pcidev[devind].pd_dev, &p, end); *p++= '.'; ntostr(pcidev[devind].pd_func, &p, end); return label;}/*===========================================================================* * pci_dev_name * *===========================================================================*/PUBLIC char *pci_dev_name(vid, did)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_attr_r8 * *===========================================================================*/PUBLIC u8_t pci_attr_r8(devind, port)int devind;int port;{ int busind; busind= pcidev[devind].pd_busind; return pcibus[busind].pb_rreg8(busind, devind, port);}/*===========================================================================* * pci_attr_r16 * *===========================================================================*/PUBLIC u16_t pci_attr_r16(devind, port)int devind;int port;{ int busind; busind= pcidev[devind].pd_busind; return pcibus[busind].pb_rreg16(busind, devind, port);}/*===========================================================================* * pci_attr_r32 * *===========================================================================*/PUBLIC u32_t pci_attr_r32(devind, port)int devind;int port;{ int busind; busind= pcidev[devind].pd_busind; return pcibus[busind].pb_rreg32(busind, devind, port);}/*===========================================================================* * pci_attr_w16 * *===========================================================================*/PUBLIC void pci_attr_w16(devind, port, value)int devind;int port;u16_t value;{ int busind; busind= pcidev[devind].pd_busind; pcibus[busind].pb_wreg16(busind, devind, port, value);}/*===========================================================================* * pci_attr_w32 * *===========================================================================*/PUBLIC void pci_attr_w32(devind, port, value)int devind;int port;u32_t value;{ int busind; busind= pcidev[devind].pd_busind; pcibus[busind].pb_wreg32(busind, devind, port, value);}/*===========================================================================* * pci_intel_init * *===========================================================================*/PRIVATE void pci_intel_init(){ /* 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. Only controllers with values listed in the table * pci_intel_ctrl are actually used. */ u32_t bus, dev, func; u16_t vid, did; int s, i, r, busind; char *dstr; bus= 0; dev= 0; func= 0; vid= PCII_RREG16_(bus, dev, func, PCI_VID); did= PCII_RREG16_(bus, dev, func, PCI_DID);#if USER_SPACE if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL))) printf("PCI: warning, sys_outl failed: %d\n", s);#else outl(PCII_CONFADD, PCII_UNSEL);#endif if (vid == 0xffff && did == 0xffff) return; /* Nothing here */ for (i= 0; pci_intel_ctrl[i].vid; i++) { if (pci_intel_ctrl[i].vid == vid && pci_intel_ctrl[i].did == did) { break; } } 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); } if (nr_pcibus >= NR_PCIBUS) panic("PCI","too many PCI busses", nr_pcibus); busind= nr_pcibus; nr_pcibus++; pcibus[busind].pb_type= PBT_INTEL; pcibus[busind].pb_isabridge_dev= -1; pcibus[busind].pb_isabridge_type= 0; pcibus[busind].pb_devind= -1; pcibus[busind].pb_bus= 0; pcibus[busind].pb_rreg8= pcii_rreg8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -