new revision of BaS native PCI driver that supports find_pci_device() and find_pci_classcode() functions from TOS

This commit is contained in:
Markus Fröschle
2015-11-20 21:25:07 +00:00
parent 424a276dee
commit 24c7249156
7 changed files with 323 additions and 5 deletions

View File

@@ -608,3 +608,4 @@ tos/pci_test/include/MCF5475_SRAM.h
tos/pci_test/include/MCF5475_USB.h tos/pci_test/include/MCF5475_USB.h
tos/pci_test/include/MCF5475_XLB.h tos/pci_test/include/MCF5475_XLB.h
tos/pci_test/include/MCF5475.h tos/pci_test/include/MCF5475.h
tos/pci_test/include/pci.h

View File

@@ -1,5 +1,6 @@
include include
tos/jtagwait/include tos/jtagwait/include
tos/pci_test/include
/usr/m68k-atari-mint/include /usr/m68k-atari-mint/include
dma dma
m54455 m54455

View File

@@ -124,7 +124,7 @@ static struct pci_bios_interface pci_interface =
.phys_to_virt = wrapper_phys_to_virt, .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_longword = pci_read_config_longword,
.pci_read_config_word = pci_read_config_word, .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, .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 * driver interface struct for the BaS framebuffer video driver
*/ */
@@ -206,8 +220,17 @@ static struct generic_interface interfaces[] =
.description = "BaS PCI native", .description = "BaS PCI native",
.version = 0, .version = 0,
.revision = 1, .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, .interface.pci_native = &pci_native_interface,
}, },
/* insert new drivers here */ /* insert new drivers here */
{ {

View File

@@ -271,7 +271,7 @@ struct mmu_driver_interface
uint32_t (*report_pagesize)(void); 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); uint32_t (*pci_read_config_longword)(int32_t handle, int offset);
uint16_t (*pci_read_config_word)(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_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 union interface
{ {
struct generic_driver_interface *gdi; struct generic_driver_interface *gdi;
@@ -294,6 +310,7 @@ union interface
struct framebuffer_driver_interface *fb; struct framebuffer_driver_interface *fb;
struct pci_bios_interface *pci; struct pci_bios_interface *pci;
struct mmu_driver_interface *mmu; struct mmu_driver_interface *mmu;
struct pci_native_driver_interface_0_1 *pci_native_0_1;
struct pci_native_driver_interface *pci_native; struct pci_native_driver_interface *pci_native;
}; };

View File

@@ -25,6 +25,8 @@
#ifndef _DRIVER_VEC_H_ #ifndef _DRIVER_VEC_H_
#define _DRIVER_VEC_H_ #define _DRIVER_VEC_H_
#include "pci.h"
enum driver_type enum driver_type
{ {
BLOCKDEV_DRIVER, 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) */ 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 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_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_hook_interrupt)(int32_t handle, void *handler, void *parameter);
int32_t (*pci_unhook_interrupt)(int32_t handle); 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); struct pci_rd * (*pci_get_resource)(int32_t handle);
}; };

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
* 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_ */

View File

@@ -6,6 +6,7 @@
#include "bas_printf.h" #include "bas_printf.h"
#include "MCF5475.h" #include "MCF5475.h"
#include "driver_vec.h" #include "driver_vec.h"
#include "pci.h"
#define NOP() __asm__ __volatile__("nop\n\t" : : : "memory") #define NOP() __asm__ __volatile__("nop\n\t" : : : "memory")
@@ -14,6 +15,8 @@
volatile int32_t time, start, end; volatile int32_t time, start, end;
int i; int i;
#define swpw(a) ((a) >> 8 | (a) << 8)
void do_tests(struct pci_native_driver_interface *pci) void do_tests(struct pci_native_driver_interface *pci)
{ {
#define PCI_READ_CONFIG_LONGWORD(a, b) pci->pci_read_config_longword(a, b) #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; end = MCF_SLT0_SCNT;
time = (start - end) / (SYSCLK / 1000) / 1000; 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) struct driver_table *get_bas_drivers(void)
@@ -79,6 +110,7 @@ void pci_test(void)
pci_driver = ifc[i].interface.pci_native; pci_driver = ifc[i].interface.pci_native;
pci_driver_interface = &ifc[i]; 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("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); } while (ifc[++i].type != END_OF_DRIVERS);