void DeviceServer::registerInterrupt(Device *dev, Size vector) { if (!m_interrupts[vector]) { m_interrupts.insert(vector, new List<Device *>); } m_interrupts[vector]->append(dev); // Register to kernel ProcessCtl(SELF, WatchIRQ, vector); ProcessCtl(SELF, EnableIRQ, vector); // Register interrupt handler addIRQHandler(vector, (IRQHandlerFunction) &DeviceServer::interruptHandler); }
Error SynopsisUSB::initialize() { Error r = USBController::initialize(); if (r != ESUCCESS) return r; // Map USB host controller registers if (m_io.map(IO_BASE + Base, PAGESIZE*2, Memory::User|Memory::Readable|Memory::Writable|Memory::Device) != IO::Success) { ERROR("failed to map I/O registers"); return EIO; } // Check device ID if (m_io.read(VendorId) != DefaultVendorId) { ERROR("incompatible vendorId: " << m_io.read(VendorId) << " != " << DefaultVendorId); return EIO; } DEBUG("UserId: " << m_io.read(UserId) << " VendorId: " << m_io.read(VendorId)); NOTICE("Synopsis Design Ware USB-on-the-go Host Controller found"); // Initialize power manager if (m_power.initialize() != BroadcomPower::Success) { ERROR("failed to initialize power manager"); return EIO; } // Power on the USB subsystem if (m_power.enable(BroadcomPower::USB) != BroadcomPower::Success) { ERROR("failed to power on the USB subsystem"); return EIO; } DEBUG("powered on"); // Soft-Reset softReset(); DEBUG("software reset done"); // Setup DMA m_io.write(RxFIFOSize, 1024); m_io.write(TxFIFOSize, (1024 << 16) | 1024); m_io.write(PeriodTxFIFOSize, (1024 << 16) | 2048); m_io.set(AHBConfig, DMAEnable | AXIWait); // Enable the USB controller interrupt on the ARM's interrupt controller addIRQHandler(InterruptNumber, (IRQHandlerFunction) &SynopsisUSB::interruptHandler); addIRQHandler(0, (IRQHandlerFunction) &SynopsisUSB::interruptHandler); // TODO: ARM does not have IRQ_REG() yet ProcessCtl(SELF, WatchIRQ, InterruptNumber); ProcessCtl(SELF, EnableIRQ, InterruptNumber); DEBUG("interrupt handler installed"); // Clear all pending core interrupts m_io.write(CoreIntMask, 0); m_io.write(CoreInterrupt, 0xffffffff); // Enable core host channel and port interrupts m_io.write(CoreIntMask, CoreIntChannel | CoreIntPort); // Enable interrupts globally on the USB host controller. m_io.set(AHBConfig, InterruptEnable); DEBUG("interrupts enabled"); // Power-on host port (virtual root hub) u32 val = m_io.read(HostPortControl); val &= ~(HostPortEnable | HostPortEnableChanged | HostPortConnectChanged | HostPortCurrentChanged); val |= HostPortPower; m_io.write(HostPortControl, val); DEBUG("poweron host port"); // Begin host port reset (raise the reset signal) val = m_io.read(HostPortControl); val &= ~(HostPortEnable | HostPortEnableChanged | HostPortConnectChanged | HostPortCurrentChanged); val |= HostPortReset; m_io.write(HostPortControl, val); #warning TODO: implement real sleep() now. We need it here. sleep(60); // Finish host port reset (lower the reset signal) val = m_io.read(HostPortControl); val &= ~(HostPortEnable | HostPortEnableChanged | HostPortConnectChanged | HostPortCurrentChanged); m_io.write(HostPortControl, val); DEBUG("host port reset done"); // Clear host port interrupt flags val = m_io.read(HostPortControl); val |= HostPortEnableChanged | HostPortConnectChanged | HostPortCurrentChanged; m_io.write(HostPortControl, val); DEBUG("host port (root hub) enabled"); DEBUG("host port status=" << m_io.read(HostPortControl) << " connected=" << (m_io.read(HostPortControl) & HostPortConnect)); // Done. return ESUCCESS; }