From e9c21377d8732b8b9dcae050d147eaf6ffde35ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Fr=C3=B6schle?= Date: Fri, 20 Nov 2015 21:25:07 +0000 Subject: [PATCH] new revision of BaS native PCI driver that supports find_pci_device() and find_pci_classcode() functions from TOS --- BaS_gcc.files | 1 + BaS_gcc.includes | 1 + if/driver_vec.c | 25 ++- include/driver_vec.h | 19 ++- tos/pci_test/include/driver_vec.h | 6 +- tos/pci_test/include/pci.h | 242 ++++++++++++++++++++++++++++++ tos/pci_test/sources/pci_test.c | 34 ++++- 7 files changed, 323 insertions(+), 5 deletions(-) create mode 100644 tos/pci_test/include/pci.h diff --git a/BaS_gcc.files b/BaS_gcc.files index b874fef..2c483f2 100644 --- a/BaS_gcc.files +++ b/BaS_gcc.files @@ -608,3 +608,4 @@ tos/pci_test/include/MCF5475_SRAM.h tos/pci_test/include/MCF5475_USB.h tos/pci_test/include/MCF5475_XLB.h tos/pci_test/include/MCF5475.h +tos/pci_test/include/pci.h diff --git a/BaS_gcc.includes b/BaS_gcc.includes index bb1dc3c..3beba8b 100644 --- a/BaS_gcc.includes +++ b/BaS_gcc.includes @@ -1,5 +1,6 @@ include tos/jtagwait/include +tos/pci_test/include /usr/m68k-atari-mint/include dma m54455 diff --git a/if/driver_vec.c b/if/driver_vec.c index eaa0bc1..8b5bd9a 100644 --- a/if/driver_vec.c +++ b/if/driver_vec.c @@ -124,7 +124,7 @@ static struct pci_bios_interface pci_interface = .phys_to_virt = wrapper_phys_to_virt, }; -static struct pci_native_driver_interface pci_native_interface = +static struct pci_native_driver_interface_0_1 pci_native_interface_0_1 = { .pci_read_config_longword = pci_read_config_longword, .pci_read_config_word = pci_read_config_word, @@ -137,6 +137,20 @@ static struct pci_native_driver_interface pci_native_interface = .pci_get_resource = pci_get_resource, }; +static struct pci_native_driver_interface pci_native_interface = +{ + .pci_read_config_longword = pci_read_config_longword, + .pci_read_config_word = pci_read_config_word, + .pci_read_config_byte = pci_read_config_byte, + .pci_write_config_longword = pci_write_config_longword, + .pci_write_config_word = pci_write_config_word, + .pci_write_config_byte = pci_write_config_byte, + .pci_hook_interrupt = pci_hook_interrupt, + .pci_unhook_interrupt = pci_unhook_interrupt, + .pci_find_device = pci_find_device, + .pci_find_classcode = pci_find_classcode, + .pci_get_resource = pci_get_resource, +}; /* * driver interface struct for the BaS framebuffer video driver */ @@ -206,8 +220,17 @@ static struct generic_interface interfaces[] = .description = "BaS PCI native", .version = 0, .revision = 1, + .interface.pci_native = (struct pci_native_driver_interface *) &pci_native_interface_0_1, + }, + { + .type = PCI_NATIVE_DRIVER, + .name = "PCI_N", + .description = "BaS PCI native", + .version = 0, + .revision = 2, .interface.pci_native = &pci_native_interface, }, + /* insert new drivers here */ { diff --git a/include/driver_vec.h b/include/driver_vec.h index 61a7ae8..9c83a6a 100644 --- a/include/driver_vec.h +++ b/include/driver_vec.h @@ -271,7 +271,7 @@ struct mmu_driver_interface uint32_t (*report_pagesize)(void); }; -struct pci_native_driver_interface +struct pci_native_driver_interface_0_1 { uint32_t (*pci_read_config_longword)(int32_t handle, int offset); uint16_t (*pci_read_config_word)(int32_t handle, int offset); @@ -286,6 +286,22 @@ struct pci_native_driver_interface struct pci_rd * (*pci_get_resource)(int32_t handle); }; +struct pci_native_driver_interface +{ + uint32_t (*pci_read_config_longword)(int32_t handle, int offset); + uint16_t (*pci_read_config_word)(int32_t handle, int offset); + uint8_t (*pci_read_config_byte)(int32_t handle, int offset); + + int32_t (*pci_write_config_longword)(int32_t handle, int offset, uint32_t value); + int32_t (*pci_write_config_word)(int32_t handle, int offset, uint16_t value); + int32_t (*pci_write_config_byte)(int32_t handle, int offset, uint8_t value); + int32_t (*pci_hook_interrupt)(int32_t handle, void *handler, void *parameter); + int32_t (*pci_unhook_interrupt)(int32_t handle); + int32_t (*pci_find_device)(uint16_t device_id, uint16_t vendor_id, int index); + int32_t (*pci_find_classcode)(uint32_t classcode, int index); + struct pci_rd * (*pci_get_resource)(int32_t handle); +}; + union interface { struct generic_driver_interface *gdi; @@ -294,6 +310,7 @@ union interface struct framebuffer_driver_interface *fb; struct pci_bios_interface *pci; struct mmu_driver_interface *mmu; + struct pci_native_driver_interface_0_1 *pci_native_0_1; struct pci_native_driver_interface *pci_native; }; diff --git a/tos/pci_test/include/driver_vec.h b/tos/pci_test/include/driver_vec.h index 86f59ff..06220ef 100644 --- a/tos/pci_test/include/driver_vec.h +++ b/tos/pci_test/include/driver_vec.h @@ -25,6 +25,8 @@ #ifndef _DRIVER_VEC_H_ #define _DRIVER_VEC_H_ +#include "pci.h" + enum driver_type { BLOCKDEV_DRIVER, @@ -205,7 +207,6 @@ struct framebuffer_driver_interface struct fb_info **framebuffer_info; /* pointer to an fb_info struct (defined in include/fb.h) */ }; -typedef void *PCI_CONV_ADR; struct pci_bios_interface { @@ -280,7 +281,8 @@ struct pci_native_driver_interface int32_t (*pci_write_config_byte)(int32_t handle, int offset, uint8_t value); int32_t (*pci_hook_interrupt)(int32_t handle, void *handler, void *parameter); int32_t (*pci_unhook_interrupt)(int32_t handle); - + int32_t (*pci_find_device)(uint16_t device_id, uint16_t vendor_id, int index); + int32_t (*pci_find_classcode)(uint32_t classcode, int index); struct pci_rd * (*pci_get_resource)(int32_t handle); }; diff --git a/tos/pci_test/include/pci.h b/tos/pci_test/include/pci.h new file mode 100644 index 0000000..cdacfa2 --- /dev/null +++ b/tos/pci_test/include/pci.h @@ -0,0 +1,242 @@ +#ifndef _PCI_H_ +#define _PCI_H_ + +/* + * This file is part of BaS_gcc. + * + * BaS_gcc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BaS_gcc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with BaS_gcc. If not, see . + * + * Created on: 26.02.2013 + * Author: Markus Fröschle + */ + + +#define PCI_MEMORY_OFFSET 0x80000000 +#define PCI_MEMORY_SIZE 0x40000000 /* 1 GByte PCI memory window */ +#define PCI_IO_OFFSET 0xD0000000 +#define PCI_IO_SIZE 0x10000000 /* 128 MByte PCI I/O window */ + +/* + * Note: the byte offsets are in little endian format, so you can't use them + * on byteswapped (Motorola format) values! + */ +#define PCIIDR 0x00 /* PCI Configuration ID Register */ +#define PCICSR 0x04 /* PCI Command/Status Register */ +#define PCICR 0x04 /* PCI Command Register */ +#define PCISR 0x06 /* PCI Status Register */ +#define PCIREV 0x08 /* PCI Revision ID Register */ +#define PCICCR 0x0B /* PCI Class Code Register */ +#define PCICLSR 0x0C /* PCI Cache Line Size Register */ +#define PCILTR 0x0D /* PCI Latency Timer Register */ +#define PCIHTR 0x0E /* PCI Header Type Register */ +#define PCIBISTR 0x0F /* PCI Build-In Self Test Register */ +#define PCIBAR0 0x10 /* PCI Base Address Register for Memory + Accesses to Local, Runtime, and DMA */ +#define PCIBAR1 0x14 /* PCI Base Address Register for I/O + Accesses to Local, Runtime, and DMA */ +#define PCIBAR2 0x18 /* PCI Base Address Register for Memory + Accesses to Local Address Space 0 */ +#define PCIBAR3 0x1C /* PCI Base Address Register for Memory + Accesses to Local Address Space 1 */ +#define PCIBAR4 0x20 /* PCI Base Address Register, reserved */ +#define PCIBAR5 0x24 /* PCI Base Address Register, reserved */ +#define PCICIS 0x28 /* PCI Cardbus CIS Pointer, not support*/ +#define PCISVID 0x2E /* PCI Subsystem Vendor ID */ +#define PCISID 0x2E /* PCI Subsystem ID */ +#define PCIERBAR 0x30 /* PCI Expansion ROM Base Register */ +#define CAP_PTR 0x34 /* New Capability Pointer */ +#define PCIILR 0x3C /* PCI Interrupt Line Register */ +#define PCIIPR 0x3D /* PCI Interrupt Pin Register */ +#define PCIMGR 0x3E /* PCI Min_Gnt Register */ +#define PCIMLR 0x3F /* PCI Max_Lat Register */ +#define PMCAPID 0x40 /* Power Management Capability ID */ +#define PMNEXT 0x41 /* Power Management Next Capability + Pointer */ +#define PMC 0x42 /* Power Management Capabilities */ +#define PMCSR 0x44 /* Power Management Control/Status */ +#define PMCSR_BSE 0x46 /* PMCSR Bridge Support Extensions */ +#define PMDATA 0x47 /* Power Management Data */ +#define HS_CNTL 0x48 /* Hot Swap Control */ +#define HS_NEXT 0x49 /* Hot Swap Next Capability Pointer */ +#define HS_CSR 0x4A /* Hot Swap Control/Status */ +#define PVPDCNTL 0x4C /* PCI Vital Product Data Control */ +#define PVPD_NEXT 0x4D /* PCI Vital Product Data Next + Capability Pointer */ +#define PVPDAD 0x4E /* PCI Vital Product Data Address */ +#define PVPDATA 0x50 /* PCI VPD Data */ + +/* + * bit definitions for PCICSR lower half (Command Register) + */ +#define PCICSR_IO (1 << 0) /* if set: device responds to I/O space accesses */ +#define PCICSR_MEMORY (1 << 1) /* if set: device responds to memory space accesses */ +#define PCICSR_MASTER (1 << 2) /* if set: device is master */ +#define PCICSR_SPECIAL (1 << 3) /* if set: device reacts on special cycles */ +#define PCICSR_MEMWI (1 << 4) /* if set: device deals with memory write and invalidate */ +#define PCICSR_VGA_SNOOP (1 << 5) /* if set: capable of palette snoop */ +#define PCICSR_PERR (1 << 6) /* if set: reacts to parity errors */ +#define PCICSR_STEPPING (1 << 7) /* if set: stepping enabled */ +#define PCICSR_SERR (1 << 8) /* if set: SERR pin enabled */ +#define PCICSR_FAST_BTOB_E (1 << 9) /* if set: fast back-to-back enabled */ +#define PCICSR_INT_DISABLE (1 << 10) /* if set: disable interrupts from this device */ +/* + * bit definitions for PCICSR upper half (Status Register) + */ +#define PCICSR_INTERRUPT (1 << 3) /* device requested interrupt */ +#define PCICSR_CAPABILITIES (1 << 4) /* if set, capabilities pointer is valid */ +#define PCICSR_66MHZ (1 << 5) /* 66 MHz capable */ +#define PCICSR_UDF (1 << 6) /* UDF supported */ +#define PCICSR_FAST_BTOB (1 << 7) /* Fast back-to-back enabled */ +#define PCICSR_DPARITY_ERROR (1 << 8) /* data parity error detected */ + +#define PCICSR_T_ABORT_S (1 << 11) /* target abort signaled */ +#define PCICSR_T_ABORT_R (1 << 12) /* target abort received */ +#define PCICSR_M_ABORT_R (1 << 13) /* master abort received */ +#define PCICSR_S_ERROR_S (1 << 14) /* system error signaled */ +#define PCICSR_PARITY_ERR (1 << 15) /* data parity error */ + +/* Header type 1 (PCI-to-PCI bridges) */ +#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ +#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ +#define PCI_SUBORDINATE_BUS 0x1A /* Highest bus number behind the bridge */ +#define PCI_SEC_LATENCY_TIMER 0x1B /* Latency timer for secondary interface */ +#define PCI_IO_BASE 0x1C /* I/O range behind the bridge */ +#define PCI_IO_LIMIT 0x1D +#define PCI_SEC_STATUS 0x1E /* Secondary status register, only bit 14 used */ +#define PCI_MEMORY_BASE 0x20 /* Memory range behind */ +#define PCI_MEMORY_LIMIT 0x22 +#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ +#define PCI_PREF_MEMORY_LIMIT 0x26 +#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ +#define PCI_PREF_LIMIT_UPPER32 0x2C +#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */ +#define PCI_IO_LIMIT_UPPER16 0x32 +#define PCI_BRIDGE_CONTROL 0x3E /* Bridge Control */ + +struct pci_rd /* structure of resource descriptor */ +{ + unsigned short next; /* length of the following structure */ + unsigned short flags; /* type of resource and misc. flags */ + unsigned long start; /* start-address of resource */ + unsigned long length; /* length of resource */ + unsigned long offset; /* offset PCI to phys. CPU Address */ + unsigned long dmaoffset; /* offset for DMA-transfers */ +}; + +typedef struct /* structure of address conversion */ +{ + unsigned long adr; /* calculated address (CPU<->PCI) */ + unsigned long len; /* length of memory range */ +} PCI_CONV_ADR; + +/******************************************************************************/ +/* PCI-BIOS Error Codes */ +/******************************************************************************/ +#define PCI_SUCCESSFUL 0 /* everything's fine */ +#define PCI_FUNC_NOT_SUPPORTED -2 /* function not supported */ +#define PCI_BAD_VENDOR_ID -3 /* wrong Vendor ID */ +#define PCI_DEVICE_NOT_FOUND -4 /* PCI-Device not found */ +#define PCI_BAD_REGISTER_NUMBER -5 /* wrong register number */ +#define PCI_SET_FAILED -6 /* reserved for later use */ +#define PCI_BUFFER_TOO_SMALL -7 /* reserved for later use */ +#define PCI_GENERAL_ERROR -8 /* general BIOS error code */ +#define PCI_BAD_HANDLE -9 /* wrong/unknown PCI-handle */ + +/******************************************************************************/ +/* Flags used in Resource-Descriptor */ +/******************************************************************************/ +#define FLG_IO 0x4000 /* Ressource in IO range */ +#define FLG_ROM 0x2000 /* Expansion ROM */ +#define FLG_LAST 0x8000 /* last ressource */ +#define FLG_8BIT 0x0100 /* 8 bit accesses allowed */ +#define FLG_16BIT 0x0200 /* 16 bit accesses allowed */ +#define FLG_32BIT 0x0400 /* 32 bit accesses allowed */ +#define FLG_ENDMASK 0x000F /* mask for byte ordering */ + +/******************************************************************************/ +/* Values used in FLG_ENDMASK for Byte Ordering */ +/******************************************************************************/ +#define ORD_MOTOROLA 0 /* Motorola (big endian) */ +#define ORD_INTEL_AS 1 /* Intel (little endian), addr.swapped */ +#define ORD_INTEL_LS 2 /* Intel (little endian), lane swapped */ +#define ORD_UNKNOWN 15 /* unknown (BIOS-calls allowed only) */ + +/******************************************************************************/ +/* Status Info used in Device-Descriptor */ +/******************************************************************************/ +#define DEVICE_FREE 0 /* Device is not used */ +#define DEVICE_USED 1 /* Device is used by another driver */ +#define DEVICE_CALLBACK 2 /* used, but driver can be cancelled */ +#define DEVICE_AVAILABLE 3 /* used, not available */ +#define NO_DEVICE -1 /* no device detected */ + +/* PCI configuration space macros */ + +/* register 0x00 macros */ +#define PCI_VENDOR_ID(i) swpw((uint16_t)(((i) & 0xffff0000) >> 16)) +#define PCI_DEVICE_ID(i) swpw((uint16_t) ((i) & 0xffff)) + +/* register 0x04 macros */ +#define PCI_STATUS(i) ((i) & 0xffff) +#define PCI_COMMAND(i) (((i) >> 16) & 0xffff) + +/* register 0x08 macros */ +#define PCI_CLASS_CODE(i) ((swpl((i)) & 0xff000000) >> 24) +#define PCI_SUBCLASS(i) ((swpl((i)) & 0xffff0000) >> 16) +#define PCI_PROG_IF(i) ((swpl((i)) & 0x0000ff00) >> 8) +#define PCI_REVISION_ID(i) ((swpl((i)) & 0x000000ff)) + +/* register 0x0c macros */ +#define PCI_BIST(i) ((swpl((i)) & 0xff000000) >> 24) +#define PCI_HEADER_TYPE(i) ((swpl((i)) & 0x00ff0000) >> 16) +#define PCI_LAT_TIMER(i) ((swpl((i)) & 0x0000ff00) >> 8) +#define PCI_CACHELINE_SIZE(i) ((swpl((i)) & 0x000000ff)) + +/* register 0x2c macros */ +#define PCI_SUBSYS_ID(i) (((i) & 0xffff0000) >> 16) +#define PCI_SUBSYS_VID(i) (((i) & 0xffff)) + +/* register 0x34 macros */ +#define PCI_CAPABILITIES(i) ((i) & 0xff) + +/* register 0x3c macros */ +#define PCI_MAX_LATENCY(i) (((i) & 0xff000000) >> 24) +#define PCI_MIN_GRANT(i) (((i) & 0xff0000) >> 16) +#define PCI_INTERRUPT_PIN(i) (((i) & 0xff00) >> 8) +#define PCI_INTERRUPT_LINE(i) (((i)) & 0xff) + +#define IS_PCI_MEM_BAR(i) ((i) & 1) == 0 +#define IS_PCI_IO_BAR(i) ((i) & 1) == 1 +#define PCI_MEMBAR_TYPE(i) (((i) & 0x6) >> 1) +#define PCI_IOBAR_ADR(i) (((i) & 0xfffffffc)) +#define PCI_MEMBAR_ADR(i) (((i) & 0xfffffff0)) + +/* + * match bits for pci_find_classcode() + */ +#define PCI_FIND_BASE_CLASS (1 << 26) +#define PCI_FIND_SUB_CLASS (1 << 25) +#define PCI_FIND_PROG_IF (1 << 24) + +#define PCI_MK_CONF_ADDR(bus, device, function) (MCF_PCI_PCICAR_E | \ + ((bus) << 16) | \ + ((device << 8) | \ + (function)) + +#define PCI_HANDLE(bus, slot, function) (0 | ((bus & 0xff) << 10 | (slot & 0x1f) << 3 | (function & 7))) +#define PCI_BUS_FROM_HANDLE(h) (((h) & 0xff00) >> 10) +#define PCI_DEVICE_FROM_HANDLE(h) (((h) & 0xf8) >> 3) +#define PCI_FUNCTION_FROM_HANDLE(h) (((h) & 0x7)) + +#endif /* _PCI_H_ */ diff --git a/tos/pci_test/sources/pci_test.c b/tos/pci_test/sources/pci_test.c index d97e9a8..c0e1bdd 100644 --- a/tos/pci_test/sources/pci_test.c +++ b/tos/pci_test/sources/pci_test.c @@ -6,6 +6,7 @@ #include "bas_printf.h" #include "MCF5475.h" #include "driver_vec.h" +#include "pci.h" #define NOP() __asm__ __volatile__("nop\n\t" : : : "memory") @@ -14,6 +15,8 @@ volatile int32_t time, start, end; int i; +#define swpw(a) ((a) >> 8 | (a) << 8) + void do_tests(struct pci_native_driver_interface *pci) { #define PCI_READ_CONFIG_LONGWORD(a, b) pci->pci_read_config_longword(a, b) @@ -24,7 +27,35 @@ void do_tests(struct pci_native_driver_interface *pci) end = MCF_SLT0_SCNT; time = (start - end) / (SYSCLK / 1000) / 1000; - xprintf("finished (took %f seconds).\r\n", time / 1000.0); + printf("iterate over PCI devices\r\n"); + + int16_t handle; + int16_t index = 0; + + printf("\r\nPCI bus scan...\r\n\r\n"); + printf(" Bus| Dev|Func|Vndr|D-ID|Hndl|\r\n"); + printf("----+----+----+----+----+----+\r\n"); + + handle = (*pci->pci_find_device)(0x0, 0xFFFF, index); + + while (handle > 0) + { + uint32_t value; + + value = (*pci->pci_read_config_longword)(handle, PCIIDR); + + printf(" %02x | %02x | %02x |%04x|%04x|%04x| (0x%02x)\r\n", + (char) PCI_BUS_FROM_HANDLE(handle), + (char) PCI_DEVICE_FROM_HANDLE(handle), + (char) PCI_FUNCTION_FROM_HANDLE(handle), + (short) PCI_VENDOR_ID(value), (short) PCI_DEVICE_ID(value), + (unsigned char) handle, + (char) (*pci->pci_read_config_byte)(handle, PCICCR)); + + handle = (*pci->pci_find_device)(0x0, 0xFFFF, ++index); + } + printf("\r\n...finished\r\n"); + printf("finished (took %f seconds).\r\n", time / 1000.0); } struct driver_table *get_bas_drivers(void) @@ -79,6 +110,7 @@ void pci_test(void) pci_driver = ifc[i].interface.pci_native; pci_driver_interface = &ifc[i]; printf("PCI native driver interface v%d.%02d found\r\n", pci_driver_interface->version, pci_driver_interface->revision); + printf("replaced old with newer driver version\r\n"); } } } while (ifc[++i].type != END_OF_DRIVERS);