static int pvscsi_add_lun(struct pci_device *pci, void *iobase, struct pvscsi_ring_dsc_s *ring_dsc, u8 target, u8 lun) { struct pvscsi_lun_s *plun = malloc_fseg(sizeof(*plun)); if (!plun) { warn_noalloc(); return -1; } memset(plun, 0, sizeof(*plun)); plun->drive.type = DTYPE_PVSCSI; plun->drive.cntl_id = pci->bdf; plun->target = target; plun->lun = lun; plun->iobase = iobase; plun->ring_dsc = ring_dsc; char *name = znprintf(16, "pvscsi %02x:%02x.%x %d:%d", pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf), pci_bdf_to_fn(pci->bdf), target, lun); int prio = bootprio_find_scsi_device(pci, target, lun); int ret = scsi_drive_setup(&plun->drive, name, prio); free(name); if (ret) goto fail; return 0; fail: free(plun); return -1; }
void ohci_init(void *data) { if (! CONFIG_USB_OHCI) return; struct usb_s *cntl = data; // XXX - don't call pci_config_XXX from a thread cntl->type = USB_TYPE_OHCI; u32 baseaddr = pci_config_readl(cntl->bdf, PCI_BASE_ADDRESS_0); cntl->ohci.regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); dprintf(3, "OHCI init on dev %02x:%02x.%x (regs=%p)\n" , pci_bdf_to_bus(cntl->bdf), pci_bdf_to_dev(cntl->bdf) , pci_bdf_to_fn(cntl->bdf), cntl->ohci.regs); // Enable bus mastering and memory access. pci_config_maskw(cntl->bdf, PCI_COMMAND , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY); // XXX - check for and disable SMM control? // Disable interrupts writel(&cntl->ohci.regs->intrdisable, ~0); writel(&cntl->ohci.regs->intrstatus, ~0); // Allocate memory struct ohci_hcca *hcca = memalign_high(256, sizeof(*hcca)); struct ohci_ed *control_ed = malloc_high(sizeof(*control_ed)); if (!hcca || !control_ed) { dprintf(1, "No ram for ohci init\n"); return; } memset(hcca, 0, sizeof(*hcca)); memset(control_ed, 0, sizeof(*control_ed)); control_ed->hwINFO = ED_SKIP; cntl->ohci.control_ed = control_ed; int ret = start_ohci(cntl, hcca); if (ret) goto err; int count = check_ohci_ports(cntl); if (! count) goto err; return; err: stop_ohci(cntl); free(hcca); free(control_ed); }
int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci) { if (! CONFIG_USB_EHCI) return -1; u16 bdf = pci->bdf; u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); struct ehci_caps *caps = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); u32 hcc_params = readl(&caps->hccparams); if (hcc_params & HCC_64BIT_ADDR) { dprintf(1, "No support for 64bit EHCI\n"); return -1; } struct usb_ehci_s *cntl = malloc_tmphigh(sizeof(*cntl)); if (!cntl) { warn_noalloc(); return -1; } memset(cntl, 0, sizeof(*cntl)); cntl->usb.busid = busid; cntl->usb.pci = pci; cntl->usb.type = USB_TYPE_EHCI; cntl->caps = caps; cntl->regs = (void*)caps + readb(&caps->caplength); dprintf(1, "EHCI init on dev %02x:%02x.%x (regs=%p)\n" , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) , pci_bdf_to_fn(bdf), cntl->regs); pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); // XXX - check for and disable SMM control? // Find companion controllers. int count = 0; for (;;) { if (!comppci || comppci == pci) break; if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_UHCI) cntl->companion[count++] = comppci; else if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_OHCI) cntl->companion[count++] = comppci; comppci = comppci->next; } run_thread(configure_ehci, cntl); return 0; }
// installation check static void handle_1ab101(struct bregs *regs) { // Find max bus. int bdf, max; foreachpci(bdf, max) { } regs->al = 0x01; // Flags - "Config Mechanism #1" supported. regs->bx = 0x0210; // PCI version 2.10 regs->cl = pci_bdf_to_bus(max - 1); regs->edx = 0x20494350; // "PCI " // XXX - bochs bios code sets edi to point to 32bit code - but no // reference to this in spec. set_code_success(regs); }
static void init_pvscsi(struct pci_device *pci) { struct pvscsi_ring_dsc_s *ring_dsc = NULL; int i; u16 bdf = pci->bdf; void *iobase = (void*)(pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) & PCI_BASE_ADDRESS_MEM_MASK); pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); dprintf(1, "found pvscsi at %02x:%02x.%x, io @ %p\n", pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf), iobase); pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_ADAPTER_RESET, NULL, 0); pvscsi_init_rings(iobase, &ring_dsc); for (i = 0; i < 7; i++) pvscsi_scan_target(pci, iobase, ring_dsc, i); return; }
// IBM/MS get drive parameters static void disk_1348(struct bregs *regs, struct drive_s *drive_g) { u16 size = GET_INT13DPT(regs, size); // Buffer is too small if (size < 26) { disk_ret(regs, DISK_RET_EPARAM); return; } // EDD 1.x u8 type = GET_GLOBAL(drive_g->type); u16 npc = GET_GLOBAL(drive_g->pchs.cylinders); u16 nph = GET_GLOBAL(drive_g->pchs.heads); u16 npspt = GET_GLOBAL(drive_g->pchs.spt); u64 lba = GET_GLOBAL(drive_g->sectors); u16 blksize = GET_GLOBAL(drive_g->blksize); dprintf(DEBUG_HDL_13, "disk_1348 size=%d t=%d chs=%d,%d,%d lba=%d bs=%d\n" , size, type, npc, nph, npspt, (u32)lba, blksize); SET_INT13DPT(regs, size, 26); if (type == DTYPE_ATAPI) { // 0x74 = removable, media change, lockable, max values SET_INT13DPT(regs, infos, 0x74); SET_INT13DPT(regs, cylinders, 0xffffffff); SET_INT13DPT(regs, heads, 0xffffffff); SET_INT13DPT(regs, spt, 0xffffffff); SET_INT13DPT(regs, sector_count, (u64)-1); } else { if (lba > (u64)npspt*nph*0x3fff) { SET_INT13DPT(regs, infos, 0x00); // geometry is invalid SET_INT13DPT(regs, cylinders, 0x3fff); } else { SET_INT13DPT(regs, infos, 0x02); // geometry is valid SET_INT13DPT(regs, cylinders, (u32)npc); } SET_INT13DPT(regs, heads, (u32)nph); SET_INT13DPT(regs, spt, (u32)npspt); SET_INT13DPT(regs, sector_count, lba); } SET_INT13DPT(regs, blksize, blksize); if (size < 30 || (type != DTYPE_ATA && type != DTYPE_ATAPI)) { disk_ret(regs, DISK_RET_SUCCESS); return; } // EDD 2.x u16 ebda_seg = get_ebda_seg(); SET_INT13DPT(regs, size, 30); SET_INT13DPT(regs, dpte_segment, ebda_seg); SET_INT13DPT(regs, dpte_offset , offsetof(struct extended_bios_data_area_s, dpte)); // Fill in dpte u8 ataid = GET_GLOBAL(drive_g->cntl_id); u8 channel = ataid / 2; u8 slave = ataid % 2; u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1); u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2); u8 irq = GET_GLOBAL(ATA_channels[channel].irq); u16 options = 0; if (type == DTYPE_ATA) { u8 translation = GET_GLOBAL(drive_g->translation); if (translation != TRANSLATION_NONE) { options |= 1<<3; // CHS translation if (translation == TRANSLATION_LBA) options |= 1<<9; if (translation == TRANSLATION_RECHS) options |= 3<<9; } } else { // ATAPI options |= 1<<5; // removable device options |= 1<<6; // atapi device } options |= 1<<4; // lba translation if (CONFIG_ATA_PIO32) options |= 1<<7; SET_EBDA2(ebda_seg, dpte.iobase1, iobase1); SET_EBDA2(ebda_seg, dpte.iobase2, iobase2 + ATA_CB_DC); SET_EBDA2(ebda_seg, dpte.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | ATA_CB_DH_LBA)); SET_EBDA2(ebda_seg, dpte.unused, 0xcb); SET_EBDA2(ebda_seg, dpte.irq, irq); SET_EBDA2(ebda_seg, dpte.blkcount, 1); SET_EBDA2(ebda_seg, dpte.dma, 0); SET_EBDA2(ebda_seg, dpte.pio, 0); SET_EBDA2(ebda_seg, dpte.options, options); SET_EBDA2(ebda_seg, dpte.reserved, 0); SET_EBDA2(ebda_seg, dpte.revision, 0x11); u8 sum = checksum_far( ebda_seg, (void*)offsetof(struct extended_bios_data_area_s, dpte), 15); SET_EBDA2(ebda_seg, dpte.checksum, -sum); if (size < 66) { disk_ret(regs, DISK_RET_SUCCESS); return; } // EDD 3.x SET_INT13DPT(regs, key, 0xbedd); SET_INT13DPT(regs, dpi_length, 36); SET_INT13DPT(regs, reserved1, 0); SET_INT13DPT(regs, reserved2, 0); int bdf = GET_GLOBAL(ATA_channels[channel].pci_bdf); if (bdf != -1) { SET_INT13DPT(regs, host_bus[0], 'P'); SET_INT13DPT(regs, host_bus[1], 'C'); SET_INT13DPT(regs, host_bus[2], 'I'); SET_INT13DPT(regs, host_bus[3], 0); u32 path = (pci_bdf_to_bus(bdf) | (pci_bdf_to_dev(bdf) << 8) | (pci_bdf_to_fn(bdf) << 16)); SET_INT13DPT(regs, iface_path, path); } else { // ISA SET_INT13DPT(regs, host_bus[0], 'I'); SET_INT13DPT(regs, host_bus[1], 'S'); SET_INT13DPT(regs, host_bus[2], 'A'); SET_INT13DPT(regs, host_bus[3], 0); SET_INT13DPT(regs, iface_path, iobase1); } SET_INT13DPT(regs, iface_type[0], 'A'); SET_INT13DPT(regs, iface_type[1], 'T'); SET_INT13DPT(regs, iface_type[2], 'A'); SET_INT13DPT(regs, iface_type[3], 0); SET_INT13DPT(regs, iface_type[4], 0); SET_INT13DPT(regs, iface_type[5], 0); SET_INT13DPT(regs, iface_type[6], 0); SET_INT13DPT(regs, iface_type[7], 0); SET_INT13DPT(regs, device_path, slave); SET_INT13DPT(regs, checksum , -checksum_far(regs->ds, (void*)(regs->si+30), 35)); disk_ret(regs, DISK_RET_SUCCESS); }
int bochsvga_setup(void) { int ret = stdvga_setup(); if (ret) return ret; /* Sanity checks */ dispi_write(VBE_DISPI_INDEX_ID, VBE_DISPI_ID0); if (dispi_read(VBE_DISPI_INDEX_ID) != VBE_DISPI_ID0) { dprintf(1, "No VBE DISPI interface detected, falling back to stdvga\n"); return 0; } dispi_write(VBE_DISPI_INDEX_ID, VBE_DISPI_ID5); SET_VGA(dispi_found, 1); if (GET_GLOBAL(HaveRunInit)) return 0; u32 lfb_addr = VBE_DISPI_LFB_PHYSICAL_ADDRESS; int bdf = GET_GLOBAL(VgaBDF); if (CONFIG_VGA_PCI && bdf >= 0) { u16 vendor = pci_config_readw(bdf, PCI_VENDOR_ID); int barid; switch (vendor) { case 0x15ad: /* qemu vmware vga */ barid = 1; break; case 0x1af4: /* virtio-vga */ barid = 2; break; default: /* stdvga, qxl */ barid = 0; break; } u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0 + barid * 4); lfb_addr = bar & PCI_BASE_ADDRESS_MEM_MASK; dprintf(1, "VBE DISPI: bdf %02x:%02x.%x, bar %d\n", pci_bdf_to_bus(bdf) , pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf), barid); } SET_VGA(VBE_framebuffer, lfb_addr); u32 totalmem = dispi_read(VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024; SET_VGA(VBE_total_memory, totalmem); SET_VGA(VBE_win_granularity, 64); SET_VGA(VBE_capabilities, VBE_CAPABILITY_8BIT_DAC); dprintf(1, "VBE DISPI: lfb_addr=%x, size %d MB\n", lfb_addr, totalmem >> 20); // Validate modes u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE); dispi_write(VBE_DISPI_INDEX_ENABLE, en | VBE_DISPI_GETCAPS); u16 max_xres = dispi_read(VBE_DISPI_INDEX_XRES); u16 max_bpp = dispi_read(VBE_DISPI_INDEX_BPP); dispi_write(VBE_DISPI_INDEX_ENABLE, en); struct bochsvga_mode *m = bochsvga_modes; for (; m < &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)]; m++) { u16 width = GET_GLOBAL(m->info.width); u16 height = GET_GLOBAL(m->info.height); u8 depth = GET_GLOBAL(m->info.depth); u32 mem = (height * DIV_ROUND_UP(width * vga_bpp(&m->info), 8) * stdvga_vram_ratio(&m->info)); if (width > max_xres || depth > max_bpp || mem > totalmem) { dprintf(1, "Removing mode %x\n", GET_GLOBAL(m->mode)); SET_VGA(m->mode, 0xffff); } } return 0; }