/**************************************************************************** * * $Id: hardware.c,v 1.2 2003/09/10 11:44:38 benjl Exp $ * * Description: Device driver initialisation for SOS * * Author: Ben Leslie * ****************************************************************************/ #include #include #include #include #include #include #include #include #include "hardware.h" #include "frames.h" struct serial *serial; struct tulip *tulip; static void scan_pci(struct chipset *cs); #define TULIP_VENDOR 0x1011 #define TULIP_DEVICE 0x14 /* Should be called at startup to initialise the U4600 hardware */ void hardware_init(void) { struct chipset *cs; bus_space_t space[2]; bs_seq sserial; /* Initialise the chipset driver*/ cs = gt_init(NULL); /* Ensure the serial device memory is mapped in */ map_physical(NULL, (void*) 0x1c800000, 0x1000); /* Initialise the serial driver */ sserial.c = 2; sserial.v = space; sserial.v[0] = (void*) 0x1c800030; sserial.v[1] = (void*) 0x1c800031; /* Initialise the serial driver */ serial = serial_init(sserial); /* Register an interrupt handler for the serial driver */ register_cpu_interrupt_handler(NULL, 4, serial_interrupt_handler, serial); /* Scan the PCI bus for valid drivers */ scan_pci(cs); } /* Find the position of the first zero bit in a word */ static inline unsigned long ffz(unsigned long word) { unsigned long i; for (i = 0; i < 64; i++) if ((word & (1UL << i)) == 0UL) return i; assert(!"Not possible"); } /* Load a specific device driver */ static void load_pci(struct chipset *cs, int bus, int device, int function) { uint32_t bar[6]; uint32_t size[6]; uint16_t vendor_num, device_num; int i; int irq; bs_seq busspaces; bus_space_t spaces[6]; exec_handle_t handle; busspaces.c = 0; busspaces.v = spaces; vendor_num = cs->ops->conf_read_16(cs->pvt, bus, device, function, 0); device_num = cs->ops->conf_read_16(cs->pvt, bus, device, function, 2); /* Test if we have a device driver for this device Currently we only have one driver, the tulip driver. So the test is very straight forward . If we were a more sophisticated OS we would have to lookup registered device drivers or something. */ if (vendor_num == TULIP_VENDOR && device_num == TULIP_DEVICE) { l4e_printf("Found tulip card\n"); } else { return; } for (i=0; i < 6; i++) { int reg = 16+(i*4); bar[i] = cs->ops->conf_read_32(cs->pvt, bus, device, function, reg); cs->ops->conf_write_32(cs->pvt, bus, device, function, reg, (uint32_t)-1); size[i] = cs->ops->conf_read_32(cs->pvt, bus, device, function, reg); cs->ops->conf_write_32(cs->pvt, bus, device, function, reg, bar[i]); } for (i = 0; i < 6; i++) { uint32_t tmp_size = 0; int io = 0; if (bar[i] == 0) continue; io = size[i] & 0x1; if (io) { bus_space_t iospace; size[i] &= ~0x1L; tmp_size = 1 << ffz(~size[i]); iospace = cs->ops->pci_iospace_map(cs->pvt, (void*) (bar[i] & ~(0x1L)), tmp_size, 0); busspaces.v[busspaces.c++] = iospace; } } irq = cs->ops->conf_read_8(cs->pvt, bus, device, function, 60); tulip = tulip_init(busspaces, NULL, NULL); /* Register the interrupt for the driver */ handle.function = (void*) tulip_interrupt_handler; handle.data = tulip; cs->ops->pci_register_interrupt(cs->pvt, irq, handle); } /* Scan the PCI bus for devices */ static void scan_pci(struct chipset *cs) { uint16_t vendor, device; int i; /* There are up to sixteen devices on the PCI bus. We get the device and vendor ID for each one. If the vendor id is -1 there is no device there so we skip it. Otherwise we try to load a driver for it */ for(i=0; i < 16; i++) { /* We read the vendor and device register for this given device */ vendor = cs->ops->conf_read_16(cs->pvt, 0, i, 0, 0); device = cs->ops->conf_read_16(cs->pvt, 0, i, 0, 2); if (vendor != 0xffff) { /* Load a driver for this device */ load_pci(cs, 0, i, 0); } } }