#include #include #include #include #include #include #include "MCF5475.h" #include "driver_vec.h" #include "pci.h" #define NOP() __asm__ __volatile__("nop\n\t" : : : "memory") #define SYSCLK 132000 #define KB 1024UL #define MB (KB * KB) volatile int32_t time, start, end; int i; /* * PCI device class descriptions displayed during PCI bus scan */ static struct pci_class { int classcode; char *description; } pci_classes[] = { { 0x00, "device was built prior definition of the class code field" }, { 0x01, "Mass Storage Controller" }, { 0x02, "Network Controller" }, { 0x03, "Display Controller" }, { 0x04, "Multimedia Controller" }, { 0x05, "Memory Controller" }, { 0x06, "Bridge Device" }, { 0x07, "Simple Communication Controller" }, { 0x08, "Base System Peripherial" }, { 0x09, "Input Device" }, { 0x0a, "Docking Station" }, { 0x0b, "Processor" }, { 0x0c, "Serial Bus Controller" }, { 0x0d, "Wireless Controller" }, { 0x0e, "Intelligent I/O Controller" }, { 0x0f, "Satellite Communication Controller" }, { 0x10, "Encryption/Decryption Controller" }, { 0x11, "Data Acquisition and Signal Processing Controller" }, { 0xff, "Device does not fit any defined class" }, }; static int num_pci_classes = sizeof(pci_classes) / sizeof(struct pci_class); /* * retrieve device class (in cleartext) for a PCI classcode */ static char *device_class(int classcode) { int i; for (i = 0; i < num_pci_classes; i++) { if (pci_classes[i].classcode == classcode) { return pci_classes[i].description; } } return "unknown device class"; } void hexdump(uint8_t buffer[], int size) { int i; int line = 0; uint8_t *bp = buffer; while (bp < buffer + size) { uint8_t *lbp = bp; printf("%08lx ", (long) buffer + line); for (i = 0; i < 16; i++) { if (bp + i > buffer + size) { break; } printf("%02x ", (uint8_t) *lbp++); } lbp = bp; for (i = 0; i < 16; i++) { int8_t c = *lbp++; if (bp + i > buffer + size) { break; } if (c > ' ' && c < '~') { printf("%c", c); } else { printf("."); } } printf("\r\n"); bp += 16; line += 16; } } 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_WRITE_CONFIG_LONGWORD(a, b) pci->pci_write_config_longword(a, b) printf("enumerate 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 = swpl((*pci->pci_read_config_longword)(handle, PCIIDR)); printf(" %02x | %02x | %02x |%04x|%04x|%04x| %s (0x%02x, 0x%04x)\r\n", PCI_BUS_FROM_HANDLE(handle), PCI_DEVICE_FROM_HANDLE(handle), PCI_FUNCTION_FROM_HANDLE(handle), PCI_VENDOR_ID(value), PCI_DEVICE_ID(value), handle, device_class((*pci->pci_read_config_byte)(handle, PCI_LANESWAP_B(PCICCR))), (*pci->pci_read_config_byte)(handle, PCI_LANESWAP_B(PCICCR)), (*pci->pci_read_config_word)(handle, PCI_LANESWAP_W(PCICCR))); handle = (*pci->pci_find_device)(0x0, 0xFFFF, ++index); } struct pci_rd *rd; int flags; /* * look for an ATI Radeon video card */ // handle = 0xd8; handle = (*pci->pci_find_device)(0x5159, 0x1002, 0); if (handle > 0) { rd = (*pci->pci_get_resource)(handle); /* get resource descriptor for ATI graphics card */ if (rd != NULL) { do { flags = rd->flags; printf("Start address: 0x%08lx\r\n", rd->start); printf("Length: 0x%08lx\r\n", rd->length); printf("Offset: 0x%08lx\r\n", rd->offset); printf("DMA offset: 0x%08lx\r\n", rd->dmaoffset); printf("FLAGS: %s%s%s%s%s%s%s\r\n", flags & FLG_IO ? "FLG_IO, " : "", flags & FLG_ROM ? "FLG_ROM, " : "", flags & FLG_8BIT ? "FLG_8BIT, " : "", flags & FLG_16BIT ? "FLG_16BIT, " : "", flags & FLG_32BIT ? "FLG_32BIT, " : "", (flags & FLG_ENDMASK) == ORD_MOTOROLA ? "ORD_MOTOROLA" : (flags & FLG_ENDMASK) == ORD_INTEL_AS ? "ORD_INTEL_AS" : (flags & FLG_ENDMASK) == ORD_INTEL_LS ? "ORD_INTEL_LS" : (flags & FLG_ENDMASK) == ORD_UNKNOWN ? "ORD_UNKNOWN" : "", ""); printf("\r\n"); if (rd->start != 0L && rd->start == 0x80000000) { hexdump((uint8_t *) rd->start + rd->offset, 64); memset((uint8_t *) rd-> start + rd->offset, 0, 64 * MB); printf("memory cleared\r\n"); hexdump((uint8_t *) rd->start + rd->offset, 64); memset((uint8_t *) rd->start + rd->offset, 0xaa, 64 * MB); hexdump((uint8_t *) rd->start + rd->offset, 64); } rd = (struct pci_rd *) (((uintptr_t) rd) + (uintptr_t) rd->next); } while (!(flags & FLG_LAST)); } else { printf("resource descriptor for handle 0x%02x not found\r\n", handle); } } else fprintf(stderr, "card not found\r\n"); printf("\r\n...finished\r\n"); } /* * temporarily replace the trap 0 handler with this so we can avoid * getting caught by BaS versions that don't understand the driver interface * exposure call. * If we get here, we have a BaS version that doesn't support the trap 0 interface */ static void __attribute__((interrupt)) trap0_catcher(void) { __asm__ __volatile__( " clr.l d0 \n\t" // return 0 to indicate not supported : : : ); } struct driver_table *get_bas_drivers(void) { struct driver_table *ret = NULL; void *old_vector; old_vector = Setexc(0x20, trap0_catcher); /* set our own temporarily */ __asm__ __volatile__( " bra.s do_trap \n\t" " .dc.l 0x5f424153 \n\t" // '_BAS' "do_trap: trap #0 \n\t" " move.l d0,%[ret] \n\t" : [ret] "=m" (ret) /* output */ : /* no inputs */ : /* clobbered */ ); (void) Setexc(0x20, old_vector); /* restore original vector */ return ret; } void pci_test(void) { struct driver_table *bas_drivers; struct generic_interface *ifc; bool pci_driver_found = false; struct pci_native_driver_interface *pci_driver = NULL; bas_drivers = get_bas_drivers(); /* * trap0_catcher should return 0L on failure, for some reason FireTOS * returns -1L on a trap #0. Anyway, ... */ if (bas_drivers != NULL && bas_drivers != (void *) -1L) { printf("BaS driver vector: %p\r\n", bas_drivers); printf("BaS version: %ld.%02ld\r\n", (long) bas_drivers->bas_version, (long) bas_drivers->bas_revision); } else { printf("BaS driver retrieval not supported\r\n"); printf("(old BaS version or FireTOS?)\r\n"); exit(1); } ifc = bas_drivers->interfaces; do { struct generic_interface *pci_driver_interface = NULL; printf("interface type: %ld\r\n", (long) ifc[i].type); printf("interface version: %ld.%02ld\r\n", (long) ifc[i].version, (long) ifc[i].revision); printf("interface name: %s\r\n", ifc[i].name); printf("interface description: %s\r\n", ifc[i].description); if (ifc[i].type == PCI_NATIVE_DRIVER) { pci_driver_found = true; if (!pci_driver_interface || (ifc[i].version > pci_driver_interface->version || (ifc[i].version == pci_driver_interface->version && ifc[i].revision > pci_driver_interface->revision))) { /* * either no PCI driver interface found yet or with lower version or with lower version and higher revision * * replace it */ 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); if (pci_driver_found) { do_tests(pci_driver); } } int main(int argc, char *argv[]) { printf("PCI test routines\r\n"); printf("\xbd 2014 M. Fr\x94schle\r\n"); Supexec(pci_test); return 0; /* just to make the compiler happy, we will never return */ }