From 3f435ed80e2a6b29489b385cf3d8111bef3a7259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Fr=C3=B6schle?= Date: Thu, 7 Nov 2013 11:31:10 +0000 Subject: [PATCH] modified PCI access routines to closer follow pcibios standard --- Makefile | 2 +- include/pci.h | 48 +++++++++++++------------ sources/pci.c | 97 ++++++++++++++++++++++----------------------------- 3 files changed, 68 insertions(+), 79 deletions(-) diff --git a/Makefile b/Makefile index a78dcd9..cb588ab 100644 --- a/Makefile +++ b/Makefile @@ -206,7 +206,7 @@ depend: $(ASRCS) $(CSRCS) .PHONY: tags tags: - ctags -d sources/* include/* + ctags sources/* include/* ifneq (clean,$(MAKECMDGOALS)) -include depend diff --git a/include/pci.h b/include/pci.h index 8a27d31..aff4e19 100644 --- a/include/pci.h +++ b/include/pci.h @@ -28,16 +28,20 @@ #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 0x08 /* PCI Class Code Register */ -#define PCICLSR 0x0F /* PCI Cache Line Size Register */ -#define PCILTR 0x0E /* PCI Latency Timer Register */ -#define PCIHTR 0x0D /* PCI Header Type Register */ -#define PCIBISTR 0x0C /* PCI Build-In Self Test Register */ +#define PCICCR 0x09 /* 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 @@ -50,15 +54,13 @@ #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 0x2C /* PCI Subsystem ID */ +#define PCISID 0x2E /* PCI Subsystem ID */ #define PCIERBAR 0x30 /* PCI Expansion ROM Base Register */ -#define CAP_PTR 0x37 /* New Capability Pointer */ -#define PCIILR 0x3F /* PCI Interrupt Line Register */ -#define PCIIPR 0x3E /* PCI Interrupt Pin Register */ -#define PCIMGR 0x3D /* PCI Min_Gnt Register */ -#define PCIMLR 0x3C /* PCI Max_Lat Register */ - -// FIXME: register numbers swapped from here on +#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 */ @@ -194,19 +196,19 @@ extern void init_eport(void); extern void init_xlbus_arbiter(void); extern void init_pci(void); -extern int16_t pci_find_device(uint16_t device_id, uint16_t vendor_id, int index); +extern int32_t pci_find_device(uint16_t device_id, uint16_t vendor_id, int index); -extern uint32_t pci_read_config_longword(uint16_t handle, uint16_t offset); -extern uint16_t pci_read_config_word(uint16_t handle, uint16_t offset); -extern uint8_t pci_read_config_byte(uint16_t handle, uint16_t offset); +extern uint32_t pci_read_config_longword(int32_t handle, int offset); +extern uint16_t pci_read_config_word(int32_t handle, int offset); +extern uint8_t pci_read_config_byte(int32_t handle, int offset); -extern void pci_write_config_longword(uint16_t handle, uint16_t offset, uint32_t value); -extern void pci_write_config_word(uint16_t handle, uint16_t offset, uint16_t value); -extern void pci_write_config_byte(uint16_t handle, uint16_t offset, uint8_t value); +extern int32_t pci_write_config_longword(int32_t handle, int offset, uint32_t value); +extern int32_t pci_write_config_word(int32_t handle, int offset, uint16_t value); +extern int32_t pci_write_config_byte(int32_t handle, int offset, uint8_t value); -extern struct pci_rd *pci_get_resource(uint16_t handle); -extern int16_t pci_hook_interrupt(uint16_t handle, void *interrupt_handler, void *parameter); -extern int16_t pci_unhook_interrupt(uint16_t handle); +extern struct pci_rd *pci_get_resource(int32_t handle); +extern int32_t pci_hook_interrupt(int32_t handle, void *interrupt_handler, void *parameter); +extern int32_t pci_unhook_interrupt(int32_t handle); diff --git a/sources/pci.c b/sources/pci.c index 6730563..1237cad 100644 --- a/sources/pci.c +++ b/sources/pci.c @@ -66,14 +66,14 @@ static int num_pci_classes = sizeof(pci_classes) / sizeof(struct pci_class); #define NUM_CARDS 10 #define NUM_RESOURCES 6 /* holds the handle of a card at position = array index */ -static uint16_t handles[NUM_CARDS]; +static int32_t handles[NUM_CARDS]; /* holds the card's resource descriptors; filled in pci_device_config() */ static struct pci_rd resource_descriptors[NUM_CARDS][NUM_RESOURCES]; /* * retrieve handle for i'th device */ -static int16_t handle2index(int16_t handle) +static int handle2index(int32_t handle) { int i; @@ -104,24 +104,18 @@ static char *device_class(int classcode) return "not found"; } -uint32_t pci_read_config_longword(uint16_t handle, uint16_t offset) +/* + * read an uint32_t from configuration space of card with handle and offset + * + * The returned value is in little endian format. + */ +uint32_t pci_read_config_longword(int32_t handle, int offset) { uint32_t value; uint16_t bus = PCI_BUS_FROM_HANDLE(handle); uint16_t device = PCI_DEVICE_FROM_HANDLE(handle); uint16_t function = PCI_FUNCTION_FROM_HANDLE(handle); -#ifdef _NOT_USED_ - /* clear PCI status/command register */ - MCF_PCI_PCISCR = MCF_PCI_PCISCR_PE | /* clear parity error bit */ - MCF_PCI_PCISCR_SE | /* clear system error */ - MCF_PCI_PCISCR_MA | /* clear master abort */ - MCF_PCI_PCISCR_TR | /* clear target abort */ - MCF_PCI_PCISCR_TS | /* clear target abort signalling (as target) */ - MCF_PCI_PCISCR_DP; /* clear parity error */ -#endif /* _NOT_USED_ */ - - /* initiate PCI configuration access to device */ MCF_PCI_PCICAR = MCF_PCI_PCICAR_E | /* enable configuration access special cycle */ MCF_PCI_PCICAR_BUSNUM(bus) | @@ -131,10 +125,10 @@ uint32_t pci_read_config_longword(uint16_t handle, uint16_t offset) value = * (volatile uint32_t *) PCI_IO_OFFSET; /* access device */ - return swpl(value); + return value; } -uint16_t pci_read_config_word(uint16_t handle, uint16_t offset) +uint16_t pci_read_config_word(int32_t handle, int offset) { uint32_t value; @@ -142,35 +136,25 @@ uint16_t pci_read_config_word(uint16_t handle, uint16_t offset) return value >> ((1 - offset % 2) * 16) & 0xffff; } -uint8_t pci_read_config_byte(uint16_t handle, uint16_t offset) +uint8_t pci_read_config_byte(int32_t handle, int offset) { uint32_t value; value = pci_read_config_longword(handle, offset); - //xprintf("pci_read_config_longword(0x%x, 0x%x) = 0x%04x\r\n", handle, offset, value); return value >> ((3 - offset % 4) * 8) & 0xff; } /* * pci_write_config_longword() * - * write an uint32_t value to the configuration space of a PCI device - * offset is a PCI DWORD value. + * write an uint32_t value (must be in little endian format) to the configuration space of a PCI device */ -void pci_write_config_longword(uint16_t handle, uint16_t offset, uint32_t value) +int32_t pci_write_config_longword(int32_t handle, int offset, uint32_t value) { uint16_t bus = PCI_BUS_FROM_HANDLE(handle); uint16_t device = PCI_DEVICE_FROM_HANDLE(handle); uint16_t function = PCI_FUNCTION_FROM_HANDLE(handle); - /* clear PCI status/command register */ - MCF_PCI_PCISCR = MCF_PCI_PCISCR_PE | /* clear parity error bit */ - MCF_PCI_PCISCR_SE | /* clear system error */ - MCF_PCI_PCISCR_MA | /* clear master abort */ - MCF_PCI_PCISCR_TR | /* clear target abort */ - MCF_PCI_PCISCR_TS | /* clear target abort signalling (as target) */ - MCF_PCI_PCISCR_DP; /* clear parity error */ - /* initiate PCI configuration access to device */ MCF_PCI_PCICAR = MCF_PCI_PCICAR_E | /* enable configuration access special cycle */ MCF_PCI_PCICAR_BUSNUM(bus) | @@ -178,7 +162,9 @@ void pci_write_config_longword(uint16_t handle, uint16_t offset, uint32_t value) MCF_PCI_PCICAR_FUNCNUM(function) | /* function number */ MCF_PCI_PCICAR_DWORD(offset / 4); - * (volatile uint32_t *) PCI_IO_OFFSET = swpl(value); /* access device */ + * (volatile uint32_t *) PCI_IO_OFFSET = value; /* access device */ + + return PCI_SUCCESSFUL; } /* @@ -186,7 +172,7 @@ void pci_write_config_longword(uint16_t handle, uint16_t offset, uint32_t value) * * get resource descriptor chain for handle */ -struct pci_rd *pci_get_resource(uint16_t handle) +struct pci_rd *pci_get_resource(int32_t handle) { int index = -1; @@ -202,13 +188,13 @@ struct pci_rd *pci_get_resource(uint16_t handle) * find index'th device by device_id and vendor_id. Special case: vendor id -1 (0xffff) * matches all devices. You can search the whole bus by repeatedly calling this function */ -int16_t pci_find_device(uint16_t device_id, uint16_t vendor_id, int index) +int32_t pci_find_device(uint16_t device_id, uint16_t vendor_id, int index) { uint16_t bus; uint16_t device; uint16_t function = 0; - uint16_t pos = 0; - int handle; + uint16_t n = 0; + int32_t handle; for (bus = 0; bus < 255; bus++) { @@ -218,61 +204,62 @@ int16_t pci_find_device(uint16_t device_id, uint16_t vendor_id, int index) uint8_t htr; handle = PCI_HANDLE(bus, device, 0); - value = pci_read_config_longword(handle, PCIIDR); + value = swpl(pci_read_config_longword(handle, PCIIDR)); if (value != 0xffffffff) /* we have a device at this position */ { if (vendor_id == 0xffff || (PCI_VENDOR_ID(value) == vendor_id && PCI_DEVICE_ID(value) == device_id)) { - if (pos == index) + if (n == index) { return handle; } } - if (pci_read_config_byte(handle, PCIHTR) & 0x80) + + /* + * There is a device at this position, but not the one we are looking for. + * Check to see if it is a multi-function device. We need to look "behind" it + * for the other functions in that case. + */ + if ((htr = pci_read_config_byte(handle, PCIHTR)) & 0x80) { - /* check if we have a multi-function device at this position */ - htr = pci_read_config_byte(handle, PCIHTR); + /* yes, this is a multi-function device, look for more functions */ xprintf("bus = %02x, dev = %02x, func = %02x PCIHTR=%02x\r\n", bus, device, function, htr); for (function = 1; function < 8; function++) { - pos++; handle = PCI_HANDLE(bus, device, function); - value = pci_read_config_longword(handle, PCIIDR); + value = swpl(pci_read_config_longword(handle, PCIIDR)); if (value != 0xFFFFFFFF) /* device found */ { + n++; if (vendor_id == 0xffff || (PCI_VENDOR_ID(value) == vendor_id && PCI_DEVICE_ID(value) == device_id)) { - if (pos == index) + if (n == index) { return handle; } - else - { - //pos++; - } } } } } - /* we found a match, but at wrong position */ - pos++; + else /* no, current device is not multi-function */ + n++; /* next one */ } } } return PCI_DEVICE_NOT_FOUND; } -int16_t pci_hook_interrupt(uint16_t handle, void *handler, void *parameter) +int32_t pci_hook_interrupt(int32_t handle, void *handler, void *parameter) { /* FIXME: implement */ xprintf("pci_hook_interrupt() still not implemented\r\n"); return PCI_SUCCESSFUL; } -int16_t pci_unhook_interrupt(uint16_t handle) +int32_t pci_unhook_interrupt(int32_t handle) { /* FIXME: implement */ @@ -319,7 +306,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) /* * read BAR[i] value */ - value = pci_read_config_longword(handle, PCIBAR0 + i); + value = swpl(pci_read_config_longword(handle, PCIBAR0 + i)); /* * write all bits of BAR[i] @@ -329,7 +316,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) /* * read back value to see which bits have been set */ - address = pci_read_config_longword(handle, PCIBAR0 + i); + address = swpl(pci_read_config_longword(handle, PCIBAR0 + i)); if (address) /* is bar in use? */ { @@ -350,7 +337,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) pci_write_config_longword(handle, PCIBAR0 + i, mem_address); /* read it back, just to be sure */ - value = pci_read_config_longword(handle, PCIBAR0 + i); + value = swpl(pci_read_config_longword(handle, PCIBAR0 + i)); /* fill resource descriptor */ rd->next = sizeof(struct pci_rd); @@ -372,7 +359,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function) io_address = (io_address + size - 1) & ~(size - 1); pci_write_config_longword(handle, PCIBAR0 + i, io_address); - value = pci_read_config_longword(handle, PCIBAR0 + i); + value = swpl(pci_read_config_longword(handle, PCIBAR0 + i)); rd->next = sizeof(struct pci_rd); rd->flags = FLG_IO | FLG_8BIT | FLG_16BIT | FLG_32BIT | 1; @@ -409,7 +396,7 @@ void pci_scan(void) { uint32_t value; - value = pci_read_config_longword(handle, PCIIDR); + value = swpl(pci_read_config_longword(handle, PCIIDR)); xprintf(" %02x | %02x | %02x |%04x|%04x| %s (0x%02x)\r\n", PCI_BUS_FROM_HANDLE(handle), PCI_DEVICE_FROM_HANDLE(handle),