Пример #1
0
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;
}
Пример #2
0
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);
}
Пример #3
0
// 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;
}
Пример #4
0
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;
}
Пример #5
0
void
usb_setup(void)
{
    ASSERT32FLAT();
    if (! CONFIG_USB)
        return;
    run_thread(__usb_setup, NULL);
}
Пример #6
0
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;
}
Пример #7
0
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();
}
Пример #8
0
// 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;
}
Пример #9
0
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);
}
Пример #10
0
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();
}
Пример #11
0
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);
    }
}
Пример #12
0
// 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;
}
Пример #13
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;
}
Пример #14
0
// 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;
}
Пример #15
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;
}