int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize) { ASSERT32FLAT(); if (! CONFIG_USB_EHCI) return -1; dprintf(5, "ehci_control %p (dir=%d cmd=%d data=%d)\n" , p, dir, cmdsize, datasize); if (datasize > 4*4096 || cmdsize > 4*4096) { // XXX - should support larger sizes. warn_noalloc(); return -1; } struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); // Setup transfer descriptors struct ehci_qtd *tds = memalign_tmphigh(EHCI_QTD_ALIGN, sizeof(*tds) * 3); if (!tds) { warn_noalloc(); return -1; } memset(tds, 0, sizeof(*tds) * 3); struct ehci_qtd *td = tds; td->qtd_next = (u32)&td[1]; td->alt_next = EHCI_PTR_TERM; td->token = (ehci_explen(cmdsize) | QTD_STS_ACTIVE | QTD_PID_SETUP | ehci_maxerr(3)); u16 maxpacket = pipe->pipe.maxpacket; fillTDbuffer(td, maxpacket, cmd, cmdsize); td++; if (datasize) { td->qtd_next = (u32)&td[1]; td->alt_next = EHCI_PTR_TERM; td->token = (QTD_TOGGLE | ehci_explen(datasize) | QTD_STS_ACTIVE | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3)); fillTDbuffer(td, maxpacket, data, datasize); td++; } td->qtd_next = EHCI_PTR_TERM; td->alt_next = EHCI_PTR_TERM; td->token = (QTD_TOGGLE | QTD_STS_ACTIVE | (dir ? QTD_PID_OUT : QTD_PID_IN) | ehci_maxerr(3)); // Transfer data barrier(); pipe->qh.qtd_next = (u32)tds; int i, ret=0; for (i=0; i<3; i++) { struct ehci_qtd *td = &tds[i]; ret = ehci_wait_td(pipe, td, 500); if (ret) break; } free(tds); return ret; }
void VISIBLE32INIT handle_csm(struct bregs *regs) { ASSERT32FLAT(); if (!CONFIG_CSM) return; dprintf(3, "handle_csm regs %p AX=%04x\n", regs, regs->ax); pic_irqmask_write(PICMask); switch(regs->ax) { case 0000: handle_csm_0000(regs); break; case 0001: handle_csm_0001(regs); break; case 0002: handle_csm_0002(regs); break; case 0003: handle_csm_0003(regs); break; // case 0004: handle_csm_0004(regs); break; case 0005: handle_csm_0005(regs); break; case 0006: handle_csm_0006(regs); break; // case 0007: handle_csm_0007(regs); break; // case 0008: hamdle_csm_0008(regs); break; default: regs->al = 1; } csm_return(regs); }
// Configure a usb hub and then find devices connected to it. int usb_hub_setup(struct usbdevice_s *usbdev) { ASSERT32FLAT(); if (!CONFIG_USB_HUB) return -1; struct usb_hub_descriptor desc; int ret = get_hub_desc(usbdev->defpipe, &desc); if (ret) return ret; struct usbhub_s hub; memset(&hub, 0, sizeof(hub)); hub.usbdev = usbdev; hub.cntl = usbdev->defpipe->cntl; hub.powerwait = desc.bPwrOn2PwrGood * 2; hub.portcount = desc.bNbrPorts; hub.op = &HubOp; usb_enumerate(&hub); dprintf(1, "Initialized USB HUB (%d ports used)\n", hub.devcount); if (hub.devcount) return 0; return -1; }
int vp_find_vq(unsigned int ioaddr, int queue_index, struct vring_virtqueue **p_vq) { u16 num; ASSERT32FLAT(); struct vring_virtqueue *vq = *p_vq = memalign_low(PAGE_SIZE, sizeof(*vq)); if (!vq) { warn_noalloc(); goto fail; } memset(vq, 0, sizeof(*vq)); /* select the queue */ outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); /* check if the queue is available */ num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); if (!num) { dprintf(1, "ERROR: queue size is 0\n"); goto fail; } if (num > MAX_QUEUE_NUM) { dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); goto fail; } /* check if the queue is already active */ if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { dprintf(1, "ERROR: queue already active\n"); goto fail; } vq->queue_index = queue_index; /* initialize the queue */ struct vring * vr = &vq->vring; vring_init(vr, num, (unsigned char*)&vq->queue); /* activate the queue * * NOTE: vr->desc is initialized by vring_init() */ outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT, ioaddr + VIRTIO_PCI_QUEUE_PFN); return num; fail: free(vq); *p_vq = NULL; return -1; }
void usb_setup(void) { ASSERT32FLAT(); if (! CONFIG_USB) return; run_thread(__usb_setup, NULL); }
int getDriveId(u8 exttype, struct drive_s *drive) { ASSERT32FLAT(); int i; for (i = 0; i < ARRAY_SIZE(IDMap[0]); i++) if (getDrive(exttype, i) == drive) return i; return -1; }
void printf(const char *fmt, ...) { ASSERT32FLAT(); va_list args; va_start(args, fmt); bvprintf(&screeninfo, fmt, args); va_end(args); if (ScreenAndDebug) debug_serial_flush(); }
// Find any devices connected to the root hub. static int check_ehci_ports(struct usb_ehci_s *cntl) { ASSERT32FLAT(); struct usbhub_s hub; memset(&hub, 0, sizeof(hub)); hub.cntl = &cntl->usb; hub.portcount = cntl->checkports; hub.op = &ehci_HubOp; usb_enumerate(&hub); return hub.devcount; }
void ps2port_setup(void) { ASSERT32FLAT(); if (! CONFIG_PS2PORT) return; dprintf(3, "init ps2port\n"); enable_hwirq(1, FUNC16(entry_09)); enable_hwirq(12, FUNC16(entry_74)); run_thread(keyboard_init, NULL); }
void usb_setup(void) { ASSERT32FLAT(); if (! CONFIG_USB) return; dprintf(3, "init usb\n"); usb_time_sigatt = romfile_loadint("etc/usb-time-sigatt", USB_TIME_SIGATT); xhci_setup(); ehci_setup(); uhci_setup(); ohci_setup(); }
void pvscsi_setup(void) { ASSERT32FLAT(); if (! CONFIG_PVSCSI) return; dprintf(3, "init pvscsi\n"); struct pci_device *pci; foreachpci(pci) { if (pci->vendor != PCI_VENDOR_ID_VMWARE || pci->device != PCI_DEVICE_ID_VMWARE_PVSCSI) continue; run_thread(init_pvscsi, pci); } }
// Assign an address to a device in the default state on the given // controller. static int usb_set_address(struct usbdevice_s *usbdev) { ASSERT32FLAT(); struct usb_s *cntl = usbdev->hub->cntl; dprintf(3, "set_address %p\n", cntl); if (cntl->maxaddr >= USB_MAXADDR) return -1; msleep(USB_TIME_RSTRCY); // Create a pipe for the default address. struct usb_endpoint_descriptor epdesc = { .wMaxPacketSize = speed_to_ctlsize[usbdev->speed], .bmAttributes = USB_ENDPOINT_XFER_CONTROL, }; usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); if (!usbdev->defpipe) return -1; // Send set_address command. struct usb_ctrlrequest req; req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; req.bRequest = USB_REQ_SET_ADDRESS; req.wValue = cntl->maxaddr + 1; req.wIndex = 0; req.wLength = 0; int ret = usb_send_default_control(usbdev->defpipe, &req, NULL); if (ret) { usb_free_pipe(usbdev, usbdev->defpipe); return -1; } msleep(USB_TIME_SETADDR_RECOVERY); cntl->maxaddr++; usbdev->devaddr = cntl->maxaddr; usbdev->defpipe = usb_realloc_pipe(usbdev, usbdev->defpipe, &epdesc); if (!usbdev->defpipe) return -1; return 0; }
u32 VISIBLE32INIT handle_pmm(u16 *args) { ASSERT32FLAT(); if (! CONFIG_PMM) return PMM_FUNCTION_NOT_SUPPORTED; u16 arg1 = args[0]; dprintf(DEBUG_HDL_pmm, "pmm call arg1=%x\n", arg1); u32 ret; switch (arg1) { case 0x00: ret = handle_pmm00(args); break; case 0x01: ret = handle_pmm01(args); break; case 0x02: ret = handle_pmm02(args); break; default: ret = handle_pmmXX(args); break; } return ret; }
// Called for every found device - see if a driver is available for // this device and do setup if so. static int configure_usb_device(struct usbdevice_s *usbdev) { ASSERT32FLAT(); dprintf(3, "config_usb: %p\n", usbdev->defpipe); // Set the max packet size for endpoint 0 of this device. struct usb_device_descriptor dinfo; int ret = get_device_info8(usbdev->defpipe, &dinfo); if (ret) return 0; u16 maxpacket = dinfo.bMaxPacketSize0; if (dinfo.bcdUSB >= 0x0300) maxpacket = 1 << dinfo.bMaxPacketSize0; dprintf(3, "device rev=%04x cls=%02x sub=%02x proto=%02x size=%d\n" , dinfo.bcdUSB, dinfo.bDeviceClass, dinfo.bDeviceSubClass , dinfo.bDeviceProtocol, maxpacket); if (maxpacket < 8) return 0; struct usb_endpoint_descriptor epdesc = { .wMaxPacketSize = maxpacket, .bmAttributes = USB_ENDPOINT_XFER_CONTROL, }; usbdev->defpipe = usb_realloc_pipe(usbdev, usbdev->defpipe, &epdesc); if (!usbdev->defpipe) return -1; // Get configuration struct usb_config_descriptor *config = get_device_config(usbdev->defpipe); if (!config) return 0; // Determine if a driver exists for this device - only look at the // first interface of the first configuration. struct usb_interface_descriptor *iface = (void*)(&config[1]); if (iface->bInterfaceClass != USB_CLASS_HID && iface->bInterfaceClass != USB_CLASS_MASS_STORAGE && iface->bInterfaceClass != USB_CLASS_HUB) // Not a supported device. goto fail; // Set the configuration. ret = set_configuration(usbdev->defpipe, config->bConfigurationValue); if (ret) goto fail; // Configure driver. usbdev->config = config; usbdev->iface = iface; usbdev->imax = (void*)config + config->wTotalLength - (void*)iface; if (iface->bInterfaceClass == USB_CLASS_HUB) ret = usb_hub_setup(usbdev); else if (iface->bInterfaceClass == USB_CLASS_MASS_STORAGE) { if (iface->bInterfaceProtocol == US_PR_BULK) ret = usb_msc_setup(usbdev); if (iface->bInterfaceProtocol == US_PR_UAS) ret = usb_uas_setup(usbdev); } else ret = usb_hid_setup(usbdev); if (ret) goto fail; free(config); return 1; fail: free(config); return 0; }
int cdrom_boot(struct drive_s *drive_g) { ASSERT32FLAT(); struct disk_op_s dop; int cdid = getDriveId(EXTTYPE_CD, drive_g); memset(&dop, 0, sizeof(dop)); dop.drive_g = drive_g; if (!dop.drive_g || cdid < 0) return 1; int ret = scsi_is_ready(&dop); if (ret) dprintf(1, "scsi_is_ready returned %d\n", ret); // Read the Boot Record Volume Descriptor u8 buffer[CDROM_SECTOR_SIZE]; dop.lba = 0x11; dop.count = 1; dop.buf_fl = buffer; ret = cdb_read(&dop); if (ret) return 3; // Validity checks if (buffer[0]) return 4; if (strcmp((char*)&buffer[1], "CD001\001EL TORITO SPECIFICATION") != 0) return 5; // ok, now we calculate the Boot catalog address u32 lba = *(u32*)&buffer[0x47]; // And we read the Boot Catalog dop.lba = lba; dop.count = 1; ret = cdb_read(&dop); if (ret) return 7; // Validation entry if (buffer[0x00] != 0x01) return 8; // Header if (buffer[0x01] != 0x00) return 9; // Platform if (buffer[0x1E] != 0x55) return 10; // key 1 if (buffer[0x1F] != 0xAA) return 10; // key 2 // Initial/Default Entry if (buffer[0x20] != 0x88) return 11; // Bootable u8 media = buffer[0x21]; CDEmu.media = media; CDEmu.emulated_drive_gf = dop.drive_g; u16 boot_segment = *(u16*)&buffer[0x22]; if (!boot_segment) boot_segment = 0x07C0; CDEmu.load_segment = boot_segment; CDEmu.buffer_segment = 0x0000; u16 nbsectors = *(u16*)&buffer[0x26]; CDEmu.sector_count = nbsectors; lba = *(u32*)&buffer[0x28]; CDEmu.ilba = lba; // And we read the image in memory dop.lba = lba; dop.count = DIV_ROUND_UP(nbsectors, 4); dop.buf_fl = MAKE_FLATPTR(boot_segment, 0); ret = cdb_read(&dop); if (ret) return 12; if (media == 0) { // No emulation requested - return success. CDEmu.emulated_extdrive = EXTSTART_CD + cdid; return 0; } // Emulation of a floppy/harddisk requested if (! CONFIG_CDROM_EMU || !cdemu_drive_gf) return 13; // Set emulated drive id and increase bios installed hardware // number of devices if (media < 4) { // Floppy emulation CDEmu.emulated_extdrive = 0x00; // XXX - get and set actual floppy count. set_equipment_flags(0x41, 0x41); switch (media) { case 0x01: // 1.2M floppy CDEmu.lchs.spt = 15; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; case 0x02: // 1.44M floppy CDEmu.lchs.spt = 18; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; case 0x03: // 2.88M floppy CDEmu.lchs.spt = 36; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; } } else { // Harddrive emulation CDEmu.emulated_extdrive = 0x80; SET_BDA(hdcount, GET_BDA(hdcount) + 1); // Peak at partition table to get chs. struct mbr_s *mbr = (void*)0; u8 sptcyl = GET_FARVAR(boot_segment, mbr->partitions[0].last.sptcyl); u8 cyllow = GET_FARVAR(boot_segment, mbr->partitions[0].last.cyllow); u8 heads = GET_FARVAR(boot_segment, mbr->partitions[0].last.heads); CDEmu.lchs.spt = sptcyl & 0x3f; CDEmu.lchs.cylinders = ((sptcyl<<2)&0x300) + cyllow + 1; CDEmu.lchs.heads = heads + 1; } // everything is ok, so from now on, the emulation is active CDEmu.active = 0x01; dprintf(6, "cdemu media=%d\n", media); return 0; }