]> xenbits.xensource.com Git - people/andrewcoop/seabios.git/commitdiff
Move code centered around specific hardware devices to src/hw/
authorKevin O'Connor <kevin@koconnor.net>
Tue, 3 Sep 2013 00:48:46 +0000 (20:48 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Tue, 3 Sep 2013 00:48:46 +0000 (20:48 -0400)
Move many C files from the src/ directory to the new src/hw/ directory.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
132 files changed:
Makefile
src/acpi.c
src/ahci.c [deleted file]
src/ahci.h [deleted file]
src/ata.c [deleted file]
src/ata.h [deleted file]
src/biostables.c
src/block.c
src/blockcmd.c [deleted file]
src/blockcmd.h [deleted file]
src/boot.c
src/cdrom.c
src/clock.c
src/cmos.h [deleted file]
src/coreboot.c
src/csm.c
src/csm.h
src/disk.c
src/esp-scsi.c [deleted file]
src/esp-scsi.h [deleted file]
src/floppy.c [deleted file]
src/hw/ahci.c [new file with mode: 0644]
src/hw/ahci.h [new file with mode: 0644]
src/hw/ata.c [new file with mode: 0644]
src/hw/ata.h [new file with mode: 0644]
src/hw/blockcmd.c [new file with mode: 0644]
src/hw/blockcmd.h [new file with mode: 0644]
src/hw/cmos.h [new file with mode: 0644]
src/hw/esp-scsi.c [new file with mode: 0644]
src/hw/esp-scsi.h [new file with mode: 0644]
src/hw/floppy.c [new file with mode: 0644]
src/hw/lsi-scsi.c [new file with mode: 0644]
src/hw/lsi-scsi.h [new file with mode: 0644]
src/hw/megasas.c [new file with mode: 0644]
src/hw/megasas.h [new file with mode: 0644]
src/hw/pci.c [new file with mode: 0644]
src/hw/pci.h [new file with mode: 0644]
src/hw/pci_ids.h [new file with mode: 0644]
src/hw/pci_regs.h [new file with mode: 0644]
src/hw/pic.c [new file with mode: 0644]
src/hw/pic.h [new file with mode: 0644]
src/hw/pit.h [new file with mode: 0644]
src/hw/ps2port.c [new file with mode: 0644]
src/hw/ps2port.h [new file with mode: 0644]
src/hw/ramdisk.c [new file with mode: 0644]
src/hw/timer.c [new file with mode: 0644]
src/hw/usb-ehci.c [new file with mode: 0644]
src/hw/usb-ehci.h [new file with mode: 0644]
src/hw/usb-hid.c [new file with mode: 0644]
src/hw/usb-hid.h [new file with mode: 0644]
src/hw/usb-hub.c [new file with mode: 0644]
src/hw/usb-hub.h [new file with mode: 0644]
src/hw/usb-msc.c [new file with mode: 0644]
src/hw/usb-msc.h [new file with mode: 0644]
src/hw/usb-ohci.c [new file with mode: 0644]
src/hw/usb-ohci.h [new file with mode: 0644]
src/hw/usb-uas.c [new file with mode: 0644]
src/hw/usb-uas.h [new file with mode: 0644]
src/hw/usb-uhci.c [new file with mode: 0644]
src/hw/usb-uhci.h [new file with mode: 0644]
src/hw/usb.c [new file with mode: 0644]
src/hw/usb.h [new file with mode: 0644]
src/hw/virtio-blk.c [new file with mode: 0644]
src/hw/virtio-blk.h [new file with mode: 0644]
src/hw/virtio-pci.c [new file with mode: 0644]
src/hw/virtio-pci.h [new file with mode: 0644]
src/hw/virtio-ring.c [new file with mode: 0644]
src/hw/virtio-ring.h [new file with mode: 0644]
src/hw/virtio-scsi.c [new file with mode: 0644]
src/hw/virtio-scsi.h [new file with mode: 0644]
src/kbd.c
src/lsi-scsi.c [deleted file]
src/lsi-scsi.h [deleted file]
src/megasas.c [deleted file]
src/megasas.h [deleted file]
src/misc.c
src/mouse.c
src/mptable.c
src/mtrr.c
src/optionroms.c
src/paravirt.c
src/pci.c [deleted file]
src/pci.h [deleted file]
src/pci_ids.h [deleted file]
src/pci_regs.h [deleted file]
src/pcibios.c
src/pciinit.c
src/pic.c [deleted file]
src/pic.h [deleted file]
src/pirtable.c
src/pit.h [deleted file]
src/post.c
src/ps2port.c [deleted file]
src/ps2port.h [deleted file]
src/ramdisk.c [deleted file]
src/resume.c
src/romlayout.S
src/shadow.c
src/smm.c
src/smp.c
src/system.c
src/timer.c [deleted file]
src/usb-ehci.c [deleted file]
src/usb-ehci.h [deleted file]
src/usb-hid.c [deleted file]
src/usb-hid.h [deleted file]
src/usb-hub.c [deleted file]
src/usb-hub.h [deleted file]
src/usb-msc.c [deleted file]
src/usb-msc.h [deleted file]
src/usb-ohci.c [deleted file]
src/usb-ohci.h [deleted file]
src/usb-uas.c [deleted file]
src/usb-uas.h [deleted file]
src/usb-uhci.c [deleted file]
src/usb-uhci.h [deleted file]
src/usb.c [deleted file]
src/usb.h [deleted file]
src/util.h
src/vgahooks.c
src/virtio-blk.c [deleted file]
src/virtio-blk.h [deleted file]
src/virtio-pci.c [deleted file]
src/virtio-pci.h [deleted file]
src/virtio-ring.c [deleted file]
src/virtio-ring.h [deleted file]
src/virtio-scsi.c [deleted file]
src/virtio-scsi.h [deleted file]
vgasrc/bochsvga.c
vgasrc/clext.c
vgasrc/geodevga.c
vgasrc/vgabios.c

index bafa246425db51b1119661e74dc974f3f3e219f6..a43fa14998ed0562a0f8d58be13e2e2c1a4a5308 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,19 +8,19 @@
 OUT=out/
 
 # Source files
-SRCBOTH=misc.c stacks.c output.c util.c block.c floppy.c ata.c mouse.c \
-    kbd.c pci.c serial.c timer.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \
-    pnpbios.c vgahooks.c ramdisk.c pcibios.c blockcmd.c \
-    usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-hid.c usb-msc.c \
-    virtio-ring.c virtio-pci.c virtio-blk.c virtio-scsi.c apm.c ahci.c \
-    usb-uas.c lsi-scsi.c esp-scsi.c megasas.c
+SRCBOTH=misc.c stacks.c output.c util.c block.c hw/floppy.c hw/ata.c mouse.c \
+    kbd.c hw/pci.c serial.c hw/timer.c clock.c hw/pic.c cdrom.c hw/ps2port.c smp.c resume.c \
+    pnpbios.c vgahooks.c hw/ramdisk.c pcibios.c hw/blockcmd.c \
+    hw/usb.c hw/usb-uhci.c hw/usb-ohci.c hw/usb-ehci.c hw/usb-hid.c hw/usb-msc.c \
+    hw/virtio-ring.c hw/virtio-pci.c hw/virtio-blk.c hw/virtio-scsi.c apm.c hw/ahci.c \
+    hw/usb-uas.c hw/lsi-scsi.c hw/esp-scsi.c hw/megasas.c
 SRC16=$(SRCBOTH) system.c disk.c font.c
 SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c pmm.c coreboot.c boot.c \
     acpi.c smm.c mptable.c pirtable.c smbios.c pciinit.c optionroms.c mtrr.c \
-    lzmadecode.c bootsplash.c jpeg.c usb-hub.c paravirt.c \
+    lzmadecode.c bootsplash.c jpeg.c hw/usb-hub.c paravirt.c \
     biostables.c xen.c bmp.c romfile.c csm.c
-SRC32SEG=util.c output.c pci.c pcibios.c apm.c stacks.c
-DIRS=src vgasrc
+SRC32SEG=util.c output.c hw/pci.c pcibios.c apm.c stacks.c
+DIRS=src src/hw vgasrc
 
 # Default compiler flags
 cc-option=$(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`" \
@@ -28,7 +28,7 @@ cc-option=$(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`" \
 
 CPPFLAGS = -P -MD -MT $@
 
-COMMONCFLAGS := -I$(OUT) -Os -MD -g \
+COMMONCFLAGS := -I$(OUT) -Isrc -Os -MD -g \
     -Wall -Wno-strict-aliasing -Wold-style-definition \
     $(call cc-option,$(CC),-Wtype-limits,) \
     -m32 -march=i386 -mregparm=3 -mpreferred-stack-boundary=2 \
@@ -175,7 +175,7 @@ $(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o scripts/checkrom.py
 ################ VGA build rules
 
 # VGA src files
-SRCVGA=src/output.c src/util.c src/pci.c \
+SRCVGA=src/output.c src/util.c src/hw/pci.c \
     vgasrc/vgabios.c vgasrc/vgafb.c vgasrc/vgafonts.c vgasrc/vbe.c \
     vgasrc/stdvga.c vgasrc/stdvgamodes.c vgasrc/stdvgaio.c \
     vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c
index 8db1ed4a7fe5f7d6eab9d7929626865f641bd738..774ff956e91a449e6ba8e3d3fd21af8b77fba5d5 100644 (file)
@@ -8,9 +8,9 @@
 #include "acpi.h" // struct rsdp_descriptor
 #include "util.h" // memcpy
 #include "byteorder.h" // cpu_to_le16
-#include "pci.h" // pci_find_init_device
-#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
-#include "pci_regs.h" // PCI_INTERRUPT_LINE
+#include "hw/pci.h" // pci_find_init_device
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "hw/pci_regs.h" // PCI_INTERRUPT_LINE
 #include "ioport.h" // inl
 #include "config.h" // CONFIG_*
 #include "paravirt.h" // RamSize
diff --git a/src/ahci.c b/src/ahci.c
deleted file mode 100644 (file)
index 0e99d14..0000000
+++ /dev/null
@@ -1,638 +0,0 @@
-// Low level AHCI disk access
-//
-// Copyright (C) 2010 Gerd Hoffmann <kraxel@redhat.com>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "types.h" // u8
-#include "ioport.h" // inb
-#include "util.h" // dprintf
-#include "biosvar.h" // GET_GLOBAL
-#include "pci.h" // foreachpci
-#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER
-#include "pci_regs.h" // PCI_INTERRUPT_LINE
-#include "boot.h" // add_bcv_hd
-#include "disk.h" // struct ata_s
-#include "ata.h" // ATA_CB_STAT
-#include "ahci.h" // CDB_CMD_READ_10
-#include "blockcmd.h" // CDB_CMD_READ_10
-
-#define AHCI_REQUEST_TIMEOUT 32000 // 32 seconds max for IDE ops
-#define AHCI_RESET_TIMEOUT     500 // 500 miliseconds
-#define AHCI_LINK_TIMEOUT       10 // 10 miliseconds
-
-/****************************************************************
- * these bits must run in both 16bit and 32bit modes
- ****************************************************************/
-
-// prepare sata command fis
-static void sata_prep_simple(struct sata_cmd_fis *fis, u8 command)
-{
-    memset_fl(fis, 0, sizeof(*fis));
-    SET_LOWFLAT(fis->command, command);
-}
-
-static void sata_prep_readwrite(struct sata_cmd_fis *fis,
-                                struct disk_op_s *op, int iswrite)
-{
-    u64 lba = op->lba;
-    u8 command;
-
-    memset_fl(fis, 0, sizeof(*fis));
-
-    if (op->count >= (1<<8) || lba + op->count >= (1<<28)) {
-        SET_LOWFLAT(fis->sector_count2, op->count >> 8);
-        SET_LOWFLAT(fis->lba_low2,      lba >> 24);
-        SET_LOWFLAT(fis->lba_mid2,      lba >> 32);
-        SET_LOWFLAT(fis->lba_high2,     lba >> 40);
-        lba &= 0xffffff;
-        command = (iswrite ? ATA_CMD_WRITE_DMA_EXT
-                   : ATA_CMD_READ_DMA_EXT);
-    } else {
-        command = (iswrite ? ATA_CMD_WRITE_DMA
-                   : ATA_CMD_READ_DMA);
-    }
-    SET_LOWFLAT(fis->feature,      1); /* dma */
-    SET_LOWFLAT(fis->command,      command);
-    SET_LOWFLAT(fis->sector_count, op->count);
-    SET_LOWFLAT(fis->lba_low,      lba);
-    SET_LOWFLAT(fis->lba_mid,      lba >> 8);
-    SET_LOWFLAT(fis->lba_high,     lba >> 16);
-    SET_LOWFLAT(fis->device,       ((lba >> 24) & 0xf) | ATA_CB_DH_LBA);
-}
-
-static void sata_prep_atapi(struct sata_cmd_fis *fis, u16 blocksize)
-{
-    memset_fl(fis, 0, sizeof(*fis));
-    SET_LOWFLAT(fis->command,  ATA_CMD_PACKET);
-    SET_LOWFLAT(fis->feature,  1); /* dma */
-    SET_LOWFLAT(fis->lba_mid,  blocksize);
-    SET_LOWFLAT(fis->lba_high, blocksize >> 8);
-}
-
-// ahci register access helpers
-static u32 ahci_ctrl_readl(struct ahci_ctrl_s *ctrl, u32 reg)
-{
-    u32 addr = GET_GLOBALFLAT(ctrl->iobase) + reg;
-    return pci_readl(addr);
-}
-
-static void ahci_ctrl_writel(struct ahci_ctrl_s *ctrl, u32 reg, u32 val)
-{
-    u32 addr = GET_GLOBALFLAT(ctrl->iobase) + reg;
-    pci_writel(addr, val);
-}
-
-static u32 ahci_port_to_ctrl(u32 pnr, u32 port_reg)
-{
-    u32 ctrl_reg = 0x100;
-    ctrl_reg += pnr * 0x80;
-    ctrl_reg += port_reg;
-    return ctrl_reg;
-}
-
-static u32 ahci_port_readl(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg)
-{
-    u32 ctrl_reg = ahci_port_to_ctrl(pnr, reg);
-    return ahci_ctrl_readl(ctrl, ctrl_reg);
-}
-
-static void ahci_port_writel(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg, u32 val)
-{
-    u32 ctrl_reg = ahci_port_to_ctrl(pnr, reg);
-    ahci_ctrl_writel(ctrl, ctrl_reg, val);
-}
-
-// submit ahci command + wait for result
-static int ahci_command(struct ahci_port_s *port, int iswrite, int isatapi,
-                        void *buffer, u32 bsize)
-{
-    u32 val, status, success, flags, intbits, error;
-    struct ahci_ctrl_s *ctrl = GET_GLOBAL(port->ctrl);
-    struct ahci_cmd_s  *cmd  = GET_GLOBAL(port->cmd);
-    struct ahci_fis_s  *fis  = GET_GLOBAL(port->fis);
-    struct ahci_list_s *list = GET_GLOBAL(port->list);
-    u32 pnr                  = GET_GLOBAL(port->pnr);
-
-    SET_LOWFLAT(cmd->fis.reg,       0x27);
-    SET_LOWFLAT(cmd->fis.pmp_type,  (1 << 7)); /* cmd fis */
-    SET_LOWFLAT(cmd->prdt[0].base,  ((u32)buffer));
-    SET_LOWFLAT(cmd->prdt[0].baseu, 0);
-    SET_LOWFLAT(cmd->prdt[0].flags, bsize-1);
-
-    flags = ((1 << 16) | /* one prd entry */
-             (iswrite ? (1 << 6) : 0) |
-             (isatapi ? (1 << 5) : 0) |
-             (5 << 0)); /* fis length (dwords) */
-    SET_LOWFLAT(list[0].flags,  flags);
-    SET_LOWFLAT(list[0].bytes,  0);
-    SET_LOWFLAT(list[0].base,   ((u32)(cmd)));
-    SET_LOWFLAT(list[0].baseu,  0);
-
-    dprintf(8, "AHCI/%d: send cmd ...\n", pnr);
-    intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT);
-    if (intbits)
-        ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits);
-    ahci_port_writel(ctrl, pnr, PORT_SCR_ACT, 1);
-    ahci_port_writel(ctrl, pnr, PORT_CMD_ISSUE, 1);
-
-    u32 end = timer_calc(AHCI_REQUEST_TIMEOUT);
-    do {
-        for (;;) {
-            intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT);
-            if (intbits) {
-                ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits);
-                if (intbits & 0x02) {
-                    status = GET_LOWFLAT(fis->psfis[2]);
-                    error  = GET_LOWFLAT(fis->psfis[3]);
-                    break;
-                }
-                if (intbits & 0x01) {
-                    status = GET_LOWFLAT(fis->rfis[2]);
-                    error  = GET_LOWFLAT(fis->rfis[3]);
-                    break;
-                }
-            }
-            if (timer_check(end)) {
-                warn_timeout();
-                return -1;
-            }
-            yield();
-        }
-        dprintf(8, "AHCI/%d: ... intbits 0x%x, status 0x%x ...\n",
-                pnr, intbits, status);
-    } while (status & ATA_CB_STAT_BSY);
-
-    success = (0x00 == (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF |
-                                  ATA_CB_STAT_ERR)) &&
-               ATA_CB_STAT_RDY == (status & (ATA_CB_STAT_RDY)));
-    if (success) {
-        dprintf(8, "AHCI/%d: ... finished, status 0x%x, OK\n", pnr,
-                status);
-    } else {
-        dprintf(2, "AHCI/%d: ... finished, status 0x%x, ERROR 0x%x\n", pnr,
-                status, error);
-
-        // non-queued error recovery (AHCI 1.3 section 6.2.2.1)
-        // Clears PxCMD.ST to 0 to reset the PxCI register
-        val = ahci_port_readl(ctrl, pnr, PORT_CMD);
-        ahci_port_writel(ctrl, pnr, PORT_CMD, val & ~PORT_CMD_START);
-
-        // waits for PxCMD.CR to clear to 0
-        while (1) {
-            val = ahci_port_readl(ctrl, pnr, PORT_CMD);
-            if ((val & PORT_CMD_LIST_ON) == 0)
-                break;
-            yield();
-        }
-
-        // Clears any error bits in PxSERR to enable capturing new errors
-        val = ahci_port_readl(ctrl, pnr, PORT_SCR_ERR);
-        ahci_port_writel(ctrl, pnr, PORT_SCR_ERR, val);
-
-        // Clears status bits in PxIS as appropriate
-        val = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT);
-        ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, val);
-
-        // If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to 1, issue
-        // a COMRESET to the device to put it in an idle state
-        val = ahci_port_readl(ctrl, pnr, PORT_TFDATA);
-        if (val & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ)) {
-            dprintf(2, "AHCI/%d: issue comreset\n", pnr);
-            val = ahci_port_readl(ctrl, pnr, PORT_SCR_CTL);
-            // set Device Detection Initialization (DET) to 1 for 1 ms for comreset
-            ahci_port_writel(ctrl, pnr, PORT_SCR_CTL, val | 1);
-            mdelay (1);
-            ahci_port_writel(ctrl, pnr, PORT_SCR_CTL, val);
-        }
-
-        // Sets PxCMD.ST to 1 to enable issuing new commands
-        val = ahci_port_readl(ctrl, pnr, PORT_CMD);
-        ahci_port_writel(ctrl, pnr, PORT_CMD, val | PORT_CMD_START);
-    }
-    return success ? 0 : -1;
-}
-
-#define CDROM_CDB_SIZE 12
-
-int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    if (! CONFIG_AHCI)
-        return 0;
-
-    struct ahci_port_s *port = container_of(
-        op->drive_g, struct ahci_port_s, drive);
-    struct ahci_cmd_s *cmd = GET_GLOBAL(port->cmd);
-    u8 *atapi = cdbcmd;
-    int i, rc;
-
-    sata_prep_atapi(&cmd->fis, blocksize);
-    for (i = 0; i < CDROM_CDB_SIZE; i++) {
-        SET_LOWFLAT(cmd->atapi[i], atapi[i]);
-    }
-    rc = ahci_command(port, 0, 1, op->buf_fl,
-                      op->count * blocksize);
-    if (rc < 0)
-        return DISK_RET_EBADTRACK;
-    return DISK_RET_SUCCESS;
-}
-
-// read/write count blocks from a harddrive, op->buf_fl must be word aligned
-static int
-ahci_disk_readwrite_aligned(struct disk_op_s *op, int iswrite)
-{
-    struct ahci_port_s *port = container_of(
-        op->drive_g, struct ahci_port_s, drive);
-    struct ahci_cmd_s *cmd = GET_GLOBAL(port->cmd);
-    int rc;
-
-    sata_prep_readwrite(&cmd->fis, op, iswrite);
-    rc = ahci_command(port, iswrite, 0, op->buf_fl,
-                      op->count * DISK_SECTOR_SIZE);
-    dprintf(8, "ahci disk %s, lba %6x, count %3x, buf %p, rc %d\n",
-            iswrite ? "write" : "read", (u32)op->lba, op->count, op->buf_fl, rc);
-    if (rc < 0)
-        return DISK_RET_EBADTRACK;
-    return DISK_RET_SUCCESS;
-}
-
-// read/write count blocks from a harddrive.
-static int
-ahci_disk_readwrite(struct disk_op_s *op, int iswrite)
-{
-    // if caller's buffer is word aligned, use it directly
-    if (((u32) op->buf_fl & 1) == 0)
-        return ahci_disk_readwrite_aligned(op, iswrite);
-
-    // Use a word aligned buffer for AHCI I/O
-    int rc;
-    struct disk_op_s localop = *op;
-    u8 *alignedbuf_fl = GET_GLOBAL(bounce_buf_fl);
-    u8 *position = op->buf_fl;
-
-    localop.buf_fl = alignedbuf_fl;
-    localop.count = 1;
-
-    if (iswrite) {
-        u16 block;
-        for (block = 0; block < op->count; block++) {
-            memcpy_fl (alignedbuf_fl, position, DISK_SECTOR_SIZE);
-            rc = ahci_disk_readwrite_aligned (&localop, 1);
-            if (rc)
-                return rc;
-            position += DISK_SECTOR_SIZE;
-            localop.lba++;
-        }
-    } else { // read
-        u16 block;
-        for (block = 0; block < op->count; block++) {
-            rc = ahci_disk_readwrite_aligned (&localop, 0);
-            if (rc)
-                return rc;
-            memcpy_fl (position, alignedbuf_fl, DISK_SECTOR_SIZE);
-            position += DISK_SECTOR_SIZE;
-            localop.lba++;
-        }
-    }
-    return DISK_RET_SUCCESS;
-}
-
-// command demuxer
-int process_ahci_op(struct disk_op_s *op)
-{
-    if (!CONFIG_AHCI)
-        return 0;
-    switch (op->command) {
-    case CMD_READ:
-        return ahci_disk_readwrite(op, 0);
-    case CMD_WRITE:
-        return ahci_disk_readwrite(op, 1);
-    case CMD_FORMAT:
-    case CMD_RESET:
-    case CMD_ISREADY:
-    case CMD_VERIFY:
-    case CMD_SEEK:
-        return DISK_RET_SUCCESS;
-    default:
-        dprintf(1, "AHCI: unknown disk command %d\n", op->command);
-        op->count = 0;
-        return DISK_RET_EPARAM;
-    }
-}
-
-/****************************************************************
- * everything below is pure 32bit code
- ****************************************************************/
-
-static void
-ahci_port_reset(struct ahci_ctrl_s *ctrl, u32 pnr)
-{
-    u32 val;
-
-    /* disable FIS + CMD */
-    u32 end = timer_calc(AHCI_RESET_TIMEOUT);
-    for (;;) {
-        val = ahci_port_readl(ctrl, pnr, PORT_CMD);
-        if (!(val & (PORT_CMD_FIS_RX | PORT_CMD_START |
-                     PORT_CMD_FIS_ON | PORT_CMD_LIST_ON)))
-            break;
-        val &= ~(PORT_CMD_FIS_RX | PORT_CMD_START);
-        ahci_port_writel(ctrl, pnr, PORT_CMD, val);
-        if (timer_check(end)) {
-            warn_timeout();
-            break;
-        }
-        yield();
-    }
-
-    /* disable + clear IRQs */
-    ahci_port_writel(ctrl, pnr, PORT_IRQ_MASK, 0);
-    val = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT);
-    if (val)
-        ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, val);
-}
-
-static struct ahci_port_s*
-ahci_port_alloc(struct ahci_ctrl_s *ctrl, u32 pnr)
-{
-    struct ahci_port_s *port = malloc_tmp(sizeof(*port));
-
-    if (!port) {
-        warn_noalloc();
-        return NULL;
-    }
-    port->pnr = pnr;
-    port->ctrl = ctrl;
-    port->list = memalign_tmp(1024, 1024);
-    port->fis = memalign_tmp(256, 256);
-    port->cmd = memalign_tmp(256, 256);
-    if (port->list == NULL || port->fis == NULL || port->cmd == NULL) {
-        warn_noalloc();
-        return NULL;
-    }
-    memset(port->list, 0, 1024);
-    memset(port->fis, 0, 256);
-    memset(port->cmd, 0, 256);
-
-    ahci_port_writel(ctrl, pnr, PORT_LST_ADDR, (u32)port->list);
-    ahci_port_writel(ctrl, pnr, PORT_FIS_ADDR, (u32)port->fis);
-    return port;
-}
-
-static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port)
-{
-    struct ahci_port_s *tmp;
-    u32 cmd;
-
-    tmp = malloc_fseg(sizeof(*port));
-    *tmp = *port;
-    free(port);
-    port = tmp;
-
-    ahci_port_reset(port->ctrl, port->pnr);
-
-    free(port->list);
-    free(port->fis);
-    free(port->cmd);
-    port->list = memalign_low(1024, 1024);
-    port->fis = memalign_low(256, 256);
-    port->cmd = memalign_low(256, 256);
-
-    ahci_port_writel(port->ctrl, port->pnr, PORT_LST_ADDR, (u32)port->list);
-    ahci_port_writel(port->ctrl, port->pnr, PORT_FIS_ADDR, (u32)port->fis);
-
-    cmd = ahci_port_readl(port->ctrl, port->pnr, PORT_CMD);
-    cmd |= (PORT_CMD_FIS_RX|PORT_CMD_START);
-    ahci_port_writel(port->ctrl, port->pnr, PORT_CMD, cmd);
-
-    return port;
-}
-
-static void ahci_port_release(struct ahci_port_s *port)
-{
-    ahci_port_reset(port->ctrl, port->pnr);
-    free(port->list);
-    free(port->fis);
-    free(port->cmd);
-    free(port);
-}
-
-#define MAXMODEL 40
-
-/* See ahci spec chapter 10.1 "Software Initialization of HBA" */
-static int ahci_port_setup(struct ahci_port_s *port)
-{
-    struct ahci_ctrl_s *ctrl = port->ctrl;
-    u32 pnr = port->pnr;
-    char model[MAXMODEL+1];
-    u16 buffer[256];
-    u32 cmd, stat, err, tf;
-    int rc;
-
-    /* enable FIS recv */
-    cmd = ahci_port_readl(ctrl, pnr, PORT_CMD);
-    cmd |= PORT_CMD_FIS_RX;
-    ahci_port_writel(ctrl, pnr, PORT_CMD, cmd);
-
-    /* spin up */
-    cmd |= PORT_CMD_SPIN_UP;
-    ahci_port_writel(ctrl, pnr, PORT_CMD, cmd);
-    u32 end = timer_calc(AHCI_LINK_TIMEOUT);
-    for (;;) {
-        stat = ahci_port_readl(ctrl, pnr, PORT_SCR_STAT);
-        if ((stat & 0x07) == 0x03) {
-            dprintf(2, "AHCI/%d: link up\n", port->pnr);
-            break;
-        }
-        if (timer_check(end)) {
-            dprintf(2, "AHCI/%d: link down\n", port->pnr);
-            return -1;
-        }
-        yield();
-    }
-
-    /* clear error status */
-    err = ahci_port_readl(ctrl, pnr, PORT_SCR_ERR);
-    if (err)
-        ahci_port_writel(ctrl, pnr, PORT_SCR_ERR, err);
-
-    /* wait for device becoming ready */
-    end = timer_calc(AHCI_REQUEST_TIMEOUT);
-    for (;;) {
-        tf = ahci_port_readl(ctrl, pnr, PORT_TFDATA);
-        if (!(tf & (ATA_CB_STAT_BSY |
-                    ATA_CB_STAT_DRQ)))
-            break;
-        if (timer_check(end)) {
-            warn_timeout();
-            dprintf(1, "AHCI/%d: device not ready (tf 0x%x)\n", port->pnr, tf);
-            return -1;
-        }
-        yield();
-    }
-
-    /* start device */
-    cmd |= PORT_CMD_START;
-    ahci_port_writel(ctrl, pnr, PORT_CMD, cmd);
-
-    sata_prep_simple(&port->cmd->fis, ATA_CMD_IDENTIFY_PACKET_DEVICE);
-    rc = ahci_command(port, 0, 0, buffer, sizeof(buffer));
-    if (rc == 0) {
-        port->atapi = 1;
-    } else {
-        port->atapi = 0;
-        sata_prep_simple(&port->cmd->fis, ATA_CMD_IDENTIFY_DEVICE);
-        rc = ahci_command(port, 0, 0, buffer, sizeof(buffer));
-        if (rc < 0)
-            return -1;
-    }
-
-    port->drive.cntl_id = pnr;
-    port->drive.removable = (buffer[0] & 0x80) ? 1 : 0;
-
-    if (!port->atapi) {
-        // found disk (ata)
-        port->drive.type = DTYPE_AHCI;
-        port->drive.blksize = DISK_SECTOR_SIZE;
-        port->drive.pchs.cylinders = buffer[1];
-        port->drive.pchs.heads = buffer[3];
-        port->drive.pchs.spt = buffer[6];
-
-        u64 sectors;
-        if (buffer[83] & (1 << 10)) // word 83 - lba48 support
-            sectors = *(u64*)&buffer[100]; // word 100-103
-        else
-            sectors = *(u32*)&buffer[60]; // word 60 and word 61
-        port->drive.sectors = sectors;
-        u64 adjsize = sectors >> 11;
-        char adjprefix = 'M';
-        if (adjsize >= (1 << 16)) {
-            adjsize >>= 10;
-            adjprefix = 'G';
-        }
-        port->desc = znprintf(MAXDESCSIZE
-                              , "AHCI/%d: %s ATA-%d Hard-Disk (%u %ciBytes)"
-                              , port->pnr
-                              , ata_extract_model(model, MAXMODEL, buffer)
-                              , ata_extract_version(buffer)
-                              , (u32)adjsize, adjprefix);
-        port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0);
-    } else {
-        // found cdrom (atapi)
-        port->drive.type = DTYPE_AHCI_ATAPI;
-        port->drive.blksize = CDROM_SECTOR_SIZE;
-        port->drive.sectors = (u64)-1;
-        u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
-        if (!iscd) {
-            dprintf(1, "AHCI/%d: atapi device isn't a cdrom\n", port->pnr);
-            return -1;
-        }
-        port->desc = znprintf(MAXDESCSIZE
-                              , "DVD/CD [AHCI/%d: %s ATAPI-%d DVD/CD]"
-                              , port->pnr
-                              , ata_extract_model(model, MAXMODEL, buffer)
-                              , ata_extract_version(buffer));
-        port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0);
-    }
-    return 0;
-}
-
-// Detect any drives attached to a given controller.
-static void
-ahci_port_detect(void *data)
-{
-    struct ahci_port_s *port = data;
-    int rc;
-
-    dprintf(2, "AHCI/%d: probing\n", port->pnr);
-    ahci_port_reset(port->ctrl, port->pnr);
-    rc = ahci_port_setup(port);
-    if (rc < 0)
-        ahci_port_release(port);
-    else {
-        port = ahci_port_realloc(port);
-        dprintf(1, "AHCI/%d: registering: \"%s\"\n", port->pnr, port->desc);
-        if (!port->atapi) {
-            // Register with bcv system.
-            boot_add_hd(&port->drive, port->desc, port->prio);
-        } else {
-            // fill cdidmap
-            boot_add_cd(&port->drive, port->desc, port->prio);
-        }
-    }
-}
-
-// Initialize an ata controller and detect its drives.
-static void
-ahci_controller_setup(struct pci_device *pci)
-{
-    struct ahci_ctrl_s *ctrl = malloc_fseg(sizeof(*ctrl));
-    struct ahci_port_s *port;
-    u16 bdf = pci->bdf;
-    u32 val, pnr, max;
-
-    if (!ctrl) {
-        warn_noalloc();
-        return;
-    }
-
-    if (create_bounce_buf() < 0) {
-        warn_noalloc();
-        free(ctrl);
-        return;
-    }
-
-    ctrl->pci_tmp = pci;
-    ctrl->pci_bdf = bdf;
-    ctrl->iobase = pci_config_readl(bdf, PCI_BASE_ADDRESS_5);
-    ctrl->irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
-    dprintf(1, "AHCI controller at %02x.%x, iobase %x, irq %d\n",
-            bdf >> 3, bdf & 7, ctrl->iobase, ctrl->irq);
-
-    pci_config_maskw(bdf, PCI_COMMAND, 0,
-                     PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-
-    val = ahci_ctrl_readl(ctrl, HOST_CTL);
-    ahci_ctrl_writel(ctrl, HOST_CTL, val | HOST_CTL_AHCI_EN);
-
-    ctrl->caps = ahci_ctrl_readl(ctrl, HOST_CAP);
-    ctrl->ports = ahci_ctrl_readl(ctrl, HOST_PORTS_IMPL);
-    dprintf(2, "AHCI: cap 0x%x, ports_impl 0x%x\n",
-            ctrl->caps, ctrl->ports);
-
-    max = ctrl->caps & 0x1f;
-    for (pnr = 0; pnr <= max; pnr++) {
-        if (!(ctrl->ports & (1 << pnr)))
-            continue;
-        port = ahci_port_alloc(ctrl, pnr);
-        if (port == NULL)
-            continue;
-        run_thread(ahci_port_detect, port);
-    }
-}
-
-// Locate and init ahci controllers.
-static void
-ahci_scan(void)
-{
-    // Scan PCI bus for ATA adapters
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci->class != PCI_CLASS_STORAGE_SATA)
-            continue;
-        if (pci->prog_if != 1 /* AHCI rev 1 */)
-            continue;
-        ahci_controller_setup(pci);
-    }
-}
-
-void
-ahci_setup(void)
-{
-    ASSERT32FLAT();
-    if (!CONFIG_AHCI)
-        return;
-
-    dprintf(3, "init ahci\n");
-    ahci_scan();
-}
diff --git a/src/ahci.h b/src/ahci.h
deleted file mode 100644 (file)
index c3d3a70..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-#ifndef __AHCI_H
-#define __AHCI_H
-
-struct sata_cmd_fis {
-    u8 reg;
-    u8 pmp_type;
-    u8 command;
-    u8 feature;
-
-    u8 lba_low;
-    u8 lba_mid;
-    u8 lba_high;
-    u8 device;
-
-    u8 lba_low2;
-    u8 lba_mid2;
-    u8 lba_high2;
-    u8 feature2;
-
-    u8 sector_count;
-    u8 sector_count2;
-    u8 res_1;
-    u8 control;
-
-    u8 res_2[64 - 16];
-};
-
-struct ahci_ctrl_s {
-    struct pci_device *pci_tmp;
-    u16 pci_bdf;
-    u8  irq;
-    u32 iobase;
-    u32 caps;
-    u32 ports;
-};
-
-struct ahci_cmd_s {
-    struct sata_cmd_fis fis;
-    u8 atapi[0x20];
-    u8 res[0x20];
-    struct {
-        u32 base;
-        u32 baseu;
-        u32 res;
-        u32 flags;
-    } prdt[];
-};
-
-/* command list */
-struct ahci_list_s {
-    u32 flags;
-    u32 bytes;
-    u32 base;
-    u32 baseu;
-    u32 res[4];
-};
-
-struct ahci_fis_s {
-    u8 dsfis[0x1c];  /* dma setup */
-    u8 res_1[0x04];
-    u8 psfis[0x14];  /* pio setup */
-    u8 res_2[0x0c];
-    u8 rfis[0x14];   /* d2h register */
-    u8 res_3[0x04];
-    u8 sdbfis[0x08]; /* set device bits */
-    u8 ufis[0x40];   /* unknown */
-    u8 res_4[0x60];
-};
-
-struct ahci_port_s {
-    struct drive_s     drive;
-    struct ahci_ctrl_s *ctrl;
-    struct ahci_list_s *list;
-    struct ahci_fis_s  *fis;
-    struct ahci_cmd_s  *cmd;
-    u32                pnr;
-    u32                atapi;
-    char               *desc;
-    int                prio;
-};
-
-void ahci_setup(void);
-int process_ahci_op(struct disk_op_s *op);
-int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
-
-#define AHCI_IRQ_ON_SG            (1 << 31)
-#define AHCI_CMD_ATAPI            (1 << 5)
-#define AHCI_CMD_WRITE            (1 << 6)
-#define AHCI_CMD_PREFETCH         (1 << 7)
-#define AHCI_CMD_RESET            (1 << 8)
-#define AHCI_CMD_CLR_BUSY         (1 << 10)
-
-#define RX_FIS_D2H_REG            0x40 /* offset of D2H Register FIS data */
-#define RX_FIS_SDB                0x58 /* offset of SDB FIS data */
-#define RX_FIS_UNK                0x60 /* offset of Unknown FIS data */
-
-/* global controller registers */
-#define HOST_CAP                  0x00 /* host capabilities */
-#define HOST_CTL                  0x04 /* global host control */
-#define HOST_IRQ_STAT             0x08 /* interrupt status */
-#define HOST_PORTS_IMPL           0x0c /* bitmap of implemented ports */
-#define HOST_VERSION              0x10 /* AHCI spec. version compliancy */
-
-/* HOST_CTL bits */
-#define HOST_CTL_RESET            (1 << 0)  /* reset controller; self-clear */
-#define HOST_CTL_IRQ_EN           (1 << 1)  /* global IRQ enable */
-#define HOST_CTL_AHCI_EN          (1 << 31) /* AHCI enabled */
-
-/* HOST_CAP bits */
-#define HOST_CAP_SSC              (1 << 14) /* Slumber capable */
-#define HOST_CAP_AHCI             (1 << 18) /* AHCI only */
-#define HOST_CAP_CLO              (1 << 24) /* Command List Override support */
-#define HOST_CAP_SSS              (1 << 27) /* Staggered Spin-up */
-#define HOST_CAP_NCQ              (1 << 30) /* Native Command Queueing */
-#define HOST_CAP_64               (1 << 31) /* PCI DAC (64-bit DMA) support */
-
-/* registers for each SATA port */
-#define PORT_LST_ADDR             0x00 /* command list DMA addr */
-#define PORT_LST_ADDR_HI          0x04 /* command list DMA addr hi */
-#define PORT_FIS_ADDR             0x08 /* FIS rx buf addr */
-#define PORT_FIS_ADDR_HI          0x0c /* FIS rx buf addr hi */
-#define PORT_IRQ_STAT             0x10 /* interrupt status */
-#define PORT_IRQ_MASK             0x14 /* interrupt enable/disable mask */
-#define PORT_CMD                  0x18 /* port command */
-#define PORT_TFDATA               0x20 /* taskfile data */
-#define PORT_SIG                  0x24 /* device TF signature */
-#define PORT_SCR_STAT             0x28 /* SATA phy register: SStatus */
-#define PORT_SCR_CTL              0x2c /* SATA phy register: SControl */
-#define PORT_SCR_ERR              0x30 /* SATA phy register: SError */
-#define PORT_SCR_ACT              0x34 /* SATA phy register: SActive */
-#define PORT_CMD_ISSUE            0x38 /* command issue */
-#define PORT_RESERVED             0x3c /* reserved */
-
-/* PORT_IRQ_{STAT,MASK} bits */
-#define PORT_IRQ_COLD_PRES        (1 << 31) /* cold presence detect */
-#define PORT_IRQ_TF_ERR           (1 << 30) /* task file error */
-#define PORT_IRQ_HBUS_ERR         (1 << 29) /* host bus fatal error */
-#define PORT_IRQ_HBUS_DATA_ERR    (1 << 28) /* host bus data error */
-#define PORT_IRQ_IF_ERR           (1 << 27) /* interface fatal error */
-#define PORT_IRQ_IF_NONFATAL      (1 << 26) /* interface non-fatal error */
-#define PORT_IRQ_OVERFLOW         (1 << 24) /* xfer exhausted available S/G */
-#define PORT_IRQ_BAD_PMP          (1 << 23) /* incorrect port multiplier */
-
-#define PORT_IRQ_PHYRDY           (1 << 22) /* PhyRdy changed */
-#define PORT_IRQ_DEV_ILCK         (1 << 7) /* device interlock */
-#define PORT_IRQ_CONNECT          (1 << 6) /* port connect change status */
-#define PORT_IRQ_SG_DONE          (1 << 5) /* descriptor processed */
-#define PORT_IRQ_UNK_FIS          (1 << 4) /* unknown FIS rx'd */
-#define PORT_IRQ_SDB_FIS          (1 << 3) /* Set Device Bits FIS rx'd */
-#define PORT_IRQ_DMAS_FIS         (1 << 2) /* DMA Setup FIS rx'd */
-#define PORT_IRQ_PIOS_FIS         (1 << 1) /* PIO Setup FIS rx'd */
-#define PORT_IRQ_D2H_REG_FIS      (1 << 0) /* D2H Register FIS rx'd */
-
-#define PORT_IRQ_FREEZE           (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR |   \
-                                   PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY |    \
-                                   PORT_IRQ_UNK_FIS)
-#define PORT_IRQ_ERROR            (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR |     \
-                                   PORT_IRQ_HBUS_DATA_ERR)
-#define DEF_PORT_IRQ              (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |     \
-                                   PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |  \
-                                   PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
-
-/* PORT_CMD bits */
-#define PORT_CMD_ATAPI            (1 << 24) /* Device is ATAPI */
-#define PORT_CMD_LIST_ON          (1 << 15) /* cmd list DMA engine running */
-#define PORT_CMD_FIS_ON           (1 << 14) /* FIS DMA engine running */
-#define PORT_CMD_FIS_RX           (1 << 4) /* Enable FIS receive DMA engine */
-#define PORT_CMD_CLO              (1 << 3) /* Command list override */
-#define PORT_CMD_POWER_ON         (1 << 2) /* Power up device */
-#define PORT_CMD_SPIN_UP          (1 << 1) /* Spin up device */
-#define PORT_CMD_START            (1 << 0) /* Enable port DMA engine */
-
-#define PORT_CMD_ICC_MASK         (0xf << 28) /* i/f ICC state mask */
-#define PORT_CMD_ICC_ACTIVE       (0x1 << 28) /* Put i/f in active state */
-#define PORT_CMD_ICC_PARTIAL      (0x2 << 28) /* Put i/f in partial state */
-#define PORT_CMD_ICC_SLUMBER      (0x6 << 28) /* Put i/f in slumber state */
-
-#define PORT_IRQ_STAT_DHRS        (1 << 0) /* Device to Host Register FIS */
-#define PORT_IRQ_STAT_PSS         (1 << 1) /* PIO Setup FIS */
-#define PORT_IRQ_STAT_DSS         (1 << 2) /* DMA Setup FIS */
-#define PORT_IRQ_STAT_SDBS        (1 << 3) /* Set Device Bits */
-#define PORT_IRQ_STAT_UFS         (1 << 4) /* Unknown FIS */
-#define PORT_IRQ_STAT_DPS         (1 << 5) /* Descriptor Processed */
-#define PORT_IRQ_STAT_PCS         (1 << 6) /* Port Connect Change Status */
-#define PORT_IRQ_STAT_DMPS        (1 << 7) /* Device Mechanical Presence
-                                              Status */
-#define PORT_IRQ_STAT_PRCS        (1 << 22) /* File Ready Status */
-#define PORT_IRQ_STAT_IPMS        (1 << 23) /* Incorrect Port Multiplier
-                                               Status */
-#define PORT_IRQ_STAT_OFS         (1 << 24) /* Overflow Status */
-#define PORT_IRQ_STAT_INFS        (1 << 26) /* Interface Non-Fatal Error
-                                               Status */
-#define PORT_IRQ_STAT_IFS         (1 << 27) /* Interface Fatal Error */
-#define PORT_IRQ_STAT_HBDS        (1 << 28) /* Host Bus Data Error Status */
-#define PORT_IRQ_STAT_HBFS        (1 << 29) /* Host Bus Fatal Error Status */
-#define PORT_IRQ_STAT_TFES        (1 << 30) /* Task File Error Status */
-#define PORT_IRQ_STAT_CPDS        (1 << 31) /* Code Port Detect Status */
-
-#endif // ahci.h
diff --git a/src/ata.c b/src/ata.c
deleted file mode 100644 (file)
index e319aa9..0000000
--- a/src/ata.c
+++ /dev/null
@@ -1,1043 +0,0 @@
-// Low level ATA disk access
-//
-// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2002  MandrakeSoft S.A.
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "types.h" // u8
-#include "ioport.h" // inb
-#include "util.h" // dprintf
-#include "byteorder.h" // be16_to_cpu
-#include "cmos.h" // inb_cmos
-#include "pic.h" // enable_hwirq
-#include "biosvar.h" // GET_GLOBAL
-#include "pci.h" // foreachpci
-#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER
-#include "pci_regs.h" // PCI_INTERRUPT_LINE
-#include "boot.h" // boot_add_hd
-#include "disk.h" // struct ata_s
-#include "ata.h" // ATA_CB_STAT
-#include "blockcmd.h" // CDB_CMD_READ_10
-
-#define IDE_TIMEOUT 32000 //32 seconds max for IDE ops
-
-
-/****************************************************************
- * Helper functions
- ****************************************************************/
-
-// Wait for the specified ide state
-static inline int
-await_ide(u8 mask, u8 flags, u16 base, u16 timeout)
-{
-    u32 end = timer_calc(timeout);
-    for (;;) {
-        u8 status = inb(base+ATA_CB_STAT);
-        if ((status & mask) == flags)
-            return status;
-        if (timer_check(end)) {
-            warn_timeout();
-            return -1;
-        }
-        yield();
-    }
-}
-
-// Wait for the device to be not-busy.
-static int
-await_not_bsy(u16 base)
-{
-    return await_ide(ATA_CB_STAT_BSY, 0, base, IDE_TIMEOUT);
-}
-
-// Wait for the device to be ready.
-static int
-await_rdy(u16 base)
-{
-    return await_ide(ATA_CB_STAT_RDY, ATA_CB_STAT_RDY, base, IDE_TIMEOUT);
-}
-
-// Wait for ide state - pauses for one ata cycle first.
-static inline int
-pause_await_not_bsy(u16 iobase1, u16 iobase2)
-{
-    // Wait one PIO transfer cycle.
-    inb(iobase2 + ATA_CB_ASTAT);
-
-    return await_not_bsy(iobase1);
-}
-
-// Wait for ide state - pause for 400ns first.
-static inline int
-ndelay_await_not_bsy(u16 iobase1)
-{
-    ndelay(400);
-    return await_not_bsy(iobase1);
-}
-
-// Reset a drive
-static void
-ata_reset(struct atadrive_s *adrive_g)
-{
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u8 slave = GET_GLOBAL(adrive_g->slave);
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
-
-    dprintf(6, "ata_reset drive=%p\n", &adrive_g->drive);
-    // Pulse SRST
-    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC);
-    udelay(5);
-    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
-    msleep(2);
-
-    // wait for device to become not busy.
-    int status = await_not_bsy(iobase1);
-    if (status < 0)
-        goto done;
-    if (slave) {
-        // Change device.
-        u32 end = timer_calc(IDE_TIMEOUT);
-        for (;;) {
-            outb(ATA_CB_DH_DEV1, iobase1 + ATA_CB_DH);
-            status = ndelay_await_not_bsy(iobase1);
-            if (status < 0)
-                goto done;
-            if (inb(iobase1 + ATA_CB_DH) == ATA_CB_DH_DEV1)
-                break;
-            // Change drive request failed to take effect - retry.
-            if (timer_check(end)) {
-                warn_timeout();
-                goto done;
-            }
-        }
-    } else {
-        // QEMU doesn't reset dh on reset, so set it explicitly.
-        outb(ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH);
-    }
-
-    // On a user-reset request, wait for RDY if it is an ATA device.
-    u8 type=GET_GLOBAL(adrive_g->drive.type);
-    if (type == DTYPE_ATA)
-        status = await_rdy(iobase1);
-
-done:
-    // Enable interrupts
-    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
-
-    dprintf(6, "ata_reset exit status=%x\n", status);
-}
-
-// Check for drive RDY for 16bit interface command.
-static int
-isready(struct atadrive_s *adrive_g)
-{
-    // Read the status from controller
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-    u8 status = inb(iobase1 + ATA_CB_STAT);
-    if ((status & (ATA_CB_STAT_BSY|ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY)
-        return DISK_RET_SUCCESS;
-    return DISK_RET_ENOTREADY;
-}
-
-
-/****************************************************************
- * ATA send command
- ****************************************************************/
-
-struct ata_pio_command {
-    u8 feature;
-    u8 sector_count;
-    u8 lba_low;
-    u8 lba_mid;
-    u8 lba_high;
-    u8 device;
-    u8 command;
-
-    u8 feature2;
-    u8 sector_count2;
-    u8 lba_low2;
-    u8 lba_mid2;
-    u8 lba_high2;
-};
-
-// Send an ata command to the drive.
-static int
-send_cmd(struct atadrive_s *adrive_g, struct ata_pio_command *cmd)
-{
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u8 slave = GET_GLOBAL(adrive_g->slave);
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-
-    // Select device
-    int status = await_not_bsy(iobase1);
-    if (status < 0)
-        return status;
-    u8 newdh = ((cmd->device & ~ATA_CB_DH_DEV1)
-                | (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0));
-    u8 olddh = inb(iobase1 + ATA_CB_DH);
-    outb(newdh, iobase1 + ATA_CB_DH);
-    if ((olddh ^ newdh) & (1<<4)) {
-        // Was a device change - wait for device to become not busy.
-        status = ndelay_await_not_bsy(iobase1);
-        if (status < 0)
-            return status;
-    }
-
-    // Check for ATA_CMD_(READ|WRITE)_(SECTORS|DMA)_EXT commands.
-    if ((cmd->command & ~0x11) == ATA_CMD_READ_SECTORS_EXT) {
-        outb(cmd->feature2, iobase1 + ATA_CB_FR);
-        outb(cmd->sector_count2, iobase1 + ATA_CB_SC);
-        outb(cmd->lba_low2, iobase1 + ATA_CB_SN);
-        outb(cmd->lba_mid2, iobase1 + ATA_CB_CL);
-        outb(cmd->lba_high2, iobase1 + ATA_CB_CH);
-    }
-    outb(cmd->feature, iobase1 + ATA_CB_FR);
-    outb(cmd->sector_count, iobase1 + ATA_CB_SC);
-    outb(cmd->lba_low, iobase1 + ATA_CB_SN);
-    outb(cmd->lba_mid, iobase1 + ATA_CB_CL);
-    outb(cmd->lba_high, iobase1 + ATA_CB_CH);
-    outb(cmd->command, iobase1 + ATA_CB_CMD);
-
-    return 0;
-}
-
-// Wait for data after calling 'send_cmd'.
-static int
-ata_wait_data(u16 iobase1)
-{
-    int status = ndelay_await_not_bsy(iobase1);
-    if (status < 0)
-        return status;
-
-    if (status & ATA_CB_STAT_ERR) {
-        dprintf(6, "send_cmd : read error (status=%02x err=%02x)\n"
-                , status, inb(iobase1 + ATA_CB_ERR));
-        return -4;
-    }
-    if (!(status & ATA_CB_STAT_DRQ)) {
-        dprintf(6, "send_cmd : DRQ not set (status %02x)\n", status);
-        return -5;
-    }
-
-    return 0;
-}
-
-// Send an ata command that does not transfer any further data.
-int
-ata_cmd_nondata(struct atadrive_s *adrive_g, struct ata_pio_command *cmd)
-{
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
-
-    // Disable interrupts
-    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
-
-    int ret = send_cmd(adrive_g, cmd);
-    if (ret)
-        goto fail;
-    ret = ndelay_await_not_bsy(iobase1);
-    if (ret < 0)
-        goto fail;
-
-    if (ret & ATA_CB_STAT_ERR) {
-        dprintf(6, "nondata cmd : read error (status=%02x err=%02x)\n"
-                , ret, inb(iobase1 + ATA_CB_ERR));
-        ret = -4;
-        goto fail;
-    }
-    if (ret & ATA_CB_STAT_DRQ) {
-        dprintf(6, "nondata cmd : DRQ set (status %02x)\n", ret);
-        ret = -5;
-        goto fail;
-    }
-
-fail:
-    // Enable interrupts
-    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
-
-    return ret;
-}
-
-
-/****************************************************************
- * ATA PIO transfers
- ****************************************************************/
-
-// Transfer 'op->count' blocks (of 'blocksize' bytes) to/from drive
-// 'op->drive_g'.
-static int
-ata_pio_transfer(struct disk_op_s *op, int iswrite, int blocksize)
-{
-    dprintf(16, "ata_pio_transfer id=%p write=%d count=%d bs=%d buf=%p\n"
-            , op->drive_g, iswrite, op->count, blocksize, op->buf_fl);
-
-    struct atadrive_s *adrive_g = container_of(
-        op->drive_g, struct atadrive_s, drive);
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
-    int count = op->count;
-    void *buf_fl = op->buf_fl;
-    int status;
-    for (;;) {
-        if (iswrite) {
-            // Write data to controller
-            dprintf(16, "Write sector id=%p dest=%p\n", op->drive_g, buf_fl);
-            if (CONFIG_ATA_PIO32)
-                outsl_fl(iobase1, buf_fl, blocksize / 4);
-            else
-                outsw_fl(iobase1, buf_fl, blocksize / 2);
-        } else {
-            // Read data from controller
-            dprintf(16, "Read sector id=%p dest=%p\n", op->drive_g, buf_fl);
-            if (CONFIG_ATA_PIO32)
-                insl_fl(iobase1, buf_fl, blocksize / 4);
-            else
-                insw_fl(iobase1, buf_fl, blocksize / 2);
-        }
-        buf_fl += blocksize;
-
-        status = pause_await_not_bsy(iobase1, iobase2);
-        if (status < 0) {
-            // Error
-            op->count -= count;
-            return status;
-        }
-
-        count--;
-        if (!count)
-            break;
-        status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR);
-        if (status != ATA_CB_STAT_DRQ) {
-            dprintf(6, "ata_pio_transfer : more sectors left (status %02x)\n"
-                    , status);
-            op->count -= count;
-            return -6;
-        }
-    }
-
-    status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ
-               | ATA_CB_STAT_ERR);
-    if (!iswrite)
-        status &= ~ATA_CB_STAT_DF;
-    if (status != 0) {
-        dprintf(6, "ata_pio_transfer : no sectors left (status %02x)\n", status);
-        return -7;
-    }
-
-    return 0;
-}
-
-
-/****************************************************************
- * ATA DMA transfers
- ****************************************************************/
-
-#define BM_CMD    0
-#define  BM_CMD_MEMWRITE  0x08
-#define  BM_CMD_START     0x01
-#define BM_STATUS 2
-#define  BM_STATUS_IRQ    0x04
-#define  BM_STATUS_ERROR  0x02
-#define  BM_STATUS_ACTIVE 0x01
-#define BM_TABLE  4
-
-struct sff_dma_prd {
-    u32 buf_fl;
-    u32 count;
-};
-
-// Check if DMA available and setup transfer if so.
-static int
-ata_try_dma(struct disk_op_s *op, int iswrite, int blocksize)
-{
-    ASSERT16();
-    if (! CONFIG_ATA_DMA)
-        return -1;
-    u32 dest = (u32)op->buf_fl;
-    if (dest & 1)
-        // Need minimum alignment of 1.
-        return -1;
-    struct atadrive_s *adrive_g = container_of(
-        op->drive_g, struct atadrive_s, drive);
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u16 iomaster = GET_GLOBALFLAT(chan_gf->iomaster);
-    if (! iomaster)
-        return -1;
-    u32 bytes = op->count * blocksize;
-    if (! bytes)
-        return -1;
-
-    // Build PRD dma structure.
-    struct sff_dma_prd *dma = MAKE_FLATPTR(SEG_LOW, ExtraStack);
-    struct sff_dma_prd *origdma = dma;
-    while (bytes) {
-        if (dma >= &origdma[16])
-            // Too many descriptors..
-            return -1;
-        u32 count = bytes;
-        u32 max = 0x10000 - (dest & 0xffff);
-        if (count > max)
-            count = max;
-
-        SET_LOWFLAT(dma->buf_fl, dest);
-        bytes -= count;
-        if (!bytes)
-            // Last descriptor.
-            count |= 1<<31;
-        dprintf(16, "dma@%p: %08x %08x\n", dma, dest, count);
-        dest += count;
-        SET_LOWFLAT(dma->count, count);
-        dma++;
-    }
-
-    // Program bus-master controller.
-    outl((u32)origdma, iomaster + BM_TABLE);
-    u8 oldcmd = inb(iomaster + BM_CMD) & ~(BM_CMD_MEMWRITE|BM_CMD_START);
-    outb(oldcmd | (iswrite ? 0x00 : BM_CMD_MEMWRITE), iomaster + BM_CMD);
-    outb(BM_STATUS_ERROR|BM_STATUS_IRQ, iomaster + BM_STATUS);
-
-    return 0;
-}
-
-// Transfer data using DMA.
-static int
-ata_dma_transfer(struct disk_op_s *op)
-{
-    if (! CONFIG_ATA_DMA)
-        return -1;
-    dprintf(16, "ata_dma_transfer id=%p buf=%p\n", op->drive_g, op->buf_fl);
-
-    struct atadrive_s *adrive_g = container_of(
-        op->drive_g, struct atadrive_s, drive);
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u16 iomaster = GET_GLOBALFLAT(chan_gf->iomaster);
-
-    // Start bus-master controller.
-    u8 oldcmd = inb(iomaster + BM_CMD);
-    outb(oldcmd | BM_CMD_START, iomaster + BM_CMD);
-
-    u32 end = timer_calc(IDE_TIMEOUT);
-    u8 status;
-    for (;;) {
-        status = inb(iomaster + BM_STATUS);
-        if (status & BM_STATUS_IRQ)
-            break;
-        // Transfer in progress
-        if (timer_check(end)) {
-            // Timeout.
-            warn_timeout();
-            break;
-        }
-        yield();
-    }
-    outb(oldcmd & ~BM_CMD_START, iomaster + BM_CMD);
-
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
-    int idestatus = pause_await_not_bsy(iobase1, iobase2);
-
-    if ((status & (BM_STATUS_IRQ|BM_STATUS_ACTIVE)) == BM_STATUS_IRQ
-        && idestatus >= 0x00
-        && (idestatus & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ
-                         | ATA_CB_STAT_ERR)) == 0x00)
-        // Success.
-        return 0;
-
-    dprintf(6, "IDE DMA error (dma=%x ide=%x/%x/%x)\n", status, idestatus
-            , inb(iobase2 + ATA_CB_ASTAT), inb(iobase1 + ATA_CB_ERR));
-    op->count = 0;
-    return -1;
-}
-
-
-/****************************************************************
- * ATA hard drive functions
- ****************************************************************/
-
-// Transfer data to harddrive using PIO protocol.
-static int
-ata_pio_cmd_data(struct disk_op_s *op, int iswrite, struct ata_pio_command *cmd)
-{
-    struct atadrive_s *adrive_g = container_of(
-        op->drive_g, struct atadrive_s, drive);
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
-
-    // Disable interrupts
-    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
-
-    int ret = send_cmd(adrive_g, cmd);
-    if (ret)
-        goto fail;
-    ret = ata_wait_data(iobase1);
-    if (ret)
-        goto fail;
-    ret = ata_pio_transfer(op, iswrite, DISK_SECTOR_SIZE);
-
-fail:
-    // Enable interrupts
-    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
-    return ret;
-}
-
-// Transfer data to harddrive using DMA protocol.
-static int
-ata_dma_cmd_data(struct disk_op_s *op, struct ata_pio_command *cmd)
-{
-    if (! CONFIG_ATA_DMA)
-        return -1;
-    struct atadrive_s *adrive_g = container_of(
-        op->drive_g, struct atadrive_s, drive);
-    int ret = send_cmd(adrive_g, cmd);
-    if (ret)
-        return ret;
-    return ata_dma_transfer(op);
-}
-
-// Read/write count blocks from a harddrive.
-static int
-ata_readwrite(struct disk_op_s *op, int iswrite)
-{
-    u64 lba = op->lba;
-
-    int usepio = ata_try_dma(op, iswrite, DISK_SECTOR_SIZE);
-
-    struct ata_pio_command cmd;
-    memset(&cmd, 0, sizeof(cmd));
-
-    if (op->count >= (1<<8) || lba + op->count >= (1<<28)) {
-        cmd.sector_count2 = op->count >> 8;
-        cmd.lba_low2 = lba >> 24;
-        cmd.lba_mid2 = lba >> 32;
-        cmd.lba_high2 = lba >> 40;
-        lba &= 0xffffff;
-
-        if (usepio)
-            cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS_EXT
-                           : ATA_CMD_READ_SECTORS_EXT);
-        else
-            cmd.command = (iswrite ? ATA_CMD_WRITE_DMA_EXT
-                           : ATA_CMD_READ_DMA_EXT);
-    } else {
-        if (usepio)
-            cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS
-                           : ATA_CMD_READ_SECTORS);
-        else
-            cmd.command = (iswrite ? ATA_CMD_WRITE_DMA
-                           : ATA_CMD_READ_DMA);
-    }
-
-    cmd.sector_count = op->count;
-    cmd.lba_low = lba;
-    cmd.lba_mid = lba >> 8;
-    cmd.lba_high = lba >> 16;
-    cmd.device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA;
-
-    int ret;
-    if (usepio)
-        ret = ata_pio_cmd_data(op, iswrite, &cmd);
-    else
-        ret = ata_dma_cmd_data(op, &cmd);
-    if (ret)
-        return DISK_RET_EBADTRACK;
-    return DISK_RET_SUCCESS;
-}
-
-// 16bit command demuxer for ATA harddrives.
-int
-process_ata_op(struct disk_op_s *op)
-{
-    if (!CONFIG_ATA)
-        return 0;
-
-    struct atadrive_s *adrive_g = container_of(
-        op->drive_g, struct atadrive_s, drive);
-    switch (op->command) {
-    case CMD_READ:
-        return ata_readwrite(op, 0);
-    case CMD_WRITE:
-        return ata_readwrite(op, 1);
-    case CMD_RESET:
-        ata_reset(adrive_g);
-        return DISK_RET_SUCCESS;
-    case CMD_ISREADY:
-        return isready(adrive_g);
-    case CMD_FORMAT:
-    case CMD_VERIFY:
-    case CMD_SEEK:
-        return DISK_RET_SUCCESS;
-    default:
-        op->count = 0;
-        return DISK_RET_EPARAM;
-    }
-}
-
-
-/****************************************************************
- * ATAPI functions
- ****************************************************************/
-
-#define CDROM_CDB_SIZE 12
-
-// Low-level atapi command transmit function.
-int
-atapi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    if (! CONFIG_ATA)
-        return 0;
-
-    struct atadrive_s *adrive_g = container_of(
-        op->drive_g, struct atadrive_s, drive);
-    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
-    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
-    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
-
-    struct ata_pio_command cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.lba_mid = blocksize;
-    cmd.lba_high = blocksize >> 8;
-    cmd.command = ATA_CMD_PACKET;
-
-    // Disable interrupts
-    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
-
-    int ret = send_cmd(adrive_g, &cmd);
-    if (ret)
-        goto fail;
-    ret = ata_wait_data(iobase1);
-    if (ret)
-        goto fail;
-
-    // Send command to device
-    outsw_fl(iobase1, MAKE_FLATPTR(GET_SEG(SS), cdbcmd), CDROM_CDB_SIZE / 2);
-
-    int status = pause_await_not_bsy(iobase1, iobase2);
-    if (status < 0) {
-        ret = status;
-        goto fail;
-    }
-
-    if (status & ATA_CB_STAT_ERR) {
-        u8 err = inb(iobase1 + ATA_CB_ERR);
-        // skip "Not Ready"
-        if (err != 0x20)
-            dprintf(6, "send_atapi_cmd : read error (status=%02x err=%02x)\n"
-                    , status, err);
-        ret = -2;
-        goto fail;
-    }
-    if (blocksize) {
-        if (!(status & ATA_CB_STAT_DRQ)) {
-            dprintf(6, "send_atapi_cmd : DRQ not set (status %02x)\n", status);
-            ret = -3;
-            goto fail;
-        }
-
-        ret = ata_pio_transfer(op, 0, blocksize);
-    }
-
-fail:
-    // Enable interrupts
-    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
-    if (ret)
-        return DISK_RET_EBADTRACK;
-    return DISK_RET_SUCCESS;
-}
-
-
-/****************************************************************
- * ATA detect and init
- ****************************************************************/
-
-// Send an identify device or identify device packet command.
-static int
-send_ata_identity(struct atadrive_s *adrive_g, u16 *buffer, int command)
-{
-    memset(buffer, 0, DISK_SECTOR_SIZE);
-
-    struct disk_op_s dop;
-    memset(&dop, 0, sizeof(dop));
-    dop.drive_g = &adrive_g->drive;
-    dop.count = 1;
-    dop.lba = 1;
-    dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer);
-
-    struct ata_pio_command cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.command = command;
-
-    return ata_pio_cmd_data(&dop, 0, &cmd);
-}
-
-// Extract the ATA/ATAPI version info.
-int
-ata_extract_version(u16 *buffer)
-{
-    // Extract ATA/ATAPI version.
-    u16 ataversion = buffer[80];
-    u8 version;
-    for (version=15; version>0; version--)
-        if (ataversion & (1<<version))
-            break;
-    return version;
-}
-
-#define MAXMODEL 40
-
-// Extract the ATA/ATAPI model info.
-char *
-ata_extract_model(char *model, u32 size, u16 *buffer)
-{
-    // Read model name
-    int i;
-    for (i=0; i<size/2; i++)
-        *(u16*)&model[i*2] = be16_to_cpu(buffer[27+i]);
-    model[size] = 0x00;
-    nullTrailingSpace(model);
-    return model;
-}
-
-// Common init code between ata and atapi
-static struct atadrive_s *
-init_atadrive(struct atadrive_s *dummy, u16 *buffer)
-{
-    struct atadrive_s *adrive_g = malloc_fseg(sizeof(*adrive_g));
-    if (!adrive_g) {
-        warn_noalloc();
-        return NULL;
-    }
-    memset(adrive_g, 0, sizeof(*adrive_g));
-    adrive_g->chan_gf = dummy->chan_gf;
-    adrive_g->slave = dummy->slave;
-    adrive_g->drive.cntl_id = adrive_g->chan_gf->chanid * 2 + dummy->slave;
-    adrive_g->drive.removable = (buffer[0] & 0x80) ? 1 : 0;
-    return adrive_g;
-}
-
-// Detect if the given drive is an atapi - initialize it if so.
-static struct atadrive_s *
-init_drive_atapi(struct atadrive_s *dummy, u16 *buffer)
-{
-    // Send an IDENTIFY_DEVICE_PACKET command to device
-    int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_PACKET_DEVICE);
-    if (ret)
-        return NULL;
-
-    // Success - setup as ATAPI.
-    struct atadrive_s *adrive_g = init_atadrive(dummy, buffer);
-    if (!adrive_g)
-        return NULL;
-    adrive_g->drive.type = DTYPE_ATA_ATAPI;
-    adrive_g->drive.blksize = CDROM_SECTOR_SIZE;
-    adrive_g->drive.sectors = (u64)-1;
-    u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
-    char model[MAXMODEL+1];
-    char *desc = znprintf(MAXDESCSIZE
-                          , "DVD/CD [ata%d-%d: %s ATAPI-%d %s]"
-                          , adrive_g->chan_gf->chanid, adrive_g->slave
-                          , ata_extract_model(model, MAXMODEL, buffer)
-                          , ata_extract_version(buffer)
-                          , (iscd ? "DVD/CD" : "Device"));
-    dprintf(1, "%s\n", desc);
-
-    // fill cdidmap
-    if (iscd) {
-        int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_tmp,
-                                            adrive_g->chan_gf->chanid,
-                                            adrive_g->slave);
-        boot_add_cd(&adrive_g->drive, desc, prio);
-    }
-
-    return adrive_g;
-}
-
-// Detect if the given drive is a regular ata drive - initialize it if so.
-static struct atadrive_s *
-init_drive_ata(struct atadrive_s *dummy, u16 *buffer)
-{
-    // Send an IDENTIFY_DEVICE command to device
-    int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_DEVICE);
-    if (ret)
-        return NULL;
-
-    // Success - setup as ATA.
-    struct atadrive_s *adrive_g = init_atadrive(dummy, buffer);
-    if (!adrive_g)
-        return NULL;
-    adrive_g->drive.type = DTYPE_ATA;
-    adrive_g->drive.blksize = DISK_SECTOR_SIZE;
-
-    adrive_g->drive.pchs.cylinders = buffer[1];
-    adrive_g->drive.pchs.heads = buffer[3];
-    adrive_g->drive.pchs.spt = buffer[6];
-
-    u64 sectors;
-    if (buffer[83] & (1 << 10)) // word 83 - lba48 support
-        sectors = *(u64*)&buffer[100]; // word 100-103
-    else
-        sectors = *(u32*)&buffer[60]; // word 60 and word 61
-    adrive_g->drive.sectors = sectors;
-    u64 adjsize = sectors >> 11;
-    char adjprefix = 'M';
-    if (adjsize >= (1 << 16)) {
-        adjsize >>= 10;
-        adjprefix = 'G';
-    }
-    char model[MAXMODEL+1];
-    char *desc = znprintf(MAXDESCSIZE
-                          , "ata%d-%d: %s ATA-%d Hard-Disk (%u %ciBytes)"
-                          , adrive_g->chan_gf->chanid, adrive_g->slave
-                          , ata_extract_model(model, MAXMODEL, buffer)
-                          , ata_extract_version(buffer)
-                          , (u32)adjsize, adjprefix);
-    dprintf(1, "%s\n", desc);
-
-    int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_tmp,
-                                        adrive_g->chan_gf->chanid,
-                                        adrive_g->slave);
-    // Register with bcv system.
-    boot_add_hd(&adrive_g->drive, desc, prio);
-
-    return adrive_g;
-}
-
-static u32 SpinupEnd;
-
-// Wait for non-busy status and check for "floating bus" condition.
-static int
-powerup_await_non_bsy(u16 base)
-{
-    u8 orstatus = 0;
-    u8 status;
-    for (;;) {
-        status = inb(base+ATA_CB_STAT);
-        if (!(status & ATA_CB_STAT_BSY))
-            break;
-        orstatus |= status;
-        if (orstatus == 0xff) {
-            dprintf(4, "powerup IDE floating\n");
-            return orstatus;
-        }
-        if (timer_check(SpinupEnd)) {
-            warn_timeout();
-            return -1;
-        }
-        yield();
-    }
-    dprintf(6, "powerup iobase=%x st=%x\n", base, status);
-    return status;
-}
-
-// Detect any drives attached to a given controller.
-static void
-ata_detect(void *data)
-{
-    struct ata_channel_s *chan_gf = data;
-    struct atadrive_s dummy;
-    memset(&dummy, 0, sizeof(dummy));
-    dummy.chan_gf = chan_gf;
-    // Device detection
-    int didreset = 0;
-    u8 slave;
-    for (slave=0; slave<=1; slave++) {
-        // Wait for not-bsy.
-        u16 iobase1 = chan_gf->iobase1;
-        int status = powerup_await_non_bsy(iobase1);
-        if (status < 0)
-            continue;
-        u8 newdh = slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0;
-        outb(newdh, iobase1+ATA_CB_DH);
-        ndelay(400);
-        status = powerup_await_non_bsy(iobase1);
-        if (status < 0)
-            continue;
-
-        // Check if ioport registers look valid.
-        outb(newdh, iobase1+ATA_CB_DH);
-        u8 dh = inb(iobase1+ATA_CB_DH);
-        outb(0x55, iobase1+ATA_CB_SC);
-        outb(0xaa, iobase1+ATA_CB_SN);
-        u8 sc = inb(iobase1+ATA_CB_SC);
-        u8 sn = inb(iobase1+ATA_CB_SN);
-        dprintf(6, "ata_detect ata%d-%d: sc=%x sn=%x dh=%x\n"
-                , chan_gf->chanid, slave, sc, sn, dh);
-        if (sc != 0x55 || sn != 0xaa || dh != newdh)
-            continue;
-
-        // Prepare new drive.
-        dummy.slave = slave;
-
-        // reset the channel
-        if (!didreset) {
-            ata_reset(&dummy);
-            didreset = 1;
-        }
-
-        // check for ATAPI
-        u16 buffer[256];
-        struct atadrive_s *adrive_g = init_drive_atapi(&dummy, buffer);
-        if (!adrive_g) {
-            // Didn't find an ATAPI drive - look for ATA drive.
-            u8 st = inb(iobase1+ATA_CB_STAT);
-            if (!st)
-                // Status not set - can't be a valid drive.
-                continue;
-
-            // Wait for RDY.
-            int ret = await_rdy(iobase1);
-            if (ret < 0)
-                continue;
-
-            // check for ATA.
-            adrive_g = init_drive_ata(&dummy, buffer);
-            if (!adrive_g)
-                // No ATA drive found
-                continue;
-        }
-
-        u16 resetresult = buffer[93];
-        dprintf(6, "ata_detect resetresult=%04x\n", resetresult);
-        if (!slave && (resetresult & 0xdf61) == 0x4041)
-            // resetresult looks valid and device 0 is responding to
-            // device 1 requests - device 1 must not be present - skip
-            // detection.
-            break;
-    }
-}
-
-// Initialize an ata controller and detect its drives.
-static void
-init_controller(struct pci_device *pci, int irq
-                , u32 port1, u32 port2, u32 master)
-{
-    static int chanid = 0;
-    struct ata_channel_s *chan_gf = malloc_fseg(sizeof(*chan_gf));
-    if (!chan_gf) {
-        warn_noalloc();
-        return;
-    }
-    chan_gf->chanid = chanid++;
-    chan_gf->irq = irq;
-    chan_gf->pci_bdf = pci ? pci->bdf : -1;
-    chan_gf->pci_tmp = pci;
-    chan_gf->iobase1 = port1;
-    chan_gf->iobase2 = port2;
-    chan_gf->iomaster = master;
-    dprintf(1, "ATA controller %d at %x/%x/%x (irq %d dev %x)\n"
-            , chanid, port1, port2, master, irq, chan_gf->pci_bdf);
-    run_thread(ata_detect, chan_gf);
-}
-
-#define IRQ_ATA1 14
-#define IRQ_ATA2 15
-
-// Handle controllers on an ATA PCI device.
-static void
-init_pciata(struct pci_device *pci, u8 prog_if)
-{
-    pci->have_driver = 1;
-    u16 bdf = pci->bdf;
-    u8 pciirq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
-    int master = 0;
-    if (CONFIG_ATA_DMA && prog_if & 0x80) {
-        // Check for bus-mastering.
-        u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_4);
-        if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
-            master = bar & PCI_BASE_ADDRESS_IO_MASK;
-            pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
-        }
-    }
-
-    u32 port1, port2, irq;
-    if (prog_if & 1) {
-        port1 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_0)
-                 & PCI_BASE_ADDRESS_IO_MASK);
-        port2 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_1)
-                 & PCI_BASE_ADDRESS_IO_MASK);
-        irq = pciirq;
-    } else {
-        port1 = PORT_ATA1_CMD_BASE;
-        port2 = PORT_ATA1_CTRL_BASE;
-        irq = IRQ_ATA1;
-    }
-    init_controller(pci, irq, port1, port2, master);
-
-    if (prog_if & 4) {
-        port1 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_2)
-                 & PCI_BASE_ADDRESS_IO_MASK);
-        port2 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_3)
-                 & PCI_BASE_ADDRESS_IO_MASK);
-        irq = pciirq;
-    } else {
-        port1 = PORT_ATA2_CMD_BASE;
-        port2 = PORT_ATA2_CTRL_BASE;
-        irq = IRQ_ATA2;
-    }
-    init_controller(pci, irq, port1, port2, master ? master + 8 : 0);
-}
-
-static void
-found_genericata(struct pci_device *pci, void *arg)
-{
-    init_pciata(pci, pci->prog_if);
-}
-
-static void
-found_compatibleahci(struct pci_device *pci, void *arg)
-{
-    if (CONFIG_AHCI)
-        // Already handled directly via native ahci interface.
-        return;
-    init_pciata(pci, 0x8f);
-}
-
-static const struct pci_device_id pci_ata_tbl[] = {
-    PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE
-                     , found_genericata),
-    PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4391, found_compatibleahci),
-    PCI_DEVICE_END,
-};
-
-// Locate and init ata controllers.
-static void
-ata_scan(void)
-{
-    if (CONFIG_QEMU && hlist_empty(&PCIDevices)) {
-        // No PCI devices found - probably a QEMU "-M isapc" machine.
-        // Try using ISA ports for ATA controllers.
-        init_controller(NULL, IRQ_ATA1
-                        , PORT_ATA1_CMD_BASE, PORT_ATA1_CTRL_BASE, 0);
-        init_controller(NULL, IRQ_ATA2
-                        , PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE, 0);
-        return;
-    }
-
-    // Scan PCI bus for ATA adapters
-    struct pci_device *pci;
-    foreachpci(pci) {
-        pci_init_device(pci_ata_tbl, pci, NULL);
-    }
-}
-
-void
-ata_setup(void)
-{
-    ASSERT32FLAT();
-    if (!CONFIG_ATA)
-        return;
-
-    dprintf(3, "init hard drives\n");
-
-    SpinupEnd = timer_calc(IDE_TIMEOUT);
-    ata_scan();
-
-    SET_BDA(disk_control_byte, 0xc0);
-
-    enable_hwirq(14, FUNC16(entry_76));
-}
diff --git a/src/ata.h b/src/ata.h
deleted file mode 100644 (file)
index 1f41233..0000000
--- a/src/ata.h
+++ /dev/null
@@ -1,153 +0,0 @@
-#ifndef __ATA_H
-#define __ATA_H
-
-#include "types.h" // u8
-#include "config.h" // CONFIG_MAX_ATA_INTERFACES
-#include "disk.h" // struct drive_s
-
-struct ata_channel_s {
-    u16 iobase1;
-    u16 iobase2;
-    u16 iomaster;
-    u8  irq;
-    u8  chanid;
-    int pci_bdf;
-    struct pci_device *pci_tmp;
-};
-
-struct atadrive_s {
-    struct drive_s drive;
-    struct ata_channel_s *chan_gf;
-    u8 slave;
-};
-
-// ata.c
-char *ata_extract_model(char *model, u32 size, u16 *buffer);
-int ata_extract_version(u16 *buffer);
-int cdrom_read(struct disk_op_s *op);
-int atapi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
-void ata_setup(void);
-int process_ata_op(struct disk_op_s *op);
-
-// Global defines -- ATA register and register bits.
-// command block & control block regs
-#define ATA_CB_DATA  0   // data reg         in/out pio_base_addr1+0
-#define ATA_CB_ERR   1   // error            in     pio_base_addr1+1
-#define ATA_CB_FR    1   // feature reg         out pio_base_addr1+1
-#define ATA_CB_SC    2   // sector count     in/out pio_base_addr1+2
-#define ATA_CB_SN    3   // sector number    in/out pio_base_addr1+3
-#define ATA_CB_CL    4   // cylinder low     in/out pio_base_addr1+4
-#define ATA_CB_CH    5   // cylinder high    in/out pio_base_addr1+5
-#define ATA_CB_DH    6   // device head      in/out pio_base_addr1+6
-#define ATA_CB_STAT  7   // primary status   in     pio_base_addr1+7
-#define ATA_CB_CMD   7   // command             out pio_base_addr1+7
-
-#define ATA_CB_ASTAT 2   // alternate status in     pio_base_addr2+2
-#define ATA_CB_DC    2   // device control      out pio_base_addr2+2
-#define ATA_CB_DA    3   // device address   in     pio_base_addr2+3
-
-#define ATA_CB_ER_ICRC 0x80    // ATA Ultra DMA bad CRC
-#define ATA_CB_ER_BBK  0x80    // ATA bad block
-#define ATA_CB_ER_UNC  0x40    // ATA uncorrected error
-#define ATA_CB_ER_MC   0x20    // ATA media change
-#define ATA_CB_ER_IDNF 0x10    // ATA id not found
-#define ATA_CB_ER_MCR  0x08    // ATA media change request
-#define ATA_CB_ER_ABRT 0x04    // ATA command aborted
-#define ATA_CB_ER_NTK0 0x02    // ATA track 0 not found
-#define ATA_CB_ER_NDAM 0x01    // ATA address mark not found
-
-#define ATA_CB_ER_P_SNSKEY 0xf0   // ATAPI sense key (mask)
-#define ATA_CB_ER_P_MCR    0x08   // ATAPI Media Change Request
-#define ATA_CB_ER_P_ABRT   0x04   // ATAPI command abort
-#define ATA_CB_ER_P_EOM    0x02   // ATAPI End of Media
-#define ATA_CB_ER_P_ILI    0x01   // ATAPI Illegal Length Indication
-
-// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
-#define ATA_CB_SC_P_TAG    0xf8   // ATAPI tag (mask)
-#define ATA_CB_SC_P_REL    0x04   // ATAPI release
-#define ATA_CB_SC_P_IO     0x02   // ATAPI I/O
-#define ATA_CB_SC_P_CD     0x01   // ATAPI C/D
-
-// bits 7-4 of the device/head (CB_DH) reg
-#define ATA_CB_DH_DEV0 0xa0    // select device 0
-#define ATA_CB_DH_DEV1 0xb0    // select device 1
-#define ATA_CB_DH_LBA 0x40    // use LBA
-
-// status reg (CB_STAT and CB_ASTAT) bits
-#define ATA_CB_STAT_BSY  0x80  // busy
-#define ATA_CB_STAT_RDY  0x40  // ready
-#define ATA_CB_STAT_DF   0x20  // device fault
-#define ATA_CB_STAT_WFT  0x20  // write fault (old name)
-#define ATA_CB_STAT_SKC  0x10  // seek complete
-#define ATA_CB_STAT_SERV 0x10  // service
-#define ATA_CB_STAT_DRQ  0x08  // data request
-#define ATA_CB_STAT_CORR 0x04  // corrected
-#define ATA_CB_STAT_IDX  0x02  // index
-#define ATA_CB_STAT_ERR  0x01  // error (ATA)
-#define ATA_CB_STAT_CHK  0x01  // check (ATAPI)
-
-// device control reg (CB_DC) bits
-#define ATA_CB_DC_HD15   0x08  // bit should always be set to one
-#define ATA_CB_DC_SRST   0x04  // soft reset
-#define ATA_CB_DC_NIEN   0x02  // disable interrupts
-
-// Most mandtory and optional ATA commands (from ATA-3),
-#define ATA_CMD_NOP                          0x00
-#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE     0x03
-#define ATA_CMD_DEVICE_RESET                 0x08
-#define ATA_CMD_RECALIBRATE                  0x10
-#define ATA_CMD_READ_SECTORS                 0x20
-#define ATA_CMD_READ_SECTORS_EXT             0x24
-#define ATA_CMD_READ_DMA_EXT                 0x25
-#define ATA_CMD_READ_DMA_QUEUED_EXT          0x26
-#define ATA_CMD_READ_NATIVE_MAX_ADDRESS_EXT  0x27
-#define ATA_CMD_READ_MULTIPLE_EXT            0x29
-#define ATA_CMD_READ_LOG_EXT                 0x2F
-#define ATA_CMD_WRITE_SECTORS                0x30
-#define ATA_CMD_WRITE_SECTORS_EXT            0x34
-#define ATA_CMD_WRITE_DMA_EXT                0x35
-#define ATA_CMD_WRITE_DMA_QUEUED_EXT         0x36
-#define ATA_CMD_SET_MAX_ADDRESS_EXT          0x37
-#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE   0x38
-#define ATA_CMD_WRITE_MULTIPLE_EXT           0x39
-#define ATA_CMD_WRITE_VERIFY                 0x3C
-#define ATA_CMD_WRITE_LOG_EXT                0x3F
-#define ATA_CMD_READ_VERIFY_SECTORS          0x40
-#define ATA_CMD_READ_VERIFY_SECTORS_EXT      0x42
-#define ATA_CMD_FORMAT_TRACK                 0x50
-#define ATA_CMD_SEEK                         0x70
-#define ATA_CMD_CFA_TRANSLATE_SECTOR         0x87
-#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC    0x90
-#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
-#define ATA_CMD_STANDBY_IMMEDIATE2           0x94
-#define ATA_CMD_IDLE_IMMEDIATE2              0x95
-#define ATA_CMD_STANDBY2                     0x96
-#define ATA_CMD_IDLE2                        0x97
-#define ATA_CMD_CHECK_POWER_MODE2            0x98
-#define ATA_CMD_SLEEP2                       0x99
-#define ATA_CMD_PACKET                       0xA0
-#define ATA_CMD_IDENTIFY_PACKET_DEVICE       0xA1
-#define ATA_CMD_CFA_ERASE_SECTORS            0xC0
-#define ATA_CMD_READ_MULTIPLE                0xC4
-#define ATA_CMD_WRITE_MULTIPLE               0xC5
-#define ATA_CMD_SET_MULTIPLE_MODE            0xC6
-#define ATA_CMD_READ_DMA_QUEUED              0xC7
-#define ATA_CMD_READ_DMA                     0xC8
-#define ATA_CMD_WRITE_DMA                    0xCA
-#define ATA_CMD_WRITE_DMA_QUEUED             0xCC
-#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE  0xCD
-#define ATA_CMD_STANDBY_IMMEDIATE            0xE0
-#define ATA_CMD_IDLE_IMMEDIATE               0xE1
-#define ATA_CMD_STANDBY                      0xE2
-#define ATA_CMD_IDLE                         0xE3
-#define ATA_CMD_READ_BUFFER                  0xE4
-#define ATA_CMD_CHECK_POWER_MODE             0xE5
-#define ATA_CMD_SLEEP                        0xE6
-#define ATA_CMD_FLUSH_CACHE                  0xE7
-#define ATA_CMD_WRITE_BUFFER                 0xE8
-#define ATA_CMD_IDENTIFY_DEVICE              0xEC
-#define ATA_CMD_SET_FEATURES                 0xEF
-#define ATA_CMD_READ_NATIVE_MAX_ADDRESS      0xF8
-#define ATA_CMD_SET_MAX                      0xF9
-
-#endif // ata.h
index 7b860e1db7af121b5ed63a0f1846824ec8654777..beb0bed307ed9020a439ad775cf63a20bcc84cca 100644 (file)
@@ -6,7 +6,7 @@
 
 #include "config.h" // CONFIG_*
 #include "util.h" // dprintf
-#include "pci.h" // struct pir_header
+#include "hw/pci.h" // struct pir_header
 #include "acpi.h" // struct rsdp_descriptor
 #include "mptable.h" // MPTABLE_SIGNATURE
 #include "smbios.h" // struct smbios_entry_point
index af7363056ae04f791aadf75c2cd2559acf0ab82f..74c649701b4fbe78c6de38a5043f1bfeb9d71bef 100644 (file)
@@ -7,12 +7,12 @@
 
 #include "disk.h" // struct ata_s
 #include "biosvar.h" // GET_GLOBAL
-#include "cmos.h" // inb_cmos
+#include "hw/cmos.h" // inb_cmos
 #include "util.h" // dprintf
-#include "ata.h" // process_ata_op
-#include "ahci.h" // process_ahci_op
-#include "virtio-blk.h" // process_virtio_blk_op
-#include "blockcmd.h" // cdb_*
+#include "hw/ata.h" // process_ata_op
+#include "hw/ahci.h" // process_ahci_op
+#include "hw/virtio-blk.h" // process_virtio_blk_op
+#include "hw/blockcmd.h" // cdb_*
 
 u8 FloppyCount VARFSEG;
 u8 CDCount;
diff --git a/src/blockcmd.c b/src/blockcmd.c
deleted file mode 100644 (file)
index 5cd4eb0..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-// Support for several common scsi like command data block requests
-//
-// Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2002  MandrakeSoft S.A.
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "biosvar.h" // GET_GLOBAL
-#include "util.h" // dprintf
-#include "byteorder.h" // be32_to_cpu
-#include "disk.h" // struct disk_op_s
-#include "blockcmd.h" // struct cdb_request_sense
-#include "ata.h" // atapi_cmd_data
-#include "ahci.h" // atapi_cmd_data
-#include "usb-msc.h" // usb_cmd_data
-#include "usb-uas.h" // usb_cmd_data
-#include "virtio-scsi.h" // virtio_scsi_cmd_data
-#include "lsi-scsi.h" // lsi_scsi_cmd_data
-#include "esp-scsi.h" // esp_scsi_cmd_data
-#include "megasas.h" // megasas_cmd_data
-#include "boot.h" // boot_add_hd
-
-// Route command to low-level handler.
-static int
-cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    u8 type = GET_GLOBAL(op->drive_g->type);
-    switch (type) {
-    case DTYPE_ATA_ATAPI:
-        return atapi_cmd_data(op, cdbcmd, blocksize);
-    case DTYPE_USB:
-        return usb_cmd_data(op, cdbcmd, blocksize);
-    case DTYPE_UAS:
-        return uas_cmd_data(op, cdbcmd, blocksize);
-    case DTYPE_AHCI_ATAPI:
-        return ahci_cmd_data(op, cdbcmd, blocksize);
-    case DTYPE_VIRTIO_SCSI:
-        return virtio_scsi_cmd_data(op, cdbcmd, blocksize);
-    case DTYPE_LSI_SCSI:
-        return lsi_scsi_cmd_data(op, cdbcmd, blocksize);
-    case DTYPE_ESP_SCSI:
-        return esp_scsi_cmd_data(op, cdbcmd, blocksize);
-    case DTYPE_MEGASAS:
-        return megasas_cmd_data(op, cdbcmd, blocksize);
-    default:
-        op->count = 0;
-        return DISK_RET_EPARAM;
-    }
-}
-
-// Determine if the command is a request to pull data from the device
-int
-cdb_is_read(u8 *cdbcmd, u16 blocksize)
-{
-    return blocksize && cdbcmd[0] != CDB_CMD_WRITE_10;
-}
-
-int
-scsi_is_ready(struct disk_op_s *op)
-{
-    dprintf(6, "scsi_is_ready (drive=%p)\n", op->drive_g);
-
-    /* Retry TEST UNIT READY for 5 seconds unless MEDIUM NOT PRESENT is
-     * reported by the device.  If the device reports "IN PROGRESS",
-     * 30 seconds is added. */
-    int in_progress = 0;
-    u32 end = timer_calc(5000);
-    for (;;) {
-        if (timer_check(end)) {
-            dprintf(1, "test unit ready failed\n");
-            return -1;
-        }
-
-        int ret = cdb_test_unit_ready(op);
-        if (!ret)
-            // Success
-            break;
-
-        struct cdbres_request_sense sense;
-        ret = cdb_get_sense(op, &sense);
-        if (ret)
-            // Error - retry.
-            continue;
-
-        // Sense succeeded.
-        if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */
-            dprintf(1, "Device reports MEDIUM NOT PRESENT\n");
-            return -1;
-        }
-
-        if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) {
-            /* IN PROGRESS OF BECOMING READY */
-            printf("Waiting for device to detect medium... ");
-            /* Allow 30 seconds more */
-            end = timer_calc(30000);
-            in_progress = 1;
-        }
-    }
-    return 0;
-}
-
-// Validate drive, find block size / sector count, and register drive.
-int
-scsi_drive_setup(struct drive_s *drive, const char *s, int prio)
-{
-    struct disk_op_s dop;
-    memset(&dop, 0, sizeof(dop));
-    dop.drive_g = drive;
-    struct cdbres_inquiry data;
-    int ret = cdb_get_inquiry(&dop, &data);
-    if (ret)
-        return ret;
-    char vendor[sizeof(data.vendor)+1], product[sizeof(data.product)+1];
-    char rev[sizeof(data.rev)+1];
-    strtcpy(vendor, data.vendor, sizeof(vendor));
-    nullTrailingSpace(vendor);
-    strtcpy(product, data.product, sizeof(product));
-    nullTrailingSpace(product);
-    strtcpy(rev, data.rev, sizeof(rev));
-    nullTrailingSpace(rev);
-    int pdt = data.pdt & 0x1f;
-    int removable = !!(data.removable & 0x80);
-    dprintf(1, "%s vendor='%s' product='%s' rev='%s' type=%d removable=%d\n"
-            , s, vendor, product, rev, pdt, removable);
-    drive->removable = removable;
-
-    if (pdt == SCSI_TYPE_CDROM) {
-        drive->blksize = CDROM_SECTOR_SIZE;
-        drive->sectors = (u64)-1;
-
-        char *desc = znprintf(MAXDESCSIZE, "DVD/CD [%s Drive %s %s %s]"
-                              , s, vendor, product, rev);
-        boot_add_cd(drive, desc, prio);
-        return 0;
-    }
-
-    ret = scsi_is_ready(&dop);
-    if (ret) {
-        dprintf(1, "scsi_is_ready returned %d\n", ret);
-        return ret;
-    }
-
-    struct cdbres_read_capacity capdata;
-    ret = cdb_read_capacity(&dop, &capdata);
-    if (ret)
-        return ret;
-
-    // READ CAPACITY returns the address of the last block.
-    // We do not bother with READ CAPACITY(16) because BIOS does not support
-    // 64-bit LBA anyway.
-    drive->blksize = be32_to_cpu(capdata.blksize);
-    if (drive->blksize != DISK_SECTOR_SIZE) {
-        dprintf(1, "%s: unsupported block size %d\n", s, drive->blksize);
-        return -1;
-    }
-    drive->sectors = (u64)be32_to_cpu(capdata.sectors) + 1;
-    dprintf(1, "%s blksize=%d sectors=%d\n"
-            , s, drive->blksize, (unsigned)drive->sectors);
-
-    // We do not recover from USB stalls, so try to be safe and avoid
-    // sending the command if the (obsolete, but still provided by QEMU)
-    // fixed disk geometry page may not be supported.
-    //
-    // We could also send the command only to small disks (e.g. <504MiB)
-    // but some old USB keys only support a very small subset of SCSI which
-    // does not even include the MODE SENSE command!
-    //
-    if (CONFIG_QEMU_HARDWARE && memcmp(vendor, "QEMU", 5) == 0) {
-        struct cdbres_mode_sense_geom geomdata;
-        ret = cdb_mode_sense_geom(&dop, &geomdata);
-        if (ret == 0) {
-            u32 cylinders;
-            cylinders = geomdata.cyl[0] << 16;
-            cylinders |= geomdata.cyl[1] << 8;
-            cylinders |= geomdata.cyl[2];
-            if (cylinders && geomdata.heads &&
-                drive->sectors <= 0xFFFFFFFFULL &&
-                ((u32)drive->sectors % (geomdata.heads * cylinders) == 0)) {
-                drive->pchs.cylinders = cylinders;
-                drive->pchs.heads = geomdata.heads;
-                drive->pchs.spt = (u32)drive->sectors / (geomdata.heads * cylinders);
-            }
-        }
-    }
-
-    char *desc = znprintf(MAXDESCSIZE, "%s Drive %s %s %s"
-                          , s, vendor, product, rev);
-    boot_add_hd(drive, desc, prio);
-    return 0;
-}
-
-int
-cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data)
-{
-    struct cdb_request_sense cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.command = CDB_CMD_INQUIRY;
-    cmd.length = sizeof(*data);
-    op->count = 1;
-    op->buf_fl = data;
-    return cdb_cmd_data(op, &cmd, sizeof(*data));
-}
-
-// Request SENSE
-int
-cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data)
-{
-    struct cdb_request_sense cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.command = CDB_CMD_REQUEST_SENSE;
-    cmd.length = sizeof(*data);
-    op->count = 1;
-    op->buf_fl = data;
-    return cdb_cmd_data(op, &cmd, sizeof(*data));
-}
-
-// Test unit ready
-int
-cdb_test_unit_ready(struct disk_op_s *op)
-{
-    struct cdb_request_sense cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.command = CDB_CMD_TEST_UNIT_READY;
-    op->count = 0;
-    op->buf_fl = NULL;
-    return cdb_cmd_data(op, &cmd, 0);
-}
-
-// Request capacity
-int
-cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data)
-{
-    struct cdb_read_capacity cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.command = CDB_CMD_READ_CAPACITY;
-    op->count = 1;
-    op->buf_fl = data;
-    return cdb_cmd_data(op, &cmd, sizeof(*data));
-}
-
-// Mode sense, geometry page.
-int
-cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data)
-{
-    struct cdb_mode_sense cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.command = CDB_CMD_MODE_SENSE;
-    cmd.flags = 8; /* DBD */
-    cmd.page = MODE_PAGE_HD_GEOMETRY;
-    cmd.count = cpu_to_be16(sizeof(*data));
-    op->count = 1;
-    op->buf_fl = data;
-    return cdb_cmd_data(op, &cmd, sizeof(*data));
-}
-
-// Read sectors.
-int
-cdb_read(struct disk_op_s *op)
-{
-    struct cdb_rwdata_10 cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.command = CDB_CMD_READ_10;
-    cmd.lba = cpu_to_be32(op->lba);
-    cmd.count = cpu_to_be16(op->count);
-    return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
-}
-
-// Write sectors.
-int
-cdb_write(struct disk_op_s *op)
-{
-    struct cdb_rwdata_10 cmd;
-    memset(&cmd, 0, sizeof(cmd));
-    cmd.command = CDB_CMD_WRITE_10;
-    cmd.lba = cpu_to_be32(op->lba);
-    cmd.count = cpu_to_be16(op->count);
-    return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
-}
diff --git a/src/blockcmd.h b/src/blockcmd.h
deleted file mode 100644 (file)
index 8bacfcf..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-// Definitions for SCSI style command data blocks.
-#ifndef __BLOCKCMD_H
-#define __BLOCKCMD_H
-
-#include "types.h" // u8
-
-#define CDB_CMD_READ_10 0x28
-#define CDB_CMD_VERIFY_10 0x2f
-#define CDB_CMD_WRITE_10 0x2a
-
-struct cdb_rwdata_10 {
-    u8 command;
-    u8 flags;
-    u32 lba;
-    u8 resreved_06;
-    u16 count;
-    u8 reserved_09;
-    u8 pad[6];
-} PACKED;
-
-#define CDB_CMD_READ_CAPACITY 0x25
-
-struct cdb_read_capacity {
-    u8 command;
-    u8 flags;
-    u8 resreved_02[8];
-    u8 pad[6];
-} PACKED;
-
-struct cdbres_read_capacity {
-    u32 sectors;
-    u32 blksize;
-} PACKED;
-
-#define CDB_CMD_TEST_UNIT_READY  0x00
-#define CDB_CMD_INQUIRY          0x12
-#define CDB_CMD_REQUEST_SENSE    0x03
-
-struct cdb_request_sense {
-    u8 command;
-    u8 flags;
-    u16 reserved_02;
-    u8 length;
-    u8 reserved_05;
-    u8 pad[10];
-} PACKED;
-
-struct cdbres_request_sense {
-    u8 errcode;
-    u8 segment;
-    u8 flags;
-    u32 info;
-    u8 additional;
-    u32 specific;
-    u8 asc;
-    u8 ascq;
-    u32 reserved_0e;
-} PACKED;
-
-#define SCSI_TYPE_DISK  0x00
-#define SCSI_TYPE_CDROM 0x05
-
-struct cdbres_inquiry {
-    u8 pdt;
-    u8 removable;
-    u8 reserved_02[2];
-    u8 additional;
-    u8 reserved_05[3];
-    char vendor[8];
-    char product[16];
-    char rev[4];
-} PACKED;
-
-#define CDB_CMD_MODE_SENSE    0x5A
-#define MODE_PAGE_HD_GEOMETRY 0x04
-
-struct cdb_mode_sense {
-    u8 command;
-    u8 flags;
-    u8 page;
-    u32 reserved_03;
-    u16 count;
-    u8 reserved_09;
-    u8 pad[6];
-} PACKED;
-
-struct cdbres_mode_sense_geom {
-    u8 unused_00[3];
-    u8 read_only;
-    u32 unused_04;
-    u8 page;
-    u8 length;
-    u8 cyl[3];
-    u8 heads;
-    u8 precomp[3];
-    u8 reduced[3];
-    u16 step_rate;
-    u8 landing[3];
-    u16 rpm;
-} PACKED;
-
-// blockcmd.c
-int cdb_is_read(u8 *cdbcmd, u16 blocksize);
-struct disk_op_s;
-int cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data);
-int cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data);
-int cdb_test_unit_ready(struct disk_op_s *op);
-int cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data);
-int cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data);
-int cdb_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data);
-int cdb_read(struct disk_op_s *op);
-int cdb_write(struct disk_op_s *op);
-
-int scsi_is_ready(struct disk_op_s *op);
-struct drive_s;
-int scsi_drive_setup(struct drive_s *drive, const char *s, int prio);
-
-#endif // blockcmd.h
index c3438401de2c10fe4eb0e7291ef436892d82ac8c..4d8f1613bed4edbe4a552f5730220c61891ee1a4 100644 (file)
 #include "disk.h" // cdrom_boot
 #include "bregs.h" // struct bregs
 #include "boot.h" // func defs
-#include "cmos.h" // inb_cmos
+#include "hw/cmos.h" // inb_cmos
 #include "paravirt.h" // qemu_cfg_show_boot_menu
-#include "pci.h" // pci_bdf_to_*
-#include "usb.h" // struct usbdevice_s
+#include "hw/pci.h" // pci_bdf_to_*
+#include "hw/usb.h" // struct usbdevice_s
 #include "csm.h" // csm_bootprio_*
 #include "list.h" // hlist_node
 
index b2811cd09a1e12530ca387757c4e909350182f8b..94265b04307887b28a666b36fea5174c635cf03a 100644 (file)
@@ -9,8 +9,8 @@
 #include "util.h" // memset
 #include "bregs.h" // struct bregs
 #include "biosvar.h" // GET_GLOBAL
-#include "ata.h" // ATA_CMD_REQUEST_SENSE
-#include "blockcmd.h" // CDB_CMD_REQUEST_SENSE
+#include "hw/ata.h" // ATA_CMD_REQUEST_SENSE
+#include "hw/blockcmd.h" // CDB_CMD_REQUEST_SENSE
 
 // Locks for removable devices
 u8 CDRom_locks[BUILD_MAX_EXTDRIVE] VARLOW;
index 5014b604cfcfa88de59c5c666eb94cb558e2cf26..cc962e47fba28f6398572e3ae32cec87db9a723b 100644 (file)
@@ -8,12 +8,12 @@
 #include "biosvar.h" // SET_BDA
 #include "util.h" // debug_enter
 #include "disk.h" // floppy_tick
-#include "cmos.h" // inb_cmos
-#include "pic.h" // pic_eoi1
-#include "pit.h" // PM_SEL_TIMER0
+#include "hw/cmos.h" // inb_cmos
+#include "hw/pic.h" // pic_eoi1
+#include "hw/pit.h" // PM_SEL_TIMER0
 #include "bregs.h" // struct bregs
 #include "biosvar.h" // GET_GLOBAL
-#include "usb-hid.h" // usb_check_event
+#include "hw/usb-hid.h" // usb_check_event
 
 // RTC register flags
 #define RTC_A_UIP 0x80
diff --git a/src/cmos.h b/src/cmos.h
deleted file mode 100644 (file)
index 067c7fa..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// Definitions for X86 CMOS non-volatile memory access.
-//
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-#ifndef __CMOS_H
-#define __CMOS_H
-
-// Standard BIOS RTC chip entries
-#define CMOS_RTC_SECONDS         0x00
-#define CMOS_RTC_SECONDS_ALARM   0x01
-#define CMOS_RTC_MINUTES         0x02
-#define CMOS_RTC_MINUTES_ALARM   0x03
-#define CMOS_RTC_HOURS           0x04
-#define CMOS_RTC_HOURS_ALARM     0x05
-#define CMOS_RTC_DAY_WEEK        0x06
-#define CMOS_RTC_DAY_MONTH       0x07
-#define CMOS_RTC_MONTH           0x08
-#define CMOS_RTC_YEAR            0x09
-#define CMOS_STATUS_A            0x0a
-#define CMOS_STATUS_B            0x0b
-#define CMOS_STATUS_C            0x0c
-#define CMOS_STATUS_D            0x0d
-#define CMOS_RESET_CODE          0x0f
-
-// QEMU cmos config fields.  DO NOT ADD MORE.  (All new content should
-// be passed via the fw_cfg "file" interface.)
-#define CMOS_FLOPPY_DRIVE_TYPE   0x10
-#define CMOS_DISK_DATA           0x12
-#define CMOS_EQUIPMENT_INFO      0x14
-#define CMOS_DISK_DRIVE1_TYPE    0x19
-#define CMOS_DISK_DRIVE2_TYPE    0x1a
-#define CMOS_DISK_DRIVE1_CYL     0x1b
-#define CMOS_DISK_DRIVE2_CYL     0x24
-#define CMOS_MEM_EXTMEM_LOW      0x30
-#define CMOS_MEM_EXTMEM_HIGH     0x31
-#define CMOS_CENTURY             0x32
-#define CMOS_MEM_EXTMEM2_LOW     0x34
-#define CMOS_MEM_EXTMEM2_HIGH    0x35
-#define CMOS_BIOS_BOOTFLAG1      0x38
-#define CMOS_BIOS_DISKTRANSFLAG  0x39
-#define CMOS_BIOS_BOOTFLAG2      0x3d
-#define CMOS_MEM_HIGHMEM_LOW     0x5b
-#define CMOS_MEM_HIGHMEM_MID     0x5c
-#define CMOS_MEM_HIGHMEM_HIGH    0x5d
-#define CMOS_BIOS_SMP_COUNT      0x5f
-
-// CMOS_FLOPPY_DRIVE_TYPE bitdefs
-#define CFD_NO_DRIVE 0
-#define CFD_360KB    1
-#define CFD_12MB     2
-#define CFD_720KB    3
-#define CFD_144MB    4
-#define CFD_288MB    5
-
-#ifndef __ASSEMBLY__
-
-#include "ioport.h" // inb, outb
-
-static inline u8
-inb_cmos(u8 reg)
-{
-    reg |= NMI_DISABLE_BIT;
-    outb(reg, PORT_CMOS_INDEX);
-    return inb(PORT_CMOS_DATA);
-}
-
-static inline void
-outb_cmos(u8 val, u8 reg)
-{
-    reg |= NMI_DISABLE_BIT;
-    outb(reg, PORT_CMOS_INDEX);
-    outb(val, PORT_CMOS_DATA);
-}
-
-#endif // !__ASSEMBLY__
-
-#endif // cmos.h
index 983a2b58dcea46bb0035237c408611f13bd93a42..126649a24e1126f8093c50654df9586b331e42df 100644 (file)
@@ -13,7 +13,7 @@
 #include "disk.h" // MAXDESCSIZE
 #include "config.h" // CONFIG_*
 #include "acpi.h" // find_acpi_features
-#include "pci.h" // pci_probe_devices
+#include "hw/pci.h" // pci_probe_devices
 #include "paravirt.h" // PlatformRunningOn
 
 
index 202170183176eed9c42a7eaffd3c4898749d0395..0093bee50945c431b22946d28157a13b7913669f 100644 (file)
--- a/src/csm.c
+++ b/src/csm.c
@@ -9,14 +9,14 @@
 #include "util.h" // checksum
 #include "bregs.h"
 #include "optionroms.h"
-#include "pci.h"
+#include "hw/pci.h"
 #include "memmap.h"
 #include "biosvar.h"
 #include "post.h"
 #include "acpi.h"
 #include "boot.h"
 #include "smbios.h"
-#include "pic.h"
+#include "hw/pic.h"
 
 struct rsdp_descriptor csm_rsdp VARFSEG __aligned(16);
 
index 77e5bf05394a204941e9d3f972cdc56aea190c7f..997e3f797aa116c04320b5b2d34fc1f60c9c33b3 100644 (file)
--- a/src/csm.h
+++ b/src/csm.h
@@ -2,13 +2,13 @@
 #define __CSM_H
 
 #include "types.h"
-#include "pci.h"
 
 #define UINT8 u8
 #define UINT16 u16
 #define UINT32 u32
 
 // csm.c
+struct pci_device;
 int csm_bootprio_fdc(struct pci_device *pci, int port, int fdid);
 int csm_bootprio_ata(struct pci_device *pci, int chanid, int slave);
 int csm_bootprio_pci(struct pci_device *pci);
index 975d053cc6834ad60499b5d90011126269977716..78252b148818af7badf21868713bb59c3a6335a2 100644 (file)
@@ -9,10 +9,10 @@
 #include "biosvar.h" // SET_BDA
 #include "config.h" // CONFIG_*
 #include "util.h" // debug_enter
-#include "pic.h" // pic_eoi2
+#include "hw/pic.h" // pic_eoi2
 #include "bregs.h" // struct bregs
-#include "pci.h" // pci_bdf_to_bus
-#include "ata.h" // ATA_CB_DC
+#include "hw/pci.h" // pci_bdf_to_bus
+#include "hw/ata.h" // ATA_CB_DC
 
 
 /****************************************************************
diff --git a/src/esp-scsi.c b/src/esp-scsi.c
deleted file mode 100644 (file)
index fe70366..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-// AMD PCscsi boot support.
-//
-// Copyright (C) 2012 Red Hat Inc.
-//
-// Authors:
-//  Paolo Bonzini <pbonzini@redhat.com>
-//
-// based on lsi-scsi.c which is written by:
-//  Gerd Hoffman <kraxel@redhat.com>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // foreachpci
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // GET_GLOBAL
-#include "pci_ids.h" // PCI_DEVICE_ID
-#include "pci_regs.h" // PCI_VENDOR_ID
-#include "boot.h" // bootprio_find_scsi_device
-#include "blockcmd.h" // scsi_drive_setup
-#include "paravirt.h" // runningOnQEMU
-#include "disk.h"
-
-#define ESP_TCLO      0x00
-#define ESP_TCMID     0x04
-#define ESP_FIFO      0x08
-#define ESP_CMD       0x0c
-#define ESP_WBUSID    0x10
-#define ESP_TCHI      0x38
-
-#define ESP_RSTAT     0x10
-#define ESP_RINTR     0x14
-#define ESP_RFLAGS    0x1c
-
-#define ESP_DMA_CMD   0x40
-#define ESP_DMA_STC   0x44
-#define ESP_DMA_SPA   0x48
-#define ESP_DMA_WBC   0x4c
-#define ESP_DMA_WAC   0x50
-#define ESP_DMA_STAT  0x54
-#define ESP_DMA_SMDLA 0x58
-#define ESP_DMA_WMAC  0x58c
-
-#define ESP_CMD_DMA      0x80
-#define ESP_CMD_RESET    0x02
-#define ESP_CMD_TI       0x10
-#define ESP_CMD_ICCS     0x11
-#define ESP_CMD_SELATN   0x42
-
-#define ESP_STAT_DI      0x01
-#define ESP_STAT_CD      0x02
-#define ESP_STAT_MSG     0x04
-#define ESP_STAT_TC      0x10
-
-#define ESP_INTR_DC      0x20
-
-struct esp_lun_s {
-    struct drive_s drive;
-    struct pci_device *pci;
-    u32 iobase;
-    u8 target;
-    u8 lun;
-};
-
-static void
-esp_scsi_dma(u32 iobase, u32 buf, u32 len, int read)
-{
-    outb(len         & 0xff, iobase + ESP_TCLO);
-    outb((len >> 8)  & 0xff, iobase + ESP_TCMID);
-    outb((len >> 16) & 0xff, iobase + ESP_TCHI);
-    outl(buf,                iobase + ESP_DMA_SPA);
-    outl(len,                iobase + ESP_DMA_STC);
-    outb(read ? 0x83 : 0x03, iobase + ESP_DMA_CMD);
-}
-
-static int
-esp_scsi_cmd(struct esp_lun_s *llun, struct disk_op_s *op,
-             u8 *cdbcmd, u16 target, u16 lun, u16 blocksize)
-{
-    u32 iobase = GET_GLOBAL(llun->iobase);
-    int i, state;
-    u8 status;
-
-    outb(target, iobase + ESP_WBUSID);
-
-    /*
-     * We need to pass the LUN at the beginning of the command, and the FIFO
-     * is only 16 bytes, so we cannot support 16-byte CDBs.  The alternative
-     * would be to use DMA for the 17-byte command too, which is quite
-     * overkill.
-     */
-    outb(lun, iobase + ESP_FIFO);
-    cdbcmd[1] &= 0x1f;
-    cdbcmd[1] |= lun << 5;
-    for (i = 0; i < 12; i++)
-        outb(cdbcmd[i], iobase + ESP_FIFO);
-    outb(ESP_CMD_SELATN, iobase + ESP_CMD);
-
-    for (state = 0;;) {
-        u8 stat = inb(iobase + ESP_RSTAT);
-
-        /* Detect disconnected device.  */
-        if (state == 0 && (inb(iobase + ESP_RINTR) & ESP_INTR_DC)) {
-            return DISK_RET_ENOTREADY;
-        }
-
-        /* HBA reads command, clears CD, sets TC -> do DMA if needed.  */
-        if (state == 0 && (stat & ESP_STAT_TC)) {
-            state++;
-            if (op->count && blocksize) {
-                /* Data phase.  */
-                u32 count = (u32)op->count * blocksize;
-                esp_scsi_dma(iobase, (u32)op->buf_fl, count,
-                             cdb_is_read(cdbcmd, blocksize));
-                outb(ESP_CMD_TI | ESP_CMD_DMA, iobase + ESP_CMD);
-                continue;
-            }
-        }
-
-       /* At end of DMA TC is set again -> complete command.  */
-        if (state == 1 && (stat & ESP_STAT_TC)) {
-            state++;
-            outb(ESP_CMD_ICCS, iobase + ESP_CMD);
-            continue;
-        }
-
-       /* Finally read data from the message in phase.  */
-        if (state == 2 && (stat & ESP_STAT_MSG)) {
-            state++;
-            status = inb(iobase + ESP_FIFO);
-            inb(iobase + ESP_FIFO);
-            break;
-        }
-        usleep(5);
-    }
-
-    if (status == 0) {
-        return DISK_RET_SUCCESS;
-    }
-
-    return DISK_RET_EBADTRACK;
-}
-
-int
-esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    if (!CONFIG_ESP_SCSI)
-        return DISK_RET_EBADTRACK;
-
-    struct esp_lun_s *llun =
-        container_of(op->drive_g, struct esp_lun_s, drive);
-
-    return esp_scsi_cmd(llun, op, cdbcmd,
-                        GET_GLOBAL(llun->target), GET_GLOBAL(llun->lun),
-                        blocksize);
-}
-
-static int
-esp_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
-{
-    struct esp_lun_s *llun = malloc_fseg(sizeof(*llun));
-    if (!llun) {
-        warn_noalloc();
-        return -1;
-    }
-    memset(llun, 0, sizeof(*llun));
-    llun->drive.type = DTYPE_ESP_SCSI;
-    llun->drive.cntl_id = pci->bdf;
-    llun->pci = pci;
-    llun->target = target;
-    llun->lun = lun;
-    llun->iobase = iobase;
-
-    char *name = znprintf(16, "esp %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(&llun->drive, name, prio);
-    free(name);
-    if (ret)
-        goto fail;
-    return 0;
-
-fail:
-    free(llun);
-    return -1;
-}
-
-static void
-esp_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target)
-{
-    esp_scsi_add_lun(pci, iobase, target, 0);
-}
-
-static void
-init_esp_scsi(struct pci_device *pci)
-{
-    u16 bdf = pci->bdf;
-    u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
-        & PCI_BASE_ADDRESS_IO_MASK;
-
-    dprintf(1, "found esp at %02x:%02x.%x, io @ %x\n",
-            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
-            pci_bdf_to_fn(bdf), iobase);
-
-    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
-
-    // reset
-    outb(ESP_CMD_RESET, iobase + ESP_CMD);
-
-    int i;
-    for (i = 0; i <= 7; i++)
-        esp_scsi_scan_target(pci, iobase, i);
-
-    return;
-}
-
-void
-esp_scsi_setup(void)
-{
-    ASSERT32FLAT();
-    if (!CONFIG_ESP_SCSI || !runningOnQEMU())
-        return;
-
-    dprintf(3, "init esp\n");
-
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci->vendor != PCI_VENDOR_ID_AMD
-            || pci->device != PCI_DEVICE_ID_AMD_SCSI)
-            continue;
-        init_esp_scsi(pci);
-    }
-}
diff --git a/src/esp-scsi.h b/src/esp-scsi.h
deleted file mode 100644 (file)
index dc555f3..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ESP_SCSI_H
-#define __ESP_SCSI_H
-
-struct disk_op_s;
-int esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
-void esp_scsi_setup(void);
-
-#endif /* __ESP_SCSI_H */
diff --git a/src/floppy.c b/src/floppy.c
deleted file mode 100644 (file)
index 37b7092..0000000
+++ /dev/null
@@ -1,701 +0,0 @@
-// 16bit code to access floppy drives.
-//
-// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2002  MandrakeSoft S.A.
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "types.h" // u8
-#include "disk.h" // DISK_RET_SUCCESS
-#include "config.h" // CONFIG_FLOPPY
-#include "biosvar.h" // SET_BDA
-#include "util.h" // dprintf
-#include "cmos.h" // inb_cmos
-#include "pic.h" // pic_eoi1
-#include "bregs.h" // struct bregs
-#include "boot.h" // boot_add_floppy
-#include "pci.h" // pci_to_bdf
-#include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA
-
-#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors
-#define FLOPPY_DATALEN 0xff   // Not used - because size code is 0x02
-#define FLOPPY_MOTOR_TICKS 37 // ~2 seconds
-#define FLOPPY_FILLBYTE 0xf6
-#define FLOPPY_GAPLEN 0x1B
-#define FLOPPY_FORMAT_GAPLEN 0x6c
-#define FLOPPY_PIO_TIMEOUT 1000
-
-// New diskette parameter table adding 3 parameters from IBM
-// Since no provisions are made for multiple drive types, most
-// values in this table are ignored.  I set parameters for 1.44M
-// floppy here
-struct floppy_ext_dbt_s diskette_param_table2 VARFSEG = {
-    .dbt = {
-        .specify1       = 0xAF, // step rate 12ms, head unload 240ms
-        .specify2       = 0x02, // head load time 4ms, DMA used
-        .shutoff_ticks  = FLOPPY_MOTOR_TICKS, // ~2 seconds
-        .bps_code       = FLOPPY_SIZE_CODE,
-        .sectors        = 18,
-        .interblock_len = FLOPPY_GAPLEN,
-        .data_len       = FLOPPY_DATALEN,
-        .gap_len        = FLOPPY_FORMAT_GAPLEN,
-        .fill_byte      = FLOPPY_FILLBYTE,
-        .settle_time    = 0x0F, // 15ms
-        .startup_time   = 0x08, // 1 second
-    },
-    .max_track      = 79,   // maximum track
-    .data_rate      = 0,    // data transfer rate
-    .drive_type     = 4,    // drive type in cmos
-};
-
-struct floppy_dbt_s diskette_param_table VAR16FIXED(0xefc7);
-
-struct floppyinfo_s {
-    struct chs_s chs;
-    u8 floppy_size;
-    u8 data_rate;
-};
-
-#define FLOPPY_SIZE_525 0x01
-#define FLOPPY_SIZE_350 0x02
-
-#define FLOPPY_RATE_500K 0x00
-#define FLOPPY_RATE_300K 0x01
-#define FLOPPY_RATE_250K 0x02
-#define FLOPPY_RATE_1M   0x03
-
-struct floppyinfo_s FloppyInfo[] VARFSEG = {
-    // Unknown
-    { {0, 0, 0}, 0x00, 0x00},
-    // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors
-    { {2, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K},
-    // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors
-    { {2, 80, 15}, FLOPPY_SIZE_525, FLOPPY_RATE_500K},
-    // 3 - 720KB, 3.5"  - 2 heads, 80 tracks, 9 sectors
-    { {2, 80, 9}, FLOPPY_SIZE_350, FLOPPY_RATE_250K},
-    // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors
-    { {2, 80, 18}, FLOPPY_SIZE_350, FLOPPY_RATE_500K},
-    // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors
-    { {2, 80, 36}, FLOPPY_SIZE_350, FLOPPY_RATE_1M},
-    // 6 - 160k, 5.25"  - 1 heads, 40 tracks, 8 sectors
-    { {1, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K},
-    // 7 - 180k, 5.25"  - 1 heads, 40 tracks, 9 sectors
-    { {1, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K},
-    // 8 - 320k, 5.25"  - 2 heads, 40 tracks, 8 sectors
-    { {2, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K},
-};
-
-struct drive_s *
-init_floppy(int floppyid, int ftype)
-{
-    if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) {
-        dprintf(1, "Bad floppy type %d\n", ftype);
-        return NULL;
-    }
-
-    struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
-    if (!drive_g) {
-        warn_noalloc();
-        return NULL;
-    }
-    memset(drive_g, 0, sizeof(*drive_g));
-    drive_g->cntl_id = floppyid;
-    drive_g->type = DTYPE_FLOPPY;
-    drive_g->blksize = DISK_SECTOR_SIZE;
-    drive_g->floppy_type = ftype;
-    drive_g->sectors = (u64)-1;
-
-    memcpy(&drive_g->lchs, &FloppyInfo[ftype].chs
-           , sizeof(FloppyInfo[ftype].chs));
-    return drive_g;
-}
-
-static void
-addFloppy(int floppyid, int ftype)
-{
-    struct drive_s *drive_g = init_floppy(floppyid, ftype);
-    if (!drive_g)
-        return;
-    char *desc = znprintf(MAXDESCSIZE, "Floppy [drive %c]", 'A' + floppyid);
-    struct pci_device *pci = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */
-    int prio = bootprio_find_fdc_device(pci, PORT_FD_BASE, floppyid);
-    boot_add_floppy(drive_g, desc, prio);
-}
-
-void
-floppy_setup(void)
-{
-    memcpy(&diskette_param_table, &diskette_param_table2
-           , sizeof(diskette_param_table));
-    SET_IVT(0x1E, SEGOFF(SEG_BIOS
-                         , (u32)&diskette_param_table2 - BUILD_BIOS_ADDR));
-
-    if (! CONFIG_FLOPPY)
-        return;
-    dprintf(3, "init floppy drives\n");
-
-    if (CONFIG_QEMU) {
-        u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE);
-        if (type & 0xf0)
-            addFloppy(0, type >> 4);
-        if (type & 0x0f)
-            addFloppy(1, type & 0x0f);
-    } else {
-        u8 type = romfile_loadint("etc/floppy0", 0);
-        if (type)
-            addFloppy(0, type);
-        type = romfile_loadint("etc/floppy1", 0);
-        if (type)
-            addFloppy(1, type);
-    }
-
-    outb(0x02, PORT_DMA1_MASK_REG);
-
-    enable_hwirq(6, FUNC16(entry_0e));
-}
-
-// Find a floppy type that matches a given image size.
-int
-find_floppy_type(u32 size)
-{
-    int i;
-    for (i=1; i<ARRAY_SIZE(FloppyInfo); i++) {
-        struct chs_s *c = &FloppyInfo[i].chs;
-        if (c->cylinders * c->heads * c->spt * DISK_SECTOR_SIZE == size)
-            return i;
-    }
-    return -1;
-}
-
-
-/****************************************************************
- * Low-level floppy IO
- ****************************************************************/
-
-static void
-floppy_disable_controller(void)
-{
-    outb(inb(PORT_FD_DOR) & ~0x04, PORT_FD_DOR);
-}
-
-static int
-floppy_wait_irq(void)
-{
-    u8 frs = GET_BDA(floppy_recalibration_status);
-    SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ);
-    for (;;) {
-        if (!GET_BDA(floppy_motor_counter)) {
-            floppy_disable_controller();
-            return DISK_RET_ETIMEOUT;
-        }
-        frs = GET_BDA(floppy_recalibration_status);
-        if (frs & FRS_IRQ)
-            break;
-        // Could use yield_toirq() here, but that causes issues on
-        // bochs, so use yield() instead.
-        yield();
-    }
-
-    SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ);
-    return DISK_RET_SUCCESS;
-}
-
-struct floppy_pio_s {
-    u8 cmdlen;
-    u8 resplen;
-    u8 waitirq;
-    u8 data[9];
-};
-
-static int
-floppy_pio(struct floppy_pio_s *pio)
-{
-    // Send command to controller.
-    u32 end = timer_calc(FLOPPY_PIO_TIMEOUT);
-    int i = 0;
-    for (;;) {
-        u8 sts = inb(PORT_FD_STATUS);
-        if (!(sts & 0x80)) {
-            if (timer_check(end)) {
-                floppy_disable_controller();
-                return DISK_RET_ETIMEOUT;
-            }
-            continue;
-        }
-        if (sts & 0x40) {
-            floppy_disable_controller();
-            return DISK_RET_ECONTROLLER;
-        }
-        outb(pio->data[i++], PORT_FD_DATA);
-        if (i >= pio->cmdlen)
-            break;
-    }
-
-    // Wait for command to complete.
-    if (pio->waitirq) {
-        int ret = floppy_wait_irq();
-        if (ret)
-            return ret;
-    }
-
-    // Read response from controller.
-    end = timer_calc(FLOPPY_PIO_TIMEOUT);
-    i = 0;
-    for (;;) {
-        u8 sts = inb(PORT_FD_STATUS);
-        if (!(sts & 0x80)) {
-            if (timer_check(end)) {
-                floppy_disable_controller();
-                return DISK_RET_ETIMEOUT;
-            }
-            continue;
-        }
-        if (i >= pio->resplen)
-            break;
-        if (!(sts & 0x40)) {
-            floppy_disable_controller();
-            return DISK_RET_ECONTROLLER;
-        }
-        pio->data[i++] = inb(PORT_FD_DATA);
-    }
-
-    return DISK_RET_SUCCESS;
-}
-
-static int
-floppy_enable_controller(void)
-{
-    outb(inb(PORT_FD_DOR) | 0x04, PORT_FD_DOR);
-    int ret = floppy_wait_irq();
-    if (ret)
-        return ret;
-
-    struct floppy_pio_s pio;
-    pio.cmdlen = 1;
-    pio.resplen = 2;
-    pio.waitirq = 0;
-    pio.data[0] = 0x08;  // 08: Check Interrupt Status
-    return floppy_pio(&pio);
-}
-
-static int
-floppy_select_drive(u8 floppyid)
-{
-    // reset the disk motor timeout value of INT 08
-    SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS);
-
-    // Enable controller if it isn't running.
-    u8 dor = inb(PORT_FD_DOR);
-    if (!(dor & 0x04)) {
-        int ret = floppy_enable_controller();
-        if (ret)
-            return ret;
-    }
-
-    // Turn on motor of selected drive, DMA & int enabled, normal operation
-    dor = (floppyid ? 0x20 : 0x10) | 0x0c | floppyid;
-    outb(dor, PORT_FD_DOR);
-
-    return DISK_RET_SUCCESS;
-}
-
-
-/****************************************************************
- * Floppy media sense
- ****************************************************************/
-
-static inline void
-set_diskette_current_cyl(u8 floppyid, u8 cyl)
-{
-    SET_BDA(floppy_track[floppyid], cyl);
-}
-
-static int
-floppy_drive_recal(u8 floppyid)
-{
-    int ret = floppy_select_drive(floppyid);
-    if (ret)
-        return ret;
-
-    // send Recalibrate command (2 bytes) to controller
-    struct floppy_pio_s pio;
-    pio.cmdlen = 2;
-    pio.resplen = 0;
-    pio.waitirq = 1;
-    pio.data[0] = 0x07;  // 07: Recalibrate
-    pio.data[1] = floppyid; // 0=drive0, 1=drive1
-    ret = floppy_pio(&pio);
-    if (ret)
-        return ret;
-
-    pio.cmdlen = 1;
-    pio.resplen = 2;
-    pio.waitirq = 0;
-    pio.data[0] = 0x08;  // 08: Check Interrupt Status
-    ret = floppy_pio(&pio);
-    if (ret)
-        return ret;
-
-    u8 frs = GET_BDA(floppy_recalibration_status);
-    SET_BDA(floppy_recalibration_status, frs | (1<<floppyid));
-    set_diskette_current_cyl(floppyid, 0);
-    return DISK_RET_SUCCESS;
-}
-
-static int
-floppy_drive_readid(u8 floppyid, u8 data_rate, u8 head)
-{
-    int ret = floppy_select_drive(floppyid);
-    if (ret)
-        return ret;
-
-    // Set data rate.
-    outb(data_rate, PORT_FD_DIR);
-
-    // send Read Sector Id command
-    struct floppy_pio_s pio;
-    pio.cmdlen = 2;
-    pio.resplen = 7;
-    pio.waitirq = 1;
-    pio.data[0] = 0x4a;  // 0a: Read Sector Id
-    pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
-    ret = floppy_pio(&pio);
-    if (ret)
-        return ret;
-    if (pio.data[0] & 0xc0)
-        return -1;
-    return 0;
-}
-
-static int
-floppy_media_sense(struct drive_s *drive_g)
-{
-    u8 ftype = GET_GLOBAL(drive_g->floppy_type), stype = ftype;
-    u8 floppyid = GET_GLOBAL(drive_g->cntl_id);
-
-    u8 data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate);
-    int ret = floppy_drive_readid(floppyid, data_rate, 0);
-    if (ret) {
-        // Attempt media sense.
-        for (stype=1; ; stype++) {
-            if (stype >= ARRAY_SIZE(FloppyInfo))
-                return DISK_RET_EMEDIA;
-            if (stype==ftype
-                || (GET_GLOBAL(FloppyInfo[stype].floppy_size)
-                    != GET_GLOBAL(FloppyInfo[ftype].floppy_size))
-                || (GET_GLOBAL(FloppyInfo[stype].chs.heads)
-                    > GET_GLOBAL(FloppyInfo[ftype].chs.heads))
-                || (GET_GLOBAL(FloppyInfo[stype].chs.cylinders)
-                    > GET_GLOBAL(FloppyInfo[ftype].chs.cylinders))
-                || (GET_GLOBAL(FloppyInfo[stype].chs.spt)
-                    > GET_GLOBAL(FloppyInfo[ftype].chs.spt)))
-                continue;
-            data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate);
-            ret = floppy_drive_readid(floppyid, data_rate, 0);
-            if (!ret)
-                break;
-        }
-    }
-
-    u8 old_data_rate = GET_BDA(floppy_media_state[floppyid]) >> 6;
-    SET_BDA(floppy_last_data_rate, (old_data_rate<<2) | (data_rate<<6));
-    u8 media = (stype == 1 ? 0x04 : (stype == 2 ? 0x05 : 0x07));
-    u8 fms = (data_rate<<6) | FMS_MEDIA_DRIVE_ESTABLISHED | media;
-    if (GET_GLOBAL(FloppyInfo[stype].chs.cylinders)
-        < GET_GLOBAL(FloppyInfo[ftype].chs.cylinders))
-        fms |= FMS_DOUBLE_STEPPING;
-    SET_BDA(floppy_media_state[floppyid], fms);
-
-    return DISK_RET_SUCCESS;
-}
-
-static int
-check_recal_drive(struct drive_s *drive_g)
-{
-    u8 floppyid = GET_GLOBAL(drive_g->cntl_id);
-    if ((GET_BDA(floppy_recalibration_status) & (1<<floppyid))
-        && (GET_BDA(floppy_media_state[floppyid]) & FMS_MEDIA_DRIVE_ESTABLISHED))
-        // Media is known.
-        return DISK_RET_SUCCESS;
-
-    // Recalibrate drive.
-    int ret = floppy_drive_recal(floppyid);
-    if (ret)
-        return ret;
-
-    // Sense media.
-    return floppy_media_sense(drive_g);
-}
-
-
-/****************************************************************
- * Floppy DMA
- ****************************************************************/
-
-// Perform a floppy transfer command (setup DMA and issue PIO).
-static int
-floppy_cmd(struct disk_op_s *op, int blocksize, struct floppy_pio_s *pio)
-{
-    int ret = check_recal_drive(op->drive_g);
-    if (ret)
-        return ret;
-
-    // es:bx = pointer to where to place information from diskette
-    u32 addr = (u32)op->buf_fl;
-    int count = op->count * blocksize;
-
-    // check for 64K boundary overrun
-    u16 end = count - 1;
-    u32 last_addr = addr + end;
-    if ((addr >> 16) != (last_addr >> 16))
-        return DISK_RET_EBOUNDARY;
-
-    u8 mode_register = 0x4a; // single mode, increment, autoinit disable,
-    if (pio->data[0] == 0xe6)
-        // read
-        mode_register = 0x46;
-
-    //DEBUGF("floppy dma c2\n");
-    outb(0x06, PORT_DMA1_MASK_REG);
-    outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
-    outb(addr, PORT_DMA_ADDR_2);
-    outb(addr>>8, PORT_DMA_ADDR_2);
-    outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
-    outb(end, PORT_DMA_CNT_2);
-    outb(end>>8, PORT_DMA_CNT_2);
-
-    // port 0b: DMA-1 Mode Register
-    // transfer type=write, channel 2
-    outb(mode_register, PORT_DMA1_MODE_REG);
-
-    // port 81: DMA-1 Page Register, channel 2
-    outb(addr>>16, PORT_DMA_PAGE_2);
-
-    outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2
-
-    ret = floppy_select_drive(pio->data[1] & 1);
-    if (ret)
-        return ret;
-    pio->resplen = 7;
-    pio->waitirq = 1;
-    ret = floppy_pio(pio);
-    if (ret)
-        return ret;
-
-    // Populate floppy_return_status in BDA
-    int i;
-    for (i=0; i<7; i++)
-        SET_BDA(floppy_return_status[i], pio->data[i]);
-
-    if (pio->data[0] & 0xc0) {
-        if (pio->data[1] & 0x02)
-            return DISK_RET_EWRITEPROTECT;
-        dprintf(1, "floppy error: %02x %02x %02x %02x %02x %02x %02x\n"
-                , pio->data[0], pio->data[1], pio->data[2], pio->data[3]
-                , pio->data[4], pio->data[5], pio->data[6]);
-        return DISK_RET_ECONTROLLER;
-    }
-
-    u8 track = (pio->cmdlen == 9 ? pio->data[3] : 0);
-    set_diskette_current_cyl(pio->data[0] & 1, track);
-
-    return DISK_RET_SUCCESS;
-}
-
-
-/****************************************************************
- * Floppy handlers
- ****************************************************************/
-
-static void
-lba2chs(struct disk_op_s *op, u8 *track, u8 *sector, u8 *head)
-{
-    u32 lba = op->lba;
-
-    u32 tmp = lba + 1;
-    u16 nlspt = GET_GLOBAL(op->drive_g->lchs.spt);
-    *sector = tmp % nlspt;
-
-    tmp /= nlspt;
-    u16 nlh = GET_GLOBAL(op->drive_g->lchs.heads);
-    *head = tmp % nlh;
-
-    tmp /= nlh;
-    *track = tmp;
-}
-
-// diskette controller reset
-static int
-floppy_reset(struct disk_op_s *op)
-{
-    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
-    SET_BDA(floppy_recalibration_status, 0);
-    SET_BDA(floppy_media_state[0], 0);
-    SET_BDA(floppy_media_state[1], 0);
-    SET_BDA(floppy_track[0], 0);
-    SET_BDA(floppy_track[1], 0);
-    SET_BDA(floppy_last_data_rate, 0);
-    floppy_disable_controller();
-    return floppy_select_drive(floppyid);
-}
-
-// Read Diskette Sectors
-static int
-floppy_read(struct disk_op_s *op)
-{
-    u8 track, sector, head;
-    lba2chs(op, &track, &sector, &head);
-
-    // send read-normal-data command (9 bytes) to controller
-    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
-    struct floppy_pio_s pio;
-    pio.cmdlen = 9;
-    pio.data[0] = 0xe6; // e6: read normal data
-    pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
-    pio.data[2] = track;
-    pio.data[3] = head;
-    pio.data[4] = sector;
-    pio.data[5] = FLOPPY_SIZE_CODE;
-    pio.data[6] = sector + op->count - 1; // last sector to read on track
-    pio.data[7] = FLOPPY_GAPLEN;
-    pio.data[8] = FLOPPY_DATALEN;
-
-    int res = floppy_cmd(op, DISK_SECTOR_SIZE, &pio);
-    if (res)
-        goto fail;
-    return DISK_RET_SUCCESS;
-fail:
-    op->count = 0; // no sectors read
-    return res;
-}
-
-// Write Diskette Sectors
-static int
-floppy_write(struct disk_op_s *op)
-{
-    u8 track, sector, head;
-    lba2chs(op, &track, &sector, &head);
-
-    // send write-normal-data command (9 bytes) to controller
-    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
-    struct floppy_pio_s pio;
-    pio.cmdlen = 9;
-    pio.data[0] = 0xc5; // c5: write normal data
-    pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
-    pio.data[2] = track;
-    pio.data[3] = head;
-    pio.data[4] = sector;
-    pio.data[5] = FLOPPY_SIZE_CODE;
-    pio.data[6] = sector + op->count - 1; // last sector to write on track
-    pio.data[7] = FLOPPY_GAPLEN;
-    pio.data[8] = FLOPPY_DATALEN;
-
-    int res = floppy_cmd(op, DISK_SECTOR_SIZE, &pio);
-    if (res)
-        goto fail;
-    return DISK_RET_SUCCESS;
-fail:
-    op->count = 0; // no sectors read
-    return res;
-}
-
-// Verify Diskette Sectors
-static int
-floppy_verify(struct disk_op_s *op)
-{
-    int res = check_recal_drive(op->drive_g);
-    if (res)
-        goto fail;
-
-    u8 track, sector, head;
-    lba2chs(op, &track, &sector, &head);
-
-    // ??? should track be new val from return_status[3] ?
-    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
-    set_diskette_current_cyl(floppyid, track);
-    return DISK_RET_SUCCESS;
-fail:
-    op->count = 0; // no sectors read
-    return res;
-}
-
-// format diskette track
-static int
-floppy_format(struct disk_op_s *op)
-{
-    u8 head = op->lba;
-
-    // send format-track command (6 bytes) to controller
-    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
-    struct floppy_pio_s pio;
-    pio.cmdlen = 6;
-    pio.data[0] = 0x4d; // 4d: format track
-    pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
-    pio.data[2] = FLOPPY_SIZE_CODE;
-    pio.data[3] = op->count; // number of sectors per track
-    pio.data[4] = FLOPPY_FORMAT_GAPLEN;
-    pio.data[5] = FLOPPY_FILLBYTE;
-
-    return floppy_cmd(op, 4, &pio);
-}
-
-int
-process_floppy_op(struct disk_op_s *op)
-{
-    if (!CONFIG_FLOPPY)
-        return 0;
-
-    switch (op->command) {
-    case CMD_RESET:
-        return floppy_reset(op);
-    case CMD_READ:
-        return floppy_read(op);
-    case CMD_WRITE:
-        return floppy_write(op);
-    case CMD_VERIFY:
-        return floppy_verify(op);
-    case CMD_FORMAT:
-        return floppy_format(op);
-    default:
-        op->count = 0;
-        return DISK_RET_EPARAM;
-    }
-}
-
-
-/****************************************************************
- * HW irqs
- ****************************************************************/
-
-// INT 0Eh Diskette Hardware ISR Entry Point
-void VISIBLE16
-handle_0e(void)
-{
-    if (! CONFIG_FLOPPY)
-        return;
-    debug_isr(DEBUG_ISR_0e);
-
-    // diskette interrupt has occurred
-    u8 frs = GET_BDA(floppy_recalibration_status);
-    SET_BDA(floppy_recalibration_status, frs | FRS_IRQ);
-
-    pic_eoi1();
-}
-
-// Called from int08 handler.
-void
-floppy_tick(void)
-{
-    if (! CONFIG_FLOPPY)
-        return;
-
-    // time to turn off drive(s)?
-    u8 fcount = GET_BDA(floppy_motor_counter);
-    if (fcount) {
-        fcount--;
-        SET_BDA(floppy_motor_counter, fcount);
-        if (fcount == 0)
-            // turn motor(s) off
-            outb(inb(PORT_FD_DOR) & 0xcf, PORT_FD_DOR);
-    }
-}
diff --git a/src/hw/ahci.c b/src/hw/ahci.c
new file mode 100644 (file)
index 0000000..0e99d14
--- /dev/null
@@ -0,0 +1,638 @@
+// Low level AHCI disk access
+//
+// Copyright (C) 2010 Gerd Hoffmann <kraxel@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "types.h" // u8
+#include "ioport.h" // inb
+#include "util.h" // dprintf
+#include "biosvar.h" // GET_GLOBAL
+#include "pci.h" // foreachpci
+#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER
+#include "pci_regs.h" // PCI_INTERRUPT_LINE
+#include "boot.h" // add_bcv_hd
+#include "disk.h" // struct ata_s
+#include "ata.h" // ATA_CB_STAT
+#include "ahci.h" // CDB_CMD_READ_10
+#include "blockcmd.h" // CDB_CMD_READ_10
+
+#define AHCI_REQUEST_TIMEOUT 32000 // 32 seconds max for IDE ops
+#define AHCI_RESET_TIMEOUT     500 // 500 miliseconds
+#define AHCI_LINK_TIMEOUT       10 // 10 miliseconds
+
+/****************************************************************
+ * these bits must run in both 16bit and 32bit modes
+ ****************************************************************/
+
+// prepare sata command fis
+static void sata_prep_simple(struct sata_cmd_fis *fis, u8 command)
+{
+    memset_fl(fis, 0, sizeof(*fis));
+    SET_LOWFLAT(fis->command, command);
+}
+
+static void sata_prep_readwrite(struct sata_cmd_fis *fis,
+                                struct disk_op_s *op, int iswrite)
+{
+    u64 lba = op->lba;
+    u8 command;
+
+    memset_fl(fis, 0, sizeof(*fis));
+
+    if (op->count >= (1<<8) || lba + op->count >= (1<<28)) {
+        SET_LOWFLAT(fis->sector_count2, op->count >> 8);
+        SET_LOWFLAT(fis->lba_low2,      lba >> 24);
+        SET_LOWFLAT(fis->lba_mid2,      lba >> 32);
+        SET_LOWFLAT(fis->lba_high2,     lba >> 40);
+        lba &= 0xffffff;
+        command = (iswrite ? ATA_CMD_WRITE_DMA_EXT
+                   : ATA_CMD_READ_DMA_EXT);
+    } else {
+        command = (iswrite ? ATA_CMD_WRITE_DMA
+                   : ATA_CMD_READ_DMA);
+    }
+    SET_LOWFLAT(fis->feature,      1); /* dma */
+    SET_LOWFLAT(fis->command,      command);
+    SET_LOWFLAT(fis->sector_count, op->count);
+    SET_LOWFLAT(fis->lba_low,      lba);
+    SET_LOWFLAT(fis->lba_mid,      lba >> 8);
+    SET_LOWFLAT(fis->lba_high,     lba >> 16);
+    SET_LOWFLAT(fis->device,       ((lba >> 24) & 0xf) | ATA_CB_DH_LBA);
+}
+
+static void sata_prep_atapi(struct sata_cmd_fis *fis, u16 blocksize)
+{
+    memset_fl(fis, 0, sizeof(*fis));
+    SET_LOWFLAT(fis->command,  ATA_CMD_PACKET);
+    SET_LOWFLAT(fis->feature,  1); /* dma */
+    SET_LOWFLAT(fis->lba_mid,  blocksize);
+    SET_LOWFLAT(fis->lba_high, blocksize >> 8);
+}
+
+// ahci register access helpers
+static u32 ahci_ctrl_readl(struct ahci_ctrl_s *ctrl, u32 reg)
+{
+    u32 addr = GET_GLOBALFLAT(ctrl->iobase) + reg;
+    return pci_readl(addr);
+}
+
+static void ahci_ctrl_writel(struct ahci_ctrl_s *ctrl, u32 reg, u32 val)
+{
+    u32 addr = GET_GLOBALFLAT(ctrl->iobase) + reg;
+    pci_writel(addr, val);
+}
+
+static u32 ahci_port_to_ctrl(u32 pnr, u32 port_reg)
+{
+    u32 ctrl_reg = 0x100;
+    ctrl_reg += pnr * 0x80;
+    ctrl_reg += port_reg;
+    return ctrl_reg;
+}
+
+static u32 ahci_port_readl(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg)
+{
+    u32 ctrl_reg = ahci_port_to_ctrl(pnr, reg);
+    return ahci_ctrl_readl(ctrl, ctrl_reg);
+}
+
+static void ahci_port_writel(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg, u32 val)
+{
+    u32 ctrl_reg = ahci_port_to_ctrl(pnr, reg);
+    ahci_ctrl_writel(ctrl, ctrl_reg, val);
+}
+
+// submit ahci command + wait for result
+static int ahci_command(struct ahci_port_s *port, int iswrite, int isatapi,
+                        void *buffer, u32 bsize)
+{
+    u32 val, status, success, flags, intbits, error;
+    struct ahci_ctrl_s *ctrl = GET_GLOBAL(port->ctrl);
+    struct ahci_cmd_s  *cmd  = GET_GLOBAL(port->cmd);
+    struct ahci_fis_s  *fis  = GET_GLOBAL(port->fis);
+    struct ahci_list_s *list = GET_GLOBAL(port->list);
+    u32 pnr                  = GET_GLOBAL(port->pnr);
+
+    SET_LOWFLAT(cmd->fis.reg,       0x27);
+    SET_LOWFLAT(cmd->fis.pmp_type,  (1 << 7)); /* cmd fis */
+    SET_LOWFLAT(cmd->prdt[0].base,  ((u32)buffer));
+    SET_LOWFLAT(cmd->prdt[0].baseu, 0);
+    SET_LOWFLAT(cmd->prdt[0].flags, bsize-1);
+
+    flags = ((1 << 16) | /* one prd entry */
+             (iswrite ? (1 << 6) : 0) |
+             (isatapi ? (1 << 5) : 0) |
+             (5 << 0)); /* fis length (dwords) */
+    SET_LOWFLAT(list[0].flags,  flags);
+    SET_LOWFLAT(list[0].bytes,  0);
+    SET_LOWFLAT(list[0].base,   ((u32)(cmd)));
+    SET_LOWFLAT(list[0].baseu,  0);
+
+    dprintf(8, "AHCI/%d: send cmd ...\n", pnr);
+    intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT);
+    if (intbits)
+        ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits);
+    ahci_port_writel(ctrl, pnr, PORT_SCR_ACT, 1);
+    ahci_port_writel(ctrl, pnr, PORT_CMD_ISSUE, 1);
+
+    u32 end = timer_calc(AHCI_REQUEST_TIMEOUT);
+    do {
+        for (;;) {
+            intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT);
+            if (intbits) {
+                ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits);
+                if (intbits & 0x02) {
+                    status = GET_LOWFLAT(fis->psfis[2]);
+                    error  = GET_LOWFLAT(fis->psfis[3]);
+                    break;
+                }
+                if (intbits & 0x01) {
+                    status = GET_LOWFLAT(fis->rfis[2]);
+                    error  = GET_LOWFLAT(fis->rfis[3]);
+                    break;
+                }
+            }
+            if (timer_check(end)) {
+                warn_timeout();
+                return -1;
+            }
+            yield();
+        }
+        dprintf(8, "AHCI/%d: ... intbits 0x%x, status 0x%x ...\n",
+                pnr, intbits, status);
+    } while (status & ATA_CB_STAT_BSY);
+
+    success = (0x00 == (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF |
+                                  ATA_CB_STAT_ERR)) &&
+               ATA_CB_STAT_RDY == (status & (ATA_CB_STAT_RDY)));
+    if (success) {
+        dprintf(8, "AHCI/%d: ... finished, status 0x%x, OK\n", pnr,
+                status);
+    } else {
+        dprintf(2, "AHCI/%d: ... finished, status 0x%x, ERROR 0x%x\n", pnr,
+                status, error);
+
+        // non-queued error recovery (AHCI 1.3 section 6.2.2.1)
+        // Clears PxCMD.ST to 0 to reset the PxCI register
+        val = ahci_port_readl(ctrl, pnr, PORT_CMD);
+        ahci_port_writel(ctrl, pnr, PORT_CMD, val & ~PORT_CMD_START);
+
+        // waits for PxCMD.CR to clear to 0
+        while (1) {
+            val = ahci_port_readl(ctrl, pnr, PORT_CMD);
+            if ((val & PORT_CMD_LIST_ON) == 0)
+                break;
+            yield();
+        }
+
+        // Clears any error bits in PxSERR to enable capturing new errors
+        val = ahci_port_readl(ctrl, pnr, PORT_SCR_ERR);
+        ahci_port_writel(ctrl, pnr, PORT_SCR_ERR, val);
+
+        // Clears status bits in PxIS as appropriate
+        val = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT);
+        ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, val);
+
+        // If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to 1, issue
+        // a COMRESET to the device to put it in an idle state
+        val = ahci_port_readl(ctrl, pnr, PORT_TFDATA);
+        if (val & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ)) {
+            dprintf(2, "AHCI/%d: issue comreset\n", pnr);
+            val = ahci_port_readl(ctrl, pnr, PORT_SCR_CTL);
+            // set Device Detection Initialization (DET) to 1 for 1 ms for comreset
+            ahci_port_writel(ctrl, pnr, PORT_SCR_CTL, val | 1);
+            mdelay (1);
+            ahci_port_writel(ctrl, pnr, PORT_SCR_CTL, val);
+        }
+
+        // Sets PxCMD.ST to 1 to enable issuing new commands
+        val = ahci_port_readl(ctrl, pnr, PORT_CMD);
+        ahci_port_writel(ctrl, pnr, PORT_CMD, val | PORT_CMD_START);
+    }
+    return success ? 0 : -1;
+}
+
+#define CDROM_CDB_SIZE 12
+
+int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    if (! CONFIG_AHCI)
+        return 0;
+
+    struct ahci_port_s *port = container_of(
+        op->drive_g, struct ahci_port_s, drive);
+    struct ahci_cmd_s *cmd = GET_GLOBAL(port->cmd);
+    u8 *atapi = cdbcmd;
+    int i, rc;
+
+    sata_prep_atapi(&cmd->fis, blocksize);
+    for (i = 0; i < CDROM_CDB_SIZE; i++) {
+        SET_LOWFLAT(cmd->atapi[i], atapi[i]);
+    }
+    rc = ahci_command(port, 0, 1, op->buf_fl,
+                      op->count * blocksize);
+    if (rc < 0)
+        return DISK_RET_EBADTRACK;
+    return DISK_RET_SUCCESS;
+}
+
+// read/write count blocks from a harddrive, op->buf_fl must be word aligned
+static int
+ahci_disk_readwrite_aligned(struct disk_op_s *op, int iswrite)
+{
+    struct ahci_port_s *port = container_of(
+        op->drive_g, struct ahci_port_s, drive);
+    struct ahci_cmd_s *cmd = GET_GLOBAL(port->cmd);
+    int rc;
+
+    sata_prep_readwrite(&cmd->fis, op, iswrite);
+    rc = ahci_command(port, iswrite, 0, op->buf_fl,
+                      op->count * DISK_SECTOR_SIZE);
+    dprintf(8, "ahci disk %s, lba %6x, count %3x, buf %p, rc %d\n",
+            iswrite ? "write" : "read", (u32)op->lba, op->count, op->buf_fl, rc);
+    if (rc < 0)
+        return DISK_RET_EBADTRACK;
+    return DISK_RET_SUCCESS;
+}
+
+// read/write count blocks from a harddrive.
+static int
+ahci_disk_readwrite(struct disk_op_s *op, int iswrite)
+{
+    // if caller's buffer is word aligned, use it directly
+    if (((u32) op->buf_fl & 1) == 0)
+        return ahci_disk_readwrite_aligned(op, iswrite);
+
+    // Use a word aligned buffer for AHCI I/O
+    int rc;
+    struct disk_op_s localop = *op;
+    u8 *alignedbuf_fl = GET_GLOBAL(bounce_buf_fl);
+    u8 *position = op->buf_fl;
+
+    localop.buf_fl = alignedbuf_fl;
+    localop.count = 1;
+
+    if (iswrite) {
+        u16 block;
+        for (block = 0; block < op->count; block++) {
+            memcpy_fl (alignedbuf_fl, position, DISK_SECTOR_SIZE);
+            rc = ahci_disk_readwrite_aligned (&localop, 1);
+            if (rc)
+                return rc;
+            position += DISK_SECTOR_SIZE;
+            localop.lba++;
+        }
+    } else { // read
+        u16 block;
+        for (block = 0; block < op->count; block++) {
+            rc = ahci_disk_readwrite_aligned (&localop, 0);
+            if (rc)
+                return rc;
+            memcpy_fl (position, alignedbuf_fl, DISK_SECTOR_SIZE);
+            position += DISK_SECTOR_SIZE;
+            localop.lba++;
+        }
+    }
+    return DISK_RET_SUCCESS;
+}
+
+// command demuxer
+int process_ahci_op(struct disk_op_s *op)
+{
+    if (!CONFIG_AHCI)
+        return 0;
+    switch (op->command) {
+    case CMD_READ:
+        return ahci_disk_readwrite(op, 0);
+    case CMD_WRITE:
+        return ahci_disk_readwrite(op, 1);
+    case CMD_FORMAT:
+    case CMD_RESET:
+    case CMD_ISREADY:
+    case CMD_VERIFY:
+    case CMD_SEEK:
+        return DISK_RET_SUCCESS;
+    default:
+        dprintf(1, "AHCI: unknown disk command %d\n", op->command);
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
+
+/****************************************************************
+ * everything below is pure 32bit code
+ ****************************************************************/
+
+static void
+ahci_port_reset(struct ahci_ctrl_s *ctrl, u32 pnr)
+{
+    u32 val;
+
+    /* disable FIS + CMD */
+    u32 end = timer_calc(AHCI_RESET_TIMEOUT);
+    for (;;) {
+        val = ahci_port_readl(ctrl, pnr, PORT_CMD);
+        if (!(val & (PORT_CMD_FIS_RX | PORT_CMD_START |
+                     PORT_CMD_FIS_ON | PORT_CMD_LIST_ON)))
+            break;
+        val &= ~(PORT_CMD_FIS_RX | PORT_CMD_START);
+        ahci_port_writel(ctrl, pnr, PORT_CMD, val);
+        if (timer_check(end)) {
+            warn_timeout();
+            break;
+        }
+        yield();
+    }
+
+    /* disable + clear IRQs */
+    ahci_port_writel(ctrl, pnr, PORT_IRQ_MASK, 0);
+    val = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT);
+    if (val)
+        ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, val);
+}
+
+static struct ahci_port_s*
+ahci_port_alloc(struct ahci_ctrl_s *ctrl, u32 pnr)
+{
+    struct ahci_port_s *port = malloc_tmp(sizeof(*port));
+
+    if (!port) {
+        warn_noalloc();
+        return NULL;
+    }
+    port->pnr = pnr;
+    port->ctrl = ctrl;
+    port->list = memalign_tmp(1024, 1024);
+    port->fis = memalign_tmp(256, 256);
+    port->cmd = memalign_tmp(256, 256);
+    if (port->list == NULL || port->fis == NULL || port->cmd == NULL) {
+        warn_noalloc();
+        return NULL;
+    }
+    memset(port->list, 0, 1024);
+    memset(port->fis, 0, 256);
+    memset(port->cmd, 0, 256);
+
+    ahci_port_writel(ctrl, pnr, PORT_LST_ADDR, (u32)port->list);
+    ahci_port_writel(ctrl, pnr, PORT_FIS_ADDR, (u32)port->fis);
+    return port;
+}
+
+static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port)
+{
+    struct ahci_port_s *tmp;
+    u32 cmd;
+
+    tmp = malloc_fseg(sizeof(*port));
+    *tmp = *port;
+    free(port);
+    port = tmp;
+
+    ahci_port_reset(port->ctrl, port->pnr);
+
+    free(port->list);
+    free(port->fis);
+    free(port->cmd);
+    port->list = memalign_low(1024, 1024);
+    port->fis = memalign_low(256, 256);
+    port->cmd = memalign_low(256, 256);
+
+    ahci_port_writel(port->ctrl, port->pnr, PORT_LST_ADDR, (u32)port->list);
+    ahci_port_writel(port->ctrl, port->pnr, PORT_FIS_ADDR, (u32)port->fis);
+
+    cmd = ahci_port_readl(port->ctrl, port->pnr, PORT_CMD);
+    cmd |= (PORT_CMD_FIS_RX|PORT_CMD_START);
+    ahci_port_writel(port->ctrl, port->pnr, PORT_CMD, cmd);
+
+    return port;
+}
+
+static void ahci_port_release(struct ahci_port_s *port)
+{
+    ahci_port_reset(port->ctrl, port->pnr);
+    free(port->list);
+    free(port->fis);
+    free(port->cmd);
+    free(port);
+}
+
+#define MAXMODEL 40
+
+/* See ahci spec chapter 10.1 "Software Initialization of HBA" */
+static int ahci_port_setup(struct ahci_port_s *port)
+{
+    struct ahci_ctrl_s *ctrl = port->ctrl;
+    u32 pnr = port->pnr;
+    char model[MAXMODEL+1];
+    u16 buffer[256];
+    u32 cmd, stat, err, tf;
+    int rc;
+
+    /* enable FIS recv */
+    cmd = ahci_port_readl(ctrl, pnr, PORT_CMD);
+    cmd |= PORT_CMD_FIS_RX;
+    ahci_port_writel(ctrl, pnr, PORT_CMD, cmd);
+
+    /* spin up */
+    cmd |= PORT_CMD_SPIN_UP;
+    ahci_port_writel(ctrl, pnr, PORT_CMD, cmd);
+    u32 end = timer_calc(AHCI_LINK_TIMEOUT);
+    for (;;) {
+        stat = ahci_port_readl(ctrl, pnr, PORT_SCR_STAT);
+        if ((stat & 0x07) == 0x03) {
+            dprintf(2, "AHCI/%d: link up\n", port->pnr);
+            break;
+        }
+        if (timer_check(end)) {
+            dprintf(2, "AHCI/%d: link down\n", port->pnr);
+            return -1;
+        }
+        yield();
+    }
+
+    /* clear error status */
+    err = ahci_port_readl(ctrl, pnr, PORT_SCR_ERR);
+    if (err)
+        ahci_port_writel(ctrl, pnr, PORT_SCR_ERR, err);
+
+    /* wait for device becoming ready */
+    end = timer_calc(AHCI_REQUEST_TIMEOUT);
+    for (;;) {
+        tf = ahci_port_readl(ctrl, pnr, PORT_TFDATA);
+        if (!(tf & (ATA_CB_STAT_BSY |
+                    ATA_CB_STAT_DRQ)))
+            break;
+        if (timer_check(end)) {
+            warn_timeout();
+            dprintf(1, "AHCI/%d: device not ready (tf 0x%x)\n", port->pnr, tf);
+            return -1;
+        }
+        yield();
+    }
+
+    /* start device */
+    cmd |= PORT_CMD_START;
+    ahci_port_writel(ctrl, pnr, PORT_CMD, cmd);
+
+    sata_prep_simple(&port->cmd->fis, ATA_CMD_IDENTIFY_PACKET_DEVICE);
+    rc = ahci_command(port, 0, 0, buffer, sizeof(buffer));
+    if (rc == 0) {
+        port->atapi = 1;
+    } else {
+        port->atapi = 0;
+        sata_prep_simple(&port->cmd->fis, ATA_CMD_IDENTIFY_DEVICE);
+        rc = ahci_command(port, 0, 0, buffer, sizeof(buffer));
+        if (rc < 0)
+            return -1;
+    }
+
+    port->drive.cntl_id = pnr;
+    port->drive.removable = (buffer[0] & 0x80) ? 1 : 0;
+
+    if (!port->atapi) {
+        // found disk (ata)
+        port->drive.type = DTYPE_AHCI;
+        port->drive.blksize = DISK_SECTOR_SIZE;
+        port->drive.pchs.cylinders = buffer[1];
+        port->drive.pchs.heads = buffer[3];
+        port->drive.pchs.spt = buffer[6];
+
+        u64 sectors;
+        if (buffer[83] & (1 << 10)) // word 83 - lba48 support
+            sectors = *(u64*)&buffer[100]; // word 100-103
+        else
+            sectors = *(u32*)&buffer[60]; // word 60 and word 61
+        port->drive.sectors = sectors;
+        u64 adjsize = sectors >> 11;
+        char adjprefix = 'M';
+        if (adjsize >= (1 << 16)) {
+            adjsize >>= 10;
+            adjprefix = 'G';
+        }
+        port->desc = znprintf(MAXDESCSIZE
+                              , "AHCI/%d: %s ATA-%d Hard-Disk (%u %ciBytes)"
+                              , port->pnr
+                              , ata_extract_model(model, MAXMODEL, buffer)
+                              , ata_extract_version(buffer)
+                              , (u32)adjsize, adjprefix);
+        port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0);
+    } else {
+        // found cdrom (atapi)
+        port->drive.type = DTYPE_AHCI_ATAPI;
+        port->drive.blksize = CDROM_SECTOR_SIZE;
+        port->drive.sectors = (u64)-1;
+        u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
+        if (!iscd) {
+            dprintf(1, "AHCI/%d: atapi device isn't a cdrom\n", port->pnr);
+            return -1;
+        }
+        port->desc = znprintf(MAXDESCSIZE
+                              , "DVD/CD [AHCI/%d: %s ATAPI-%d DVD/CD]"
+                              , port->pnr
+                              , ata_extract_model(model, MAXMODEL, buffer)
+                              , ata_extract_version(buffer));
+        port->prio = bootprio_find_ata_device(ctrl->pci_tmp, pnr, 0);
+    }
+    return 0;
+}
+
+// Detect any drives attached to a given controller.
+static void
+ahci_port_detect(void *data)
+{
+    struct ahci_port_s *port = data;
+    int rc;
+
+    dprintf(2, "AHCI/%d: probing\n", port->pnr);
+    ahci_port_reset(port->ctrl, port->pnr);
+    rc = ahci_port_setup(port);
+    if (rc < 0)
+        ahci_port_release(port);
+    else {
+        port = ahci_port_realloc(port);
+        dprintf(1, "AHCI/%d: registering: \"%s\"\n", port->pnr, port->desc);
+        if (!port->atapi) {
+            // Register with bcv system.
+            boot_add_hd(&port->drive, port->desc, port->prio);
+        } else {
+            // fill cdidmap
+            boot_add_cd(&port->drive, port->desc, port->prio);
+        }
+    }
+}
+
+// Initialize an ata controller and detect its drives.
+static void
+ahci_controller_setup(struct pci_device *pci)
+{
+    struct ahci_ctrl_s *ctrl = malloc_fseg(sizeof(*ctrl));
+    struct ahci_port_s *port;
+    u16 bdf = pci->bdf;
+    u32 val, pnr, max;
+
+    if (!ctrl) {
+        warn_noalloc();
+        return;
+    }
+
+    if (create_bounce_buf() < 0) {
+        warn_noalloc();
+        free(ctrl);
+        return;
+    }
+
+    ctrl->pci_tmp = pci;
+    ctrl->pci_bdf = bdf;
+    ctrl->iobase = pci_config_readl(bdf, PCI_BASE_ADDRESS_5);
+    ctrl->irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
+    dprintf(1, "AHCI controller at %02x.%x, iobase %x, irq %d\n",
+            bdf >> 3, bdf & 7, ctrl->iobase, ctrl->irq);
+
+    pci_config_maskw(bdf, PCI_COMMAND, 0,
+                     PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+    val = ahci_ctrl_readl(ctrl, HOST_CTL);
+    ahci_ctrl_writel(ctrl, HOST_CTL, val | HOST_CTL_AHCI_EN);
+
+    ctrl->caps = ahci_ctrl_readl(ctrl, HOST_CAP);
+    ctrl->ports = ahci_ctrl_readl(ctrl, HOST_PORTS_IMPL);
+    dprintf(2, "AHCI: cap 0x%x, ports_impl 0x%x\n",
+            ctrl->caps, ctrl->ports);
+
+    max = ctrl->caps & 0x1f;
+    for (pnr = 0; pnr <= max; pnr++) {
+        if (!(ctrl->ports & (1 << pnr)))
+            continue;
+        port = ahci_port_alloc(ctrl, pnr);
+        if (port == NULL)
+            continue;
+        run_thread(ahci_port_detect, port);
+    }
+}
+
+// Locate and init ahci controllers.
+static void
+ahci_scan(void)
+{
+    // Scan PCI bus for ATA adapters
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci->class != PCI_CLASS_STORAGE_SATA)
+            continue;
+        if (pci->prog_if != 1 /* AHCI rev 1 */)
+            continue;
+        ahci_controller_setup(pci);
+    }
+}
+
+void
+ahci_setup(void)
+{
+    ASSERT32FLAT();
+    if (!CONFIG_AHCI)
+        return;
+
+    dprintf(3, "init ahci\n");
+    ahci_scan();
+}
diff --git a/src/hw/ahci.h b/src/hw/ahci.h
new file mode 100644 (file)
index 0000000..c3d3a70
--- /dev/null
@@ -0,0 +1,199 @@
+#ifndef __AHCI_H
+#define __AHCI_H
+
+struct sata_cmd_fis {
+    u8 reg;
+    u8 pmp_type;
+    u8 command;
+    u8 feature;
+
+    u8 lba_low;
+    u8 lba_mid;
+    u8 lba_high;
+    u8 device;
+
+    u8 lba_low2;
+    u8 lba_mid2;
+    u8 lba_high2;
+    u8 feature2;
+
+    u8 sector_count;
+    u8 sector_count2;
+    u8 res_1;
+    u8 control;
+
+    u8 res_2[64 - 16];
+};
+
+struct ahci_ctrl_s {
+    struct pci_device *pci_tmp;
+    u16 pci_bdf;
+    u8  irq;
+    u32 iobase;
+    u32 caps;
+    u32 ports;
+};
+
+struct ahci_cmd_s {
+    struct sata_cmd_fis fis;
+    u8 atapi[0x20];
+    u8 res[0x20];
+    struct {
+        u32 base;
+        u32 baseu;
+        u32 res;
+        u32 flags;
+    } prdt[];
+};
+
+/* command list */
+struct ahci_list_s {
+    u32 flags;
+    u32 bytes;
+    u32 base;
+    u32 baseu;
+    u32 res[4];
+};
+
+struct ahci_fis_s {
+    u8 dsfis[0x1c];  /* dma setup */
+    u8 res_1[0x04];
+    u8 psfis[0x14];  /* pio setup */
+    u8 res_2[0x0c];
+    u8 rfis[0x14];   /* d2h register */
+    u8 res_3[0x04];
+    u8 sdbfis[0x08]; /* set device bits */
+    u8 ufis[0x40];   /* unknown */
+    u8 res_4[0x60];
+};
+
+struct ahci_port_s {
+    struct drive_s     drive;
+    struct ahci_ctrl_s *ctrl;
+    struct ahci_list_s *list;
+    struct ahci_fis_s  *fis;
+    struct ahci_cmd_s  *cmd;
+    u32                pnr;
+    u32                atapi;
+    char               *desc;
+    int                prio;
+};
+
+void ahci_setup(void);
+int process_ahci_op(struct disk_op_s *op);
+int ahci_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+
+#define AHCI_IRQ_ON_SG            (1 << 31)
+#define AHCI_CMD_ATAPI            (1 << 5)
+#define AHCI_CMD_WRITE            (1 << 6)
+#define AHCI_CMD_PREFETCH         (1 << 7)
+#define AHCI_CMD_RESET            (1 << 8)
+#define AHCI_CMD_CLR_BUSY         (1 << 10)
+
+#define RX_FIS_D2H_REG            0x40 /* offset of D2H Register FIS data */
+#define RX_FIS_SDB                0x58 /* offset of SDB FIS data */
+#define RX_FIS_UNK                0x60 /* offset of Unknown FIS data */
+
+/* global controller registers */
+#define HOST_CAP                  0x00 /* host capabilities */
+#define HOST_CTL                  0x04 /* global host control */
+#define HOST_IRQ_STAT             0x08 /* interrupt status */
+#define HOST_PORTS_IMPL           0x0c /* bitmap of implemented ports */
+#define HOST_VERSION              0x10 /* AHCI spec. version compliancy */
+
+/* HOST_CTL bits */
+#define HOST_CTL_RESET            (1 << 0)  /* reset controller; self-clear */
+#define HOST_CTL_IRQ_EN           (1 << 1)  /* global IRQ enable */
+#define HOST_CTL_AHCI_EN          (1 << 31) /* AHCI enabled */
+
+/* HOST_CAP bits */
+#define HOST_CAP_SSC              (1 << 14) /* Slumber capable */
+#define HOST_CAP_AHCI             (1 << 18) /* AHCI only */
+#define HOST_CAP_CLO              (1 << 24) /* Command List Override support */
+#define HOST_CAP_SSS              (1 << 27) /* Staggered Spin-up */
+#define HOST_CAP_NCQ              (1 << 30) /* Native Command Queueing */
+#define HOST_CAP_64               (1 << 31) /* PCI DAC (64-bit DMA) support */
+
+/* registers for each SATA port */
+#define PORT_LST_ADDR             0x00 /* command list DMA addr */
+#define PORT_LST_ADDR_HI          0x04 /* command list DMA addr hi */
+#define PORT_FIS_ADDR             0x08 /* FIS rx buf addr */
+#define PORT_FIS_ADDR_HI          0x0c /* FIS rx buf addr hi */
+#define PORT_IRQ_STAT             0x10 /* interrupt status */
+#define PORT_IRQ_MASK             0x14 /* interrupt enable/disable mask */
+#define PORT_CMD                  0x18 /* port command */
+#define PORT_TFDATA               0x20 /* taskfile data */
+#define PORT_SIG                  0x24 /* device TF signature */
+#define PORT_SCR_STAT             0x28 /* SATA phy register: SStatus */
+#define PORT_SCR_CTL              0x2c /* SATA phy register: SControl */
+#define PORT_SCR_ERR              0x30 /* SATA phy register: SError */
+#define PORT_SCR_ACT              0x34 /* SATA phy register: SActive */
+#define PORT_CMD_ISSUE            0x38 /* command issue */
+#define PORT_RESERVED             0x3c /* reserved */
+
+/* PORT_IRQ_{STAT,MASK} bits */
+#define PORT_IRQ_COLD_PRES        (1 << 31) /* cold presence detect */
+#define PORT_IRQ_TF_ERR           (1 << 30) /* task file error */
+#define PORT_IRQ_HBUS_ERR         (1 << 29) /* host bus fatal error */
+#define PORT_IRQ_HBUS_DATA_ERR    (1 << 28) /* host bus data error */
+#define PORT_IRQ_IF_ERR           (1 << 27) /* interface fatal error */
+#define PORT_IRQ_IF_NONFATAL      (1 << 26) /* interface non-fatal error */
+#define PORT_IRQ_OVERFLOW         (1 << 24) /* xfer exhausted available S/G */
+#define PORT_IRQ_BAD_PMP          (1 << 23) /* incorrect port multiplier */
+
+#define PORT_IRQ_PHYRDY           (1 << 22) /* PhyRdy changed */
+#define PORT_IRQ_DEV_ILCK         (1 << 7) /* device interlock */
+#define PORT_IRQ_CONNECT          (1 << 6) /* port connect change status */
+#define PORT_IRQ_SG_DONE          (1 << 5) /* descriptor processed */
+#define PORT_IRQ_UNK_FIS          (1 << 4) /* unknown FIS rx'd */
+#define PORT_IRQ_SDB_FIS          (1 << 3) /* Set Device Bits FIS rx'd */
+#define PORT_IRQ_DMAS_FIS         (1 << 2) /* DMA Setup FIS rx'd */
+#define PORT_IRQ_PIOS_FIS         (1 << 1) /* PIO Setup FIS rx'd */
+#define PORT_IRQ_D2H_REG_FIS      (1 << 0) /* D2H Register FIS rx'd */
+
+#define PORT_IRQ_FREEZE           (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR |   \
+                                   PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY |    \
+                                   PORT_IRQ_UNK_FIS)
+#define PORT_IRQ_ERROR            (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR |     \
+                                   PORT_IRQ_HBUS_DATA_ERR)
+#define DEF_PORT_IRQ              (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |     \
+                                   PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |  \
+                                   PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
+
+/* PORT_CMD bits */
+#define PORT_CMD_ATAPI            (1 << 24) /* Device is ATAPI */
+#define PORT_CMD_LIST_ON          (1 << 15) /* cmd list DMA engine running */
+#define PORT_CMD_FIS_ON           (1 << 14) /* FIS DMA engine running */
+#define PORT_CMD_FIS_RX           (1 << 4) /* Enable FIS receive DMA engine */
+#define PORT_CMD_CLO              (1 << 3) /* Command list override */
+#define PORT_CMD_POWER_ON         (1 << 2) /* Power up device */
+#define PORT_CMD_SPIN_UP          (1 << 1) /* Spin up device */
+#define PORT_CMD_START            (1 << 0) /* Enable port DMA engine */
+
+#define PORT_CMD_ICC_MASK         (0xf << 28) /* i/f ICC state mask */
+#define PORT_CMD_ICC_ACTIVE       (0x1 << 28) /* Put i/f in active state */
+#define PORT_CMD_ICC_PARTIAL      (0x2 << 28) /* Put i/f in partial state */
+#define PORT_CMD_ICC_SLUMBER      (0x6 << 28) /* Put i/f in slumber state */
+
+#define PORT_IRQ_STAT_DHRS        (1 << 0) /* Device to Host Register FIS */
+#define PORT_IRQ_STAT_PSS         (1 << 1) /* PIO Setup FIS */
+#define PORT_IRQ_STAT_DSS         (1 << 2) /* DMA Setup FIS */
+#define PORT_IRQ_STAT_SDBS        (1 << 3) /* Set Device Bits */
+#define PORT_IRQ_STAT_UFS         (1 << 4) /* Unknown FIS */
+#define PORT_IRQ_STAT_DPS         (1 << 5) /* Descriptor Processed */
+#define PORT_IRQ_STAT_PCS         (1 << 6) /* Port Connect Change Status */
+#define PORT_IRQ_STAT_DMPS        (1 << 7) /* Device Mechanical Presence
+                                              Status */
+#define PORT_IRQ_STAT_PRCS        (1 << 22) /* File Ready Status */
+#define PORT_IRQ_STAT_IPMS        (1 << 23) /* Incorrect Port Multiplier
+                                               Status */
+#define PORT_IRQ_STAT_OFS         (1 << 24) /* Overflow Status */
+#define PORT_IRQ_STAT_INFS        (1 << 26) /* Interface Non-Fatal Error
+                                               Status */
+#define PORT_IRQ_STAT_IFS         (1 << 27) /* Interface Fatal Error */
+#define PORT_IRQ_STAT_HBDS        (1 << 28) /* Host Bus Data Error Status */
+#define PORT_IRQ_STAT_HBFS        (1 << 29) /* Host Bus Fatal Error Status */
+#define PORT_IRQ_STAT_TFES        (1 << 30) /* Task File Error Status */
+#define PORT_IRQ_STAT_CPDS        (1 << 31) /* Code Port Detect Status */
+
+#endif // ahci.h
diff --git a/src/hw/ata.c b/src/hw/ata.c
new file mode 100644 (file)
index 0000000..e319aa9
--- /dev/null
@@ -0,0 +1,1043 @@
+// Low level ATA disk access
+//
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "types.h" // u8
+#include "ioport.h" // inb
+#include "util.h" // dprintf
+#include "byteorder.h" // be16_to_cpu
+#include "cmos.h" // inb_cmos
+#include "pic.h" // enable_hwirq
+#include "biosvar.h" // GET_GLOBAL
+#include "pci.h" // foreachpci
+#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER
+#include "pci_regs.h" // PCI_INTERRUPT_LINE
+#include "boot.h" // boot_add_hd
+#include "disk.h" // struct ata_s
+#include "ata.h" // ATA_CB_STAT
+#include "blockcmd.h" // CDB_CMD_READ_10
+
+#define IDE_TIMEOUT 32000 //32 seconds max for IDE ops
+
+
+/****************************************************************
+ * Helper functions
+ ****************************************************************/
+
+// Wait for the specified ide state
+static inline int
+await_ide(u8 mask, u8 flags, u16 base, u16 timeout)
+{
+    u32 end = timer_calc(timeout);
+    for (;;) {
+        u8 status = inb(base+ATA_CB_STAT);
+        if ((status & mask) == flags)
+            return status;
+        if (timer_check(end)) {
+            warn_timeout();
+            return -1;
+        }
+        yield();
+    }
+}
+
+// Wait for the device to be not-busy.
+static int
+await_not_bsy(u16 base)
+{
+    return await_ide(ATA_CB_STAT_BSY, 0, base, IDE_TIMEOUT);
+}
+
+// Wait for the device to be ready.
+static int
+await_rdy(u16 base)
+{
+    return await_ide(ATA_CB_STAT_RDY, ATA_CB_STAT_RDY, base, IDE_TIMEOUT);
+}
+
+// Wait for ide state - pauses for one ata cycle first.
+static inline int
+pause_await_not_bsy(u16 iobase1, u16 iobase2)
+{
+    // Wait one PIO transfer cycle.
+    inb(iobase2 + ATA_CB_ASTAT);
+
+    return await_not_bsy(iobase1);
+}
+
+// Wait for ide state - pause for 400ns first.
+static inline int
+ndelay_await_not_bsy(u16 iobase1)
+{
+    ndelay(400);
+    return await_not_bsy(iobase1);
+}
+
+// Reset a drive
+static void
+ata_reset(struct atadrive_s *adrive_g)
+{
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u8 slave = GET_GLOBAL(adrive_g->slave);
+    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
+
+    dprintf(6, "ata_reset drive=%p\n", &adrive_g->drive);
+    // Pulse SRST
+    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC);
+    udelay(5);
+    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
+    msleep(2);
+
+    // wait for device to become not busy.
+    int status = await_not_bsy(iobase1);
+    if (status < 0)
+        goto done;
+    if (slave) {
+        // Change device.
+        u32 end = timer_calc(IDE_TIMEOUT);
+        for (;;) {
+            outb(ATA_CB_DH_DEV1, iobase1 + ATA_CB_DH);
+            status = ndelay_await_not_bsy(iobase1);
+            if (status < 0)
+                goto done;
+            if (inb(iobase1 + ATA_CB_DH) == ATA_CB_DH_DEV1)
+                break;
+            // Change drive request failed to take effect - retry.
+            if (timer_check(end)) {
+                warn_timeout();
+                goto done;
+            }
+        }
+    } else {
+        // QEMU doesn't reset dh on reset, so set it explicitly.
+        outb(ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH);
+    }
+
+    // On a user-reset request, wait for RDY if it is an ATA device.
+    u8 type=GET_GLOBAL(adrive_g->drive.type);
+    if (type == DTYPE_ATA)
+        status = await_rdy(iobase1);
+
+done:
+    // Enable interrupts
+    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
+
+    dprintf(6, "ata_reset exit status=%x\n", status);
+}
+
+// Check for drive RDY for 16bit interface command.
+static int
+isready(struct atadrive_s *adrive_g)
+{
+    // Read the status from controller
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+    u8 status = inb(iobase1 + ATA_CB_STAT);
+    if ((status & (ATA_CB_STAT_BSY|ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY)
+        return DISK_RET_SUCCESS;
+    return DISK_RET_ENOTREADY;
+}
+
+
+/****************************************************************
+ * ATA send command
+ ****************************************************************/
+
+struct ata_pio_command {
+    u8 feature;
+    u8 sector_count;
+    u8 lba_low;
+    u8 lba_mid;
+    u8 lba_high;
+    u8 device;
+    u8 command;
+
+    u8 feature2;
+    u8 sector_count2;
+    u8 lba_low2;
+    u8 lba_mid2;
+    u8 lba_high2;
+};
+
+// Send an ata command to the drive.
+static int
+send_cmd(struct atadrive_s *adrive_g, struct ata_pio_command *cmd)
+{
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u8 slave = GET_GLOBAL(adrive_g->slave);
+    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+
+    // Select device
+    int status = await_not_bsy(iobase1);
+    if (status < 0)
+        return status;
+    u8 newdh = ((cmd->device & ~ATA_CB_DH_DEV1)
+                | (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0));
+    u8 olddh = inb(iobase1 + ATA_CB_DH);
+    outb(newdh, iobase1 + ATA_CB_DH);
+    if ((olddh ^ newdh) & (1<<4)) {
+        // Was a device change - wait for device to become not busy.
+        status = ndelay_await_not_bsy(iobase1);
+        if (status < 0)
+            return status;
+    }
+
+    // Check for ATA_CMD_(READ|WRITE)_(SECTORS|DMA)_EXT commands.
+    if ((cmd->command & ~0x11) == ATA_CMD_READ_SECTORS_EXT) {
+        outb(cmd->feature2, iobase1 + ATA_CB_FR);
+        outb(cmd->sector_count2, iobase1 + ATA_CB_SC);
+        outb(cmd->lba_low2, iobase1 + ATA_CB_SN);
+        outb(cmd->lba_mid2, iobase1 + ATA_CB_CL);
+        outb(cmd->lba_high2, iobase1 + ATA_CB_CH);
+    }
+    outb(cmd->feature, iobase1 + ATA_CB_FR);
+    outb(cmd->sector_count, iobase1 + ATA_CB_SC);
+    outb(cmd->lba_low, iobase1 + ATA_CB_SN);
+    outb(cmd->lba_mid, iobase1 + ATA_CB_CL);
+    outb(cmd->lba_high, iobase1 + ATA_CB_CH);
+    outb(cmd->command, iobase1 + ATA_CB_CMD);
+
+    return 0;
+}
+
+// Wait for data after calling 'send_cmd'.
+static int
+ata_wait_data(u16 iobase1)
+{
+    int status = ndelay_await_not_bsy(iobase1);
+    if (status < 0)
+        return status;
+
+    if (status & ATA_CB_STAT_ERR) {
+        dprintf(6, "send_cmd : read error (status=%02x err=%02x)\n"
+                , status, inb(iobase1 + ATA_CB_ERR));
+        return -4;
+    }
+    if (!(status & ATA_CB_STAT_DRQ)) {
+        dprintf(6, "send_cmd : DRQ not set (status %02x)\n", status);
+        return -5;
+    }
+
+    return 0;
+}
+
+// Send an ata command that does not transfer any further data.
+int
+ata_cmd_nondata(struct atadrive_s *adrive_g, struct ata_pio_command *cmd)
+{
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
+
+    // Disable interrupts
+    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
+
+    int ret = send_cmd(adrive_g, cmd);
+    if (ret)
+        goto fail;
+    ret = ndelay_await_not_bsy(iobase1);
+    if (ret < 0)
+        goto fail;
+
+    if (ret & ATA_CB_STAT_ERR) {
+        dprintf(6, "nondata cmd : read error (status=%02x err=%02x)\n"
+                , ret, inb(iobase1 + ATA_CB_ERR));
+        ret = -4;
+        goto fail;
+    }
+    if (ret & ATA_CB_STAT_DRQ) {
+        dprintf(6, "nondata cmd : DRQ set (status %02x)\n", ret);
+        ret = -5;
+        goto fail;
+    }
+
+fail:
+    // Enable interrupts
+    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
+
+    return ret;
+}
+
+
+/****************************************************************
+ * ATA PIO transfers
+ ****************************************************************/
+
+// Transfer 'op->count' blocks (of 'blocksize' bytes) to/from drive
+// 'op->drive_g'.
+static int
+ata_pio_transfer(struct disk_op_s *op, int iswrite, int blocksize)
+{
+    dprintf(16, "ata_pio_transfer id=%p write=%d count=%d bs=%d buf=%p\n"
+            , op->drive_g, iswrite, op->count, blocksize, op->buf_fl);
+
+    struct atadrive_s *adrive_g = container_of(
+        op->drive_g, struct atadrive_s, drive);
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
+    int count = op->count;
+    void *buf_fl = op->buf_fl;
+    int status;
+    for (;;) {
+        if (iswrite) {
+            // Write data to controller
+            dprintf(16, "Write sector id=%p dest=%p\n", op->drive_g, buf_fl);
+            if (CONFIG_ATA_PIO32)
+                outsl_fl(iobase1, buf_fl, blocksize / 4);
+            else
+                outsw_fl(iobase1, buf_fl, blocksize / 2);
+        } else {
+            // Read data from controller
+            dprintf(16, "Read sector id=%p dest=%p\n", op->drive_g, buf_fl);
+            if (CONFIG_ATA_PIO32)
+                insl_fl(iobase1, buf_fl, blocksize / 4);
+            else
+                insw_fl(iobase1, buf_fl, blocksize / 2);
+        }
+        buf_fl += blocksize;
+
+        status = pause_await_not_bsy(iobase1, iobase2);
+        if (status < 0) {
+            // Error
+            op->count -= count;
+            return status;
+        }
+
+        count--;
+        if (!count)
+            break;
+        status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR);
+        if (status != ATA_CB_STAT_DRQ) {
+            dprintf(6, "ata_pio_transfer : more sectors left (status %02x)\n"
+                    , status);
+            op->count -= count;
+            return -6;
+        }
+    }
+
+    status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ
+               | ATA_CB_STAT_ERR);
+    if (!iswrite)
+        status &= ~ATA_CB_STAT_DF;
+    if (status != 0) {
+        dprintf(6, "ata_pio_transfer : no sectors left (status %02x)\n", status);
+        return -7;
+    }
+
+    return 0;
+}
+
+
+/****************************************************************
+ * ATA DMA transfers
+ ****************************************************************/
+
+#define BM_CMD    0
+#define  BM_CMD_MEMWRITE  0x08
+#define  BM_CMD_START     0x01
+#define BM_STATUS 2
+#define  BM_STATUS_IRQ    0x04
+#define  BM_STATUS_ERROR  0x02
+#define  BM_STATUS_ACTIVE 0x01
+#define BM_TABLE  4
+
+struct sff_dma_prd {
+    u32 buf_fl;
+    u32 count;
+};
+
+// Check if DMA available and setup transfer if so.
+static int
+ata_try_dma(struct disk_op_s *op, int iswrite, int blocksize)
+{
+    ASSERT16();
+    if (! CONFIG_ATA_DMA)
+        return -1;
+    u32 dest = (u32)op->buf_fl;
+    if (dest & 1)
+        // Need minimum alignment of 1.
+        return -1;
+    struct atadrive_s *adrive_g = container_of(
+        op->drive_g, struct atadrive_s, drive);
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u16 iomaster = GET_GLOBALFLAT(chan_gf->iomaster);
+    if (! iomaster)
+        return -1;
+    u32 bytes = op->count * blocksize;
+    if (! bytes)
+        return -1;
+
+    // Build PRD dma structure.
+    struct sff_dma_prd *dma = MAKE_FLATPTR(SEG_LOW, ExtraStack);
+    struct sff_dma_prd *origdma = dma;
+    while (bytes) {
+        if (dma >= &origdma[16])
+            // Too many descriptors..
+            return -1;
+        u32 count = bytes;
+        u32 max = 0x10000 - (dest & 0xffff);
+        if (count > max)
+            count = max;
+
+        SET_LOWFLAT(dma->buf_fl, dest);
+        bytes -= count;
+        if (!bytes)
+            // Last descriptor.
+            count |= 1<<31;
+        dprintf(16, "dma@%p: %08x %08x\n", dma, dest, count);
+        dest += count;
+        SET_LOWFLAT(dma->count, count);
+        dma++;
+    }
+
+    // Program bus-master controller.
+    outl((u32)origdma, iomaster + BM_TABLE);
+    u8 oldcmd = inb(iomaster + BM_CMD) & ~(BM_CMD_MEMWRITE|BM_CMD_START);
+    outb(oldcmd | (iswrite ? 0x00 : BM_CMD_MEMWRITE), iomaster + BM_CMD);
+    outb(BM_STATUS_ERROR|BM_STATUS_IRQ, iomaster + BM_STATUS);
+
+    return 0;
+}
+
+// Transfer data using DMA.
+static int
+ata_dma_transfer(struct disk_op_s *op)
+{
+    if (! CONFIG_ATA_DMA)
+        return -1;
+    dprintf(16, "ata_dma_transfer id=%p buf=%p\n", op->drive_g, op->buf_fl);
+
+    struct atadrive_s *adrive_g = container_of(
+        op->drive_g, struct atadrive_s, drive);
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u16 iomaster = GET_GLOBALFLAT(chan_gf->iomaster);
+
+    // Start bus-master controller.
+    u8 oldcmd = inb(iomaster + BM_CMD);
+    outb(oldcmd | BM_CMD_START, iomaster + BM_CMD);
+
+    u32 end = timer_calc(IDE_TIMEOUT);
+    u8 status;
+    for (;;) {
+        status = inb(iomaster + BM_STATUS);
+        if (status & BM_STATUS_IRQ)
+            break;
+        // Transfer in progress
+        if (timer_check(end)) {
+            // Timeout.
+            warn_timeout();
+            break;
+        }
+        yield();
+    }
+    outb(oldcmd & ~BM_CMD_START, iomaster + BM_CMD);
+
+    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
+    int idestatus = pause_await_not_bsy(iobase1, iobase2);
+
+    if ((status & (BM_STATUS_IRQ|BM_STATUS_ACTIVE)) == BM_STATUS_IRQ
+        && idestatus >= 0x00
+        && (idestatus & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ
+                         | ATA_CB_STAT_ERR)) == 0x00)
+        // Success.
+        return 0;
+
+    dprintf(6, "IDE DMA error (dma=%x ide=%x/%x/%x)\n", status, idestatus
+            , inb(iobase2 + ATA_CB_ASTAT), inb(iobase1 + ATA_CB_ERR));
+    op->count = 0;
+    return -1;
+}
+
+
+/****************************************************************
+ * ATA hard drive functions
+ ****************************************************************/
+
+// Transfer data to harddrive using PIO protocol.
+static int
+ata_pio_cmd_data(struct disk_op_s *op, int iswrite, struct ata_pio_command *cmd)
+{
+    struct atadrive_s *adrive_g = container_of(
+        op->drive_g, struct atadrive_s, drive);
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
+
+    // Disable interrupts
+    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
+
+    int ret = send_cmd(adrive_g, cmd);
+    if (ret)
+        goto fail;
+    ret = ata_wait_data(iobase1);
+    if (ret)
+        goto fail;
+    ret = ata_pio_transfer(op, iswrite, DISK_SECTOR_SIZE);
+
+fail:
+    // Enable interrupts
+    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
+    return ret;
+}
+
+// Transfer data to harddrive using DMA protocol.
+static int
+ata_dma_cmd_data(struct disk_op_s *op, struct ata_pio_command *cmd)
+{
+    if (! CONFIG_ATA_DMA)
+        return -1;
+    struct atadrive_s *adrive_g = container_of(
+        op->drive_g, struct atadrive_s, drive);
+    int ret = send_cmd(adrive_g, cmd);
+    if (ret)
+        return ret;
+    return ata_dma_transfer(op);
+}
+
+// Read/write count blocks from a harddrive.
+static int
+ata_readwrite(struct disk_op_s *op, int iswrite)
+{
+    u64 lba = op->lba;
+
+    int usepio = ata_try_dma(op, iswrite, DISK_SECTOR_SIZE);
+
+    struct ata_pio_command cmd;
+    memset(&cmd, 0, sizeof(cmd));
+
+    if (op->count >= (1<<8) || lba + op->count >= (1<<28)) {
+        cmd.sector_count2 = op->count >> 8;
+        cmd.lba_low2 = lba >> 24;
+        cmd.lba_mid2 = lba >> 32;
+        cmd.lba_high2 = lba >> 40;
+        lba &= 0xffffff;
+
+        if (usepio)
+            cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS_EXT
+                           : ATA_CMD_READ_SECTORS_EXT);
+        else
+            cmd.command = (iswrite ? ATA_CMD_WRITE_DMA_EXT
+                           : ATA_CMD_READ_DMA_EXT);
+    } else {
+        if (usepio)
+            cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS
+                           : ATA_CMD_READ_SECTORS);
+        else
+            cmd.command = (iswrite ? ATA_CMD_WRITE_DMA
+                           : ATA_CMD_READ_DMA);
+    }
+
+    cmd.sector_count = op->count;
+    cmd.lba_low = lba;
+    cmd.lba_mid = lba >> 8;
+    cmd.lba_high = lba >> 16;
+    cmd.device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA;
+
+    int ret;
+    if (usepio)
+        ret = ata_pio_cmd_data(op, iswrite, &cmd);
+    else
+        ret = ata_dma_cmd_data(op, &cmd);
+    if (ret)
+        return DISK_RET_EBADTRACK;
+    return DISK_RET_SUCCESS;
+}
+
+// 16bit command demuxer for ATA harddrives.
+int
+process_ata_op(struct disk_op_s *op)
+{
+    if (!CONFIG_ATA)
+        return 0;
+
+    struct atadrive_s *adrive_g = container_of(
+        op->drive_g, struct atadrive_s, drive);
+    switch (op->command) {
+    case CMD_READ:
+        return ata_readwrite(op, 0);
+    case CMD_WRITE:
+        return ata_readwrite(op, 1);
+    case CMD_RESET:
+        ata_reset(adrive_g);
+        return DISK_RET_SUCCESS;
+    case CMD_ISREADY:
+        return isready(adrive_g);
+    case CMD_FORMAT:
+    case CMD_VERIFY:
+    case CMD_SEEK:
+        return DISK_RET_SUCCESS;
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
+
+
+/****************************************************************
+ * ATAPI functions
+ ****************************************************************/
+
+#define CDROM_CDB_SIZE 12
+
+// Low-level atapi command transmit function.
+int
+atapi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    if (! CONFIG_ATA)
+        return 0;
+
+    struct atadrive_s *adrive_g = container_of(
+        op->drive_g, struct atadrive_s, drive);
+    struct ata_channel_s *chan_gf = GET_GLOBAL(adrive_g->chan_gf);
+    u16 iobase1 = GET_GLOBALFLAT(chan_gf->iobase1);
+    u16 iobase2 = GET_GLOBALFLAT(chan_gf->iobase2);
+
+    struct ata_pio_command cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.lba_mid = blocksize;
+    cmd.lba_high = blocksize >> 8;
+    cmd.command = ATA_CMD_PACKET;
+
+    // Disable interrupts
+    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
+
+    int ret = send_cmd(adrive_g, &cmd);
+    if (ret)
+        goto fail;
+    ret = ata_wait_data(iobase1);
+    if (ret)
+        goto fail;
+
+    // Send command to device
+    outsw_fl(iobase1, MAKE_FLATPTR(GET_SEG(SS), cdbcmd), CDROM_CDB_SIZE / 2);
+
+    int status = pause_await_not_bsy(iobase1, iobase2);
+    if (status < 0) {
+        ret = status;
+        goto fail;
+    }
+
+    if (status & ATA_CB_STAT_ERR) {
+        u8 err = inb(iobase1 + ATA_CB_ERR);
+        // skip "Not Ready"
+        if (err != 0x20)
+            dprintf(6, "send_atapi_cmd : read error (status=%02x err=%02x)\n"
+                    , status, err);
+        ret = -2;
+        goto fail;
+    }
+    if (blocksize) {
+        if (!(status & ATA_CB_STAT_DRQ)) {
+            dprintf(6, "send_atapi_cmd : DRQ not set (status %02x)\n", status);
+            ret = -3;
+            goto fail;
+        }
+
+        ret = ata_pio_transfer(op, 0, blocksize);
+    }
+
+fail:
+    // Enable interrupts
+    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
+    if (ret)
+        return DISK_RET_EBADTRACK;
+    return DISK_RET_SUCCESS;
+}
+
+
+/****************************************************************
+ * ATA detect and init
+ ****************************************************************/
+
+// Send an identify device or identify device packet command.
+static int
+send_ata_identity(struct atadrive_s *adrive_g, u16 *buffer, int command)
+{
+    memset(buffer, 0, DISK_SECTOR_SIZE);
+
+    struct disk_op_s dop;
+    memset(&dop, 0, sizeof(dop));
+    dop.drive_g = &adrive_g->drive;
+    dop.count = 1;
+    dop.lba = 1;
+    dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer);
+
+    struct ata_pio_command cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = command;
+
+    return ata_pio_cmd_data(&dop, 0, &cmd);
+}
+
+// Extract the ATA/ATAPI version info.
+int
+ata_extract_version(u16 *buffer)
+{
+    // Extract ATA/ATAPI version.
+    u16 ataversion = buffer[80];
+    u8 version;
+    for (version=15; version>0; version--)
+        if (ataversion & (1<<version))
+            break;
+    return version;
+}
+
+#define MAXMODEL 40
+
+// Extract the ATA/ATAPI model info.
+char *
+ata_extract_model(char *model, u32 size, u16 *buffer)
+{
+    // Read model name
+    int i;
+    for (i=0; i<size/2; i++)
+        *(u16*)&model[i*2] = be16_to_cpu(buffer[27+i]);
+    model[size] = 0x00;
+    nullTrailingSpace(model);
+    return model;
+}
+
+// Common init code between ata and atapi
+static struct atadrive_s *
+init_atadrive(struct atadrive_s *dummy, u16 *buffer)
+{
+    struct atadrive_s *adrive_g = malloc_fseg(sizeof(*adrive_g));
+    if (!adrive_g) {
+        warn_noalloc();
+        return NULL;
+    }
+    memset(adrive_g, 0, sizeof(*adrive_g));
+    adrive_g->chan_gf = dummy->chan_gf;
+    adrive_g->slave = dummy->slave;
+    adrive_g->drive.cntl_id = adrive_g->chan_gf->chanid * 2 + dummy->slave;
+    adrive_g->drive.removable = (buffer[0] & 0x80) ? 1 : 0;
+    return adrive_g;
+}
+
+// Detect if the given drive is an atapi - initialize it if so.
+static struct atadrive_s *
+init_drive_atapi(struct atadrive_s *dummy, u16 *buffer)
+{
+    // Send an IDENTIFY_DEVICE_PACKET command to device
+    int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_PACKET_DEVICE);
+    if (ret)
+        return NULL;
+
+    // Success - setup as ATAPI.
+    struct atadrive_s *adrive_g = init_atadrive(dummy, buffer);
+    if (!adrive_g)
+        return NULL;
+    adrive_g->drive.type = DTYPE_ATA_ATAPI;
+    adrive_g->drive.blksize = CDROM_SECTOR_SIZE;
+    adrive_g->drive.sectors = (u64)-1;
+    u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
+    char model[MAXMODEL+1];
+    char *desc = znprintf(MAXDESCSIZE
+                          , "DVD/CD [ata%d-%d: %s ATAPI-%d %s]"
+                          , adrive_g->chan_gf->chanid, adrive_g->slave
+                          , ata_extract_model(model, MAXMODEL, buffer)
+                          , ata_extract_version(buffer)
+                          , (iscd ? "DVD/CD" : "Device"));
+    dprintf(1, "%s\n", desc);
+
+    // fill cdidmap
+    if (iscd) {
+        int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_tmp,
+                                            adrive_g->chan_gf->chanid,
+                                            adrive_g->slave);
+        boot_add_cd(&adrive_g->drive, desc, prio);
+    }
+
+    return adrive_g;
+}
+
+// Detect if the given drive is a regular ata drive - initialize it if so.
+static struct atadrive_s *
+init_drive_ata(struct atadrive_s *dummy, u16 *buffer)
+{
+    // Send an IDENTIFY_DEVICE command to device
+    int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_DEVICE);
+    if (ret)
+        return NULL;
+
+    // Success - setup as ATA.
+    struct atadrive_s *adrive_g = init_atadrive(dummy, buffer);
+    if (!adrive_g)
+        return NULL;
+    adrive_g->drive.type = DTYPE_ATA;
+    adrive_g->drive.blksize = DISK_SECTOR_SIZE;
+
+    adrive_g->drive.pchs.cylinders = buffer[1];
+    adrive_g->drive.pchs.heads = buffer[3];
+    adrive_g->drive.pchs.spt = buffer[6];
+
+    u64 sectors;
+    if (buffer[83] & (1 << 10)) // word 83 - lba48 support
+        sectors = *(u64*)&buffer[100]; // word 100-103
+    else
+        sectors = *(u32*)&buffer[60]; // word 60 and word 61
+    adrive_g->drive.sectors = sectors;
+    u64 adjsize = sectors >> 11;
+    char adjprefix = 'M';
+    if (adjsize >= (1 << 16)) {
+        adjsize >>= 10;
+        adjprefix = 'G';
+    }
+    char model[MAXMODEL+1];
+    char *desc = znprintf(MAXDESCSIZE
+                          , "ata%d-%d: %s ATA-%d Hard-Disk (%u %ciBytes)"
+                          , adrive_g->chan_gf->chanid, adrive_g->slave
+                          , ata_extract_model(model, MAXMODEL, buffer)
+                          , ata_extract_version(buffer)
+                          , (u32)adjsize, adjprefix);
+    dprintf(1, "%s\n", desc);
+
+    int prio = bootprio_find_ata_device(adrive_g->chan_gf->pci_tmp,
+                                        adrive_g->chan_gf->chanid,
+                                        adrive_g->slave);
+    // Register with bcv system.
+    boot_add_hd(&adrive_g->drive, desc, prio);
+
+    return adrive_g;
+}
+
+static u32 SpinupEnd;
+
+// Wait for non-busy status and check for "floating bus" condition.
+static int
+powerup_await_non_bsy(u16 base)
+{
+    u8 orstatus = 0;
+    u8 status;
+    for (;;) {
+        status = inb(base+ATA_CB_STAT);
+        if (!(status & ATA_CB_STAT_BSY))
+            break;
+        orstatus |= status;
+        if (orstatus == 0xff) {
+            dprintf(4, "powerup IDE floating\n");
+            return orstatus;
+        }
+        if (timer_check(SpinupEnd)) {
+            warn_timeout();
+            return -1;
+        }
+        yield();
+    }
+    dprintf(6, "powerup iobase=%x st=%x\n", base, status);
+    return status;
+}
+
+// Detect any drives attached to a given controller.
+static void
+ata_detect(void *data)
+{
+    struct ata_channel_s *chan_gf = data;
+    struct atadrive_s dummy;
+    memset(&dummy, 0, sizeof(dummy));
+    dummy.chan_gf = chan_gf;
+    // Device detection
+    int didreset = 0;
+    u8 slave;
+    for (slave=0; slave<=1; slave++) {
+        // Wait for not-bsy.
+        u16 iobase1 = chan_gf->iobase1;
+        int status = powerup_await_non_bsy(iobase1);
+        if (status < 0)
+            continue;
+        u8 newdh = slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0;
+        outb(newdh, iobase1+ATA_CB_DH);
+        ndelay(400);
+        status = powerup_await_non_bsy(iobase1);
+        if (status < 0)
+            continue;
+
+        // Check if ioport registers look valid.
+        outb(newdh, iobase1+ATA_CB_DH);
+        u8 dh = inb(iobase1+ATA_CB_DH);
+        outb(0x55, iobase1+ATA_CB_SC);
+        outb(0xaa, iobase1+ATA_CB_SN);
+        u8 sc = inb(iobase1+ATA_CB_SC);
+        u8 sn = inb(iobase1+ATA_CB_SN);
+        dprintf(6, "ata_detect ata%d-%d: sc=%x sn=%x dh=%x\n"
+                , chan_gf->chanid, slave, sc, sn, dh);
+        if (sc != 0x55 || sn != 0xaa || dh != newdh)
+            continue;
+
+        // Prepare new drive.
+        dummy.slave = slave;
+
+        // reset the channel
+        if (!didreset) {
+            ata_reset(&dummy);
+            didreset = 1;
+        }
+
+        // check for ATAPI
+        u16 buffer[256];
+        struct atadrive_s *adrive_g = init_drive_atapi(&dummy, buffer);
+        if (!adrive_g) {
+            // Didn't find an ATAPI drive - look for ATA drive.
+            u8 st = inb(iobase1+ATA_CB_STAT);
+            if (!st)
+                // Status not set - can't be a valid drive.
+                continue;
+
+            // Wait for RDY.
+            int ret = await_rdy(iobase1);
+            if (ret < 0)
+                continue;
+
+            // check for ATA.
+            adrive_g = init_drive_ata(&dummy, buffer);
+            if (!adrive_g)
+                // No ATA drive found
+                continue;
+        }
+
+        u16 resetresult = buffer[93];
+        dprintf(6, "ata_detect resetresult=%04x\n", resetresult);
+        if (!slave && (resetresult & 0xdf61) == 0x4041)
+            // resetresult looks valid and device 0 is responding to
+            // device 1 requests - device 1 must not be present - skip
+            // detection.
+            break;
+    }
+}
+
+// Initialize an ata controller and detect its drives.
+static void
+init_controller(struct pci_device *pci, int irq
+                , u32 port1, u32 port2, u32 master)
+{
+    static int chanid = 0;
+    struct ata_channel_s *chan_gf = malloc_fseg(sizeof(*chan_gf));
+    if (!chan_gf) {
+        warn_noalloc();
+        return;
+    }
+    chan_gf->chanid = chanid++;
+    chan_gf->irq = irq;
+    chan_gf->pci_bdf = pci ? pci->bdf : -1;
+    chan_gf->pci_tmp = pci;
+    chan_gf->iobase1 = port1;
+    chan_gf->iobase2 = port2;
+    chan_gf->iomaster = master;
+    dprintf(1, "ATA controller %d at %x/%x/%x (irq %d dev %x)\n"
+            , chanid, port1, port2, master, irq, chan_gf->pci_bdf);
+    run_thread(ata_detect, chan_gf);
+}
+
+#define IRQ_ATA1 14
+#define IRQ_ATA2 15
+
+// Handle controllers on an ATA PCI device.
+static void
+init_pciata(struct pci_device *pci, u8 prog_if)
+{
+    pci->have_driver = 1;
+    u16 bdf = pci->bdf;
+    u8 pciirq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
+    int master = 0;
+    if (CONFIG_ATA_DMA && prog_if & 0x80) {
+        // Check for bus-mastering.
+        u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_4);
+        if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
+            master = bar & PCI_BASE_ADDRESS_IO_MASK;
+            pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
+        }
+    }
+
+    u32 port1, port2, irq;
+    if (prog_if & 1) {
+        port1 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_0)
+                 & PCI_BASE_ADDRESS_IO_MASK);
+        port2 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_1)
+                 & PCI_BASE_ADDRESS_IO_MASK);
+        irq = pciirq;
+    } else {
+        port1 = PORT_ATA1_CMD_BASE;
+        port2 = PORT_ATA1_CTRL_BASE;
+        irq = IRQ_ATA1;
+    }
+    init_controller(pci, irq, port1, port2, master);
+
+    if (prog_if & 4) {
+        port1 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_2)
+                 & PCI_BASE_ADDRESS_IO_MASK);
+        port2 = (pci_config_readl(bdf, PCI_BASE_ADDRESS_3)
+                 & PCI_BASE_ADDRESS_IO_MASK);
+        irq = pciirq;
+    } else {
+        port1 = PORT_ATA2_CMD_BASE;
+        port2 = PORT_ATA2_CTRL_BASE;
+        irq = IRQ_ATA2;
+    }
+    init_controller(pci, irq, port1, port2, master ? master + 8 : 0);
+}
+
+static void
+found_genericata(struct pci_device *pci, void *arg)
+{
+    init_pciata(pci, pci->prog_if);
+}
+
+static void
+found_compatibleahci(struct pci_device *pci, void *arg)
+{
+    if (CONFIG_AHCI)
+        // Already handled directly via native ahci interface.
+        return;
+    init_pciata(pci, 0x8f);
+}
+
+static const struct pci_device_id pci_ata_tbl[] = {
+    PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE
+                     , found_genericata),
+    PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4391, found_compatibleahci),
+    PCI_DEVICE_END,
+};
+
+// Locate and init ata controllers.
+static void
+ata_scan(void)
+{
+    if (CONFIG_QEMU && hlist_empty(&PCIDevices)) {
+        // No PCI devices found - probably a QEMU "-M isapc" machine.
+        // Try using ISA ports for ATA controllers.
+        init_controller(NULL, IRQ_ATA1
+                        , PORT_ATA1_CMD_BASE, PORT_ATA1_CTRL_BASE, 0);
+        init_controller(NULL, IRQ_ATA2
+                        , PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE, 0);
+        return;
+    }
+
+    // Scan PCI bus for ATA adapters
+    struct pci_device *pci;
+    foreachpci(pci) {
+        pci_init_device(pci_ata_tbl, pci, NULL);
+    }
+}
+
+void
+ata_setup(void)
+{
+    ASSERT32FLAT();
+    if (!CONFIG_ATA)
+        return;
+
+    dprintf(3, "init hard drives\n");
+
+    SpinupEnd = timer_calc(IDE_TIMEOUT);
+    ata_scan();
+
+    SET_BDA(disk_control_byte, 0xc0);
+
+    enable_hwirq(14, FUNC16(entry_76));
+}
diff --git a/src/hw/ata.h b/src/hw/ata.h
new file mode 100644 (file)
index 0000000..1f41233
--- /dev/null
@@ -0,0 +1,153 @@
+#ifndef __ATA_H
+#define __ATA_H
+
+#include "types.h" // u8
+#include "config.h" // CONFIG_MAX_ATA_INTERFACES
+#include "disk.h" // struct drive_s
+
+struct ata_channel_s {
+    u16 iobase1;
+    u16 iobase2;
+    u16 iomaster;
+    u8  irq;
+    u8  chanid;
+    int pci_bdf;
+    struct pci_device *pci_tmp;
+};
+
+struct atadrive_s {
+    struct drive_s drive;
+    struct ata_channel_s *chan_gf;
+    u8 slave;
+};
+
+// ata.c
+char *ata_extract_model(char *model, u32 size, u16 *buffer);
+int ata_extract_version(u16 *buffer);
+int cdrom_read(struct disk_op_s *op);
+int atapi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+void ata_setup(void);
+int process_ata_op(struct disk_op_s *op);
+
+// Global defines -- ATA register and register bits.
+// command block & control block regs
+#define ATA_CB_DATA  0   // data reg         in/out pio_base_addr1+0
+#define ATA_CB_ERR   1   // error            in     pio_base_addr1+1
+#define ATA_CB_FR    1   // feature reg         out pio_base_addr1+1
+#define ATA_CB_SC    2   // sector count     in/out pio_base_addr1+2
+#define ATA_CB_SN    3   // sector number    in/out pio_base_addr1+3
+#define ATA_CB_CL    4   // cylinder low     in/out pio_base_addr1+4
+#define ATA_CB_CH    5   // cylinder high    in/out pio_base_addr1+5
+#define ATA_CB_DH    6   // device head      in/out pio_base_addr1+6
+#define ATA_CB_STAT  7   // primary status   in     pio_base_addr1+7
+#define ATA_CB_CMD   7   // command             out pio_base_addr1+7
+
+#define ATA_CB_ASTAT 2   // alternate status in     pio_base_addr2+2
+#define ATA_CB_DC    2   // device control      out pio_base_addr2+2
+#define ATA_CB_DA    3   // device address   in     pio_base_addr2+3
+
+#define ATA_CB_ER_ICRC 0x80    // ATA Ultra DMA bad CRC
+#define ATA_CB_ER_BBK  0x80    // ATA bad block
+#define ATA_CB_ER_UNC  0x40    // ATA uncorrected error
+#define ATA_CB_ER_MC   0x20    // ATA media change
+#define ATA_CB_ER_IDNF 0x10    // ATA id not found
+#define ATA_CB_ER_MCR  0x08    // ATA media change request
+#define ATA_CB_ER_ABRT 0x04    // ATA command aborted
+#define ATA_CB_ER_NTK0 0x02    // ATA track 0 not found
+#define ATA_CB_ER_NDAM 0x01    // ATA address mark not found
+
+#define ATA_CB_ER_P_SNSKEY 0xf0   // ATAPI sense key (mask)
+#define ATA_CB_ER_P_MCR    0x08   // ATAPI Media Change Request
+#define ATA_CB_ER_P_ABRT   0x04   // ATAPI command abort
+#define ATA_CB_ER_P_EOM    0x02   // ATAPI End of Media
+#define ATA_CB_ER_P_ILI    0x01   // ATAPI Illegal Length Indication
+
+// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
+#define ATA_CB_SC_P_TAG    0xf8   // ATAPI tag (mask)
+#define ATA_CB_SC_P_REL    0x04   // ATAPI release
+#define ATA_CB_SC_P_IO     0x02   // ATAPI I/O
+#define ATA_CB_SC_P_CD     0x01   // ATAPI C/D
+
+// bits 7-4 of the device/head (CB_DH) reg
+#define ATA_CB_DH_DEV0 0xa0    // select device 0
+#define ATA_CB_DH_DEV1 0xb0    // select device 1
+#define ATA_CB_DH_LBA 0x40    // use LBA
+
+// status reg (CB_STAT and CB_ASTAT) bits
+#define ATA_CB_STAT_BSY  0x80  // busy
+#define ATA_CB_STAT_RDY  0x40  // ready
+#define ATA_CB_STAT_DF   0x20  // device fault
+#define ATA_CB_STAT_WFT  0x20  // write fault (old name)
+#define ATA_CB_STAT_SKC  0x10  // seek complete
+#define ATA_CB_STAT_SERV 0x10  // service
+#define ATA_CB_STAT_DRQ  0x08  // data request
+#define ATA_CB_STAT_CORR 0x04  // corrected
+#define ATA_CB_STAT_IDX  0x02  // index
+#define ATA_CB_STAT_ERR  0x01  // error (ATA)
+#define ATA_CB_STAT_CHK  0x01  // check (ATAPI)
+
+// device control reg (CB_DC) bits
+#define ATA_CB_DC_HD15   0x08  // bit should always be set to one
+#define ATA_CB_DC_SRST   0x04  // soft reset
+#define ATA_CB_DC_NIEN   0x02  // disable interrupts
+
+// Most mandtory and optional ATA commands (from ATA-3),
+#define ATA_CMD_NOP                          0x00
+#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE     0x03
+#define ATA_CMD_DEVICE_RESET                 0x08
+#define ATA_CMD_RECALIBRATE                  0x10
+#define ATA_CMD_READ_SECTORS                 0x20
+#define ATA_CMD_READ_SECTORS_EXT             0x24
+#define ATA_CMD_READ_DMA_EXT                 0x25
+#define ATA_CMD_READ_DMA_QUEUED_EXT          0x26
+#define ATA_CMD_READ_NATIVE_MAX_ADDRESS_EXT  0x27
+#define ATA_CMD_READ_MULTIPLE_EXT            0x29
+#define ATA_CMD_READ_LOG_EXT                 0x2F
+#define ATA_CMD_WRITE_SECTORS                0x30
+#define ATA_CMD_WRITE_SECTORS_EXT            0x34
+#define ATA_CMD_WRITE_DMA_EXT                0x35
+#define ATA_CMD_WRITE_DMA_QUEUED_EXT         0x36
+#define ATA_CMD_SET_MAX_ADDRESS_EXT          0x37
+#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE   0x38
+#define ATA_CMD_WRITE_MULTIPLE_EXT           0x39
+#define ATA_CMD_WRITE_VERIFY                 0x3C
+#define ATA_CMD_WRITE_LOG_EXT                0x3F
+#define ATA_CMD_READ_VERIFY_SECTORS          0x40
+#define ATA_CMD_READ_VERIFY_SECTORS_EXT      0x42
+#define ATA_CMD_FORMAT_TRACK                 0x50
+#define ATA_CMD_SEEK                         0x70
+#define ATA_CMD_CFA_TRANSLATE_SECTOR         0x87
+#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC    0x90
+#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
+#define ATA_CMD_STANDBY_IMMEDIATE2           0x94
+#define ATA_CMD_IDLE_IMMEDIATE2              0x95
+#define ATA_CMD_STANDBY2                     0x96
+#define ATA_CMD_IDLE2                        0x97
+#define ATA_CMD_CHECK_POWER_MODE2            0x98
+#define ATA_CMD_SLEEP2                       0x99
+#define ATA_CMD_PACKET                       0xA0
+#define ATA_CMD_IDENTIFY_PACKET_DEVICE       0xA1
+#define ATA_CMD_CFA_ERASE_SECTORS            0xC0
+#define ATA_CMD_READ_MULTIPLE                0xC4
+#define ATA_CMD_WRITE_MULTIPLE               0xC5
+#define ATA_CMD_SET_MULTIPLE_MODE            0xC6
+#define ATA_CMD_READ_DMA_QUEUED              0xC7
+#define ATA_CMD_READ_DMA                     0xC8
+#define ATA_CMD_WRITE_DMA                    0xCA
+#define ATA_CMD_WRITE_DMA_QUEUED             0xCC
+#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE  0xCD
+#define ATA_CMD_STANDBY_IMMEDIATE            0xE0
+#define ATA_CMD_IDLE_IMMEDIATE               0xE1
+#define ATA_CMD_STANDBY                      0xE2
+#define ATA_CMD_IDLE                         0xE3
+#define ATA_CMD_READ_BUFFER                  0xE4
+#define ATA_CMD_CHECK_POWER_MODE             0xE5
+#define ATA_CMD_SLEEP                        0xE6
+#define ATA_CMD_FLUSH_CACHE                  0xE7
+#define ATA_CMD_WRITE_BUFFER                 0xE8
+#define ATA_CMD_IDENTIFY_DEVICE              0xEC
+#define ATA_CMD_SET_FEATURES                 0xEF
+#define ATA_CMD_READ_NATIVE_MAX_ADDRESS      0xF8
+#define ATA_CMD_SET_MAX                      0xF9
+
+#endif // ata.h
diff --git a/src/hw/blockcmd.c b/src/hw/blockcmd.c
new file mode 100644 (file)
index 0000000..5cd4eb0
--- /dev/null
@@ -0,0 +1,278 @@
+// Support for several common scsi like command data block requests
+//
+// Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "biosvar.h" // GET_GLOBAL
+#include "util.h" // dprintf
+#include "byteorder.h" // be32_to_cpu
+#include "disk.h" // struct disk_op_s
+#include "blockcmd.h" // struct cdb_request_sense
+#include "ata.h" // atapi_cmd_data
+#include "ahci.h" // atapi_cmd_data
+#include "usb-msc.h" // usb_cmd_data
+#include "usb-uas.h" // usb_cmd_data
+#include "virtio-scsi.h" // virtio_scsi_cmd_data
+#include "lsi-scsi.h" // lsi_scsi_cmd_data
+#include "esp-scsi.h" // esp_scsi_cmd_data
+#include "megasas.h" // megasas_cmd_data
+#include "boot.h" // boot_add_hd
+
+// Route command to low-level handler.
+static int
+cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    u8 type = GET_GLOBAL(op->drive_g->type);
+    switch (type) {
+    case DTYPE_ATA_ATAPI:
+        return atapi_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_USB:
+        return usb_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_UAS:
+        return uas_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_AHCI_ATAPI:
+        return ahci_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_VIRTIO_SCSI:
+        return virtio_scsi_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_LSI_SCSI:
+        return lsi_scsi_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_ESP_SCSI:
+        return esp_scsi_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_MEGASAS:
+        return megasas_cmd_data(op, cdbcmd, blocksize);
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
+
+// Determine if the command is a request to pull data from the device
+int
+cdb_is_read(u8 *cdbcmd, u16 blocksize)
+{
+    return blocksize && cdbcmd[0] != CDB_CMD_WRITE_10;
+}
+
+int
+scsi_is_ready(struct disk_op_s *op)
+{
+    dprintf(6, "scsi_is_ready (drive=%p)\n", op->drive_g);
+
+    /* Retry TEST UNIT READY for 5 seconds unless MEDIUM NOT PRESENT is
+     * reported by the device.  If the device reports "IN PROGRESS",
+     * 30 seconds is added. */
+    int in_progress = 0;
+    u32 end = timer_calc(5000);
+    for (;;) {
+        if (timer_check(end)) {
+            dprintf(1, "test unit ready failed\n");
+            return -1;
+        }
+
+        int ret = cdb_test_unit_ready(op);
+        if (!ret)
+            // Success
+            break;
+
+        struct cdbres_request_sense sense;
+        ret = cdb_get_sense(op, &sense);
+        if (ret)
+            // Error - retry.
+            continue;
+
+        // Sense succeeded.
+        if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */
+            dprintf(1, "Device reports MEDIUM NOT PRESENT\n");
+            return -1;
+        }
+
+        if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) {
+            /* IN PROGRESS OF BECOMING READY */
+            printf("Waiting for device to detect medium... ");
+            /* Allow 30 seconds more */
+            end = timer_calc(30000);
+            in_progress = 1;
+        }
+    }
+    return 0;
+}
+
+// Validate drive, find block size / sector count, and register drive.
+int
+scsi_drive_setup(struct drive_s *drive, const char *s, int prio)
+{
+    struct disk_op_s dop;
+    memset(&dop, 0, sizeof(dop));
+    dop.drive_g = drive;
+    struct cdbres_inquiry data;
+    int ret = cdb_get_inquiry(&dop, &data);
+    if (ret)
+        return ret;
+    char vendor[sizeof(data.vendor)+1], product[sizeof(data.product)+1];
+    char rev[sizeof(data.rev)+1];
+    strtcpy(vendor, data.vendor, sizeof(vendor));
+    nullTrailingSpace(vendor);
+    strtcpy(product, data.product, sizeof(product));
+    nullTrailingSpace(product);
+    strtcpy(rev, data.rev, sizeof(rev));
+    nullTrailingSpace(rev);
+    int pdt = data.pdt & 0x1f;
+    int removable = !!(data.removable & 0x80);
+    dprintf(1, "%s vendor='%s' product='%s' rev='%s' type=%d removable=%d\n"
+            , s, vendor, product, rev, pdt, removable);
+    drive->removable = removable;
+
+    if (pdt == SCSI_TYPE_CDROM) {
+        drive->blksize = CDROM_SECTOR_SIZE;
+        drive->sectors = (u64)-1;
+
+        char *desc = znprintf(MAXDESCSIZE, "DVD/CD [%s Drive %s %s %s]"
+                              , s, vendor, product, rev);
+        boot_add_cd(drive, desc, prio);
+        return 0;
+    }
+
+    ret = scsi_is_ready(&dop);
+    if (ret) {
+        dprintf(1, "scsi_is_ready returned %d\n", ret);
+        return ret;
+    }
+
+    struct cdbres_read_capacity capdata;
+    ret = cdb_read_capacity(&dop, &capdata);
+    if (ret)
+        return ret;
+
+    // READ CAPACITY returns the address of the last block.
+    // We do not bother with READ CAPACITY(16) because BIOS does not support
+    // 64-bit LBA anyway.
+    drive->blksize = be32_to_cpu(capdata.blksize);
+    if (drive->blksize != DISK_SECTOR_SIZE) {
+        dprintf(1, "%s: unsupported block size %d\n", s, drive->blksize);
+        return -1;
+    }
+    drive->sectors = (u64)be32_to_cpu(capdata.sectors) + 1;
+    dprintf(1, "%s blksize=%d sectors=%d\n"
+            , s, drive->blksize, (unsigned)drive->sectors);
+
+    // We do not recover from USB stalls, so try to be safe and avoid
+    // sending the command if the (obsolete, but still provided by QEMU)
+    // fixed disk geometry page may not be supported.
+    //
+    // We could also send the command only to small disks (e.g. <504MiB)
+    // but some old USB keys only support a very small subset of SCSI which
+    // does not even include the MODE SENSE command!
+    //
+    if (CONFIG_QEMU_HARDWARE && memcmp(vendor, "QEMU", 5) == 0) {
+        struct cdbres_mode_sense_geom geomdata;
+        ret = cdb_mode_sense_geom(&dop, &geomdata);
+        if (ret == 0) {
+            u32 cylinders;
+            cylinders = geomdata.cyl[0] << 16;
+            cylinders |= geomdata.cyl[1] << 8;
+            cylinders |= geomdata.cyl[2];
+            if (cylinders && geomdata.heads &&
+                drive->sectors <= 0xFFFFFFFFULL &&
+                ((u32)drive->sectors % (geomdata.heads * cylinders) == 0)) {
+                drive->pchs.cylinders = cylinders;
+                drive->pchs.heads = geomdata.heads;
+                drive->pchs.spt = (u32)drive->sectors / (geomdata.heads * cylinders);
+            }
+        }
+    }
+
+    char *desc = znprintf(MAXDESCSIZE, "%s Drive %s %s %s"
+                          , s, vendor, product, rev);
+    boot_add_hd(drive, desc, prio);
+    return 0;
+}
+
+int
+cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data)
+{
+    struct cdb_request_sense cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = CDB_CMD_INQUIRY;
+    cmd.length = sizeof(*data);
+    op->count = 1;
+    op->buf_fl = data;
+    return cdb_cmd_data(op, &cmd, sizeof(*data));
+}
+
+// Request SENSE
+int
+cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data)
+{
+    struct cdb_request_sense cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = CDB_CMD_REQUEST_SENSE;
+    cmd.length = sizeof(*data);
+    op->count = 1;
+    op->buf_fl = data;
+    return cdb_cmd_data(op, &cmd, sizeof(*data));
+}
+
+// Test unit ready
+int
+cdb_test_unit_ready(struct disk_op_s *op)
+{
+    struct cdb_request_sense cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = CDB_CMD_TEST_UNIT_READY;
+    op->count = 0;
+    op->buf_fl = NULL;
+    return cdb_cmd_data(op, &cmd, 0);
+}
+
+// Request capacity
+int
+cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data)
+{
+    struct cdb_read_capacity cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = CDB_CMD_READ_CAPACITY;
+    op->count = 1;
+    op->buf_fl = data;
+    return cdb_cmd_data(op, &cmd, sizeof(*data));
+}
+
+// Mode sense, geometry page.
+int
+cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data)
+{
+    struct cdb_mode_sense cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = CDB_CMD_MODE_SENSE;
+    cmd.flags = 8; /* DBD */
+    cmd.page = MODE_PAGE_HD_GEOMETRY;
+    cmd.count = cpu_to_be16(sizeof(*data));
+    op->count = 1;
+    op->buf_fl = data;
+    return cdb_cmd_data(op, &cmd, sizeof(*data));
+}
+
+// Read sectors.
+int
+cdb_read(struct disk_op_s *op)
+{
+    struct cdb_rwdata_10 cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = CDB_CMD_READ_10;
+    cmd.lba = cpu_to_be32(op->lba);
+    cmd.count = cpu_to_be16(op->count);
+    return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
+}
+
+// Write sectors.
+int
+cdb_write(struct disk_op_s *op)
+{
+    struct cdb_rwdata_10 cmd;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.command = CDB_CMD_WRITE_10;
+    cmd.lba = cpu_to_be32(op->lba);
+    cmd.count = cpu_to_be16(op->count);
+    return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
+}
diff --git a/src/hw/blockcmd.h b/src/hw/blockcmd.h
new file mode 100644 (file)
index 0000000..8bacfcf
--- /dev/null
@@ -0,0 +1,118 @@
+// Definitions for SCSI style command data blocks.
+#ifndef __BLOCKCMD_H
+#define __BLOCKCMD_H
+
+#include "types.h" // u8
+
+#define CDB_CMD_READ_10 0x28
+#define CDB_CMD_VERIFY_10 0x2f
+#define CDB_CMD_WRITE_10 0x2a
+
+struct cdb_rwdata_10 {
+    u8 command;
+    u8 flags;
+    u32 lba;
+    u8 resreved_06;
+    u16 count;
+    u8 reserved_09;
+    u8 pad[6];
+} PACKED;
+
+#define CDB_CMD_READ_CAPACITY 0x25
+
+struct cdb_read_capacity {
+    u8 command;
+    u8 flags;
+    u8 resreved_02[8];
+    u8 pad[6];
+} PACKED;
+
+struct cdbres_read_capacity {
+    u32 sectors;
+    u32 blksize;
+} PACKED;
+
+#define CDB_CMD_TEST_UNIT_READY  0x00
+#define CDB_CMD_INQUIRY          0x12
+#define CDB_CMD_REQUEST_SENSE    0x03
+
+struct cdb_request_sense {
+    u8 command;
+    u8 flags;
+    u16 reserved_02;
+    u8 length;
+    u8 reserved_05;
+    u8 pad[10];
+} PACKED;
+
+struct cdbres_request_sense {
+    u8 errcode;
+    u8 segment;
+    u8 flags;
+    u32 info;
+    u8 additional;
+    u32 specific;
+    u8 asc;
+    u8 ascq;
+    u32 reserved_0e;
+} PACKED;
+
+#define SCSI_TYPE_DISK  0x00
+#define SCSI_TYPE_CDROM 0x05
+
+struct cdbres_inquiry {
+    u8 pdt;
+    u8 removable;
+    u8 reserved_02[2];
+    u8 additional;
+    u8 reserved_05[3];
+    char vendor[8];
+    char product[16];
+    char rev[4];
+} PACKED;
+
+#define CDB_CMD_MODE_SENSE    0x5A
+#define MODE_PAGE_HD_GEOMETRY 0x04
+
+struct cdb_mode_sense {
+    u8 command;
+    u8 flags;
+    u8 page;
+    u32 reserved_03;
+    u16 count;
+    u8 reserved_09;
+    u8 pad[6];
+} PACKED;
+
+struct cdbres_mode_sense_geom {
+    u8 unused_00[3];
+    u8 read_only;
+    u32 unused_04;
+    u8 page;
+    u8 length;
+    u8 cyl[3];
+    u8 heads;
+    u8 precomp[3];
+    u8 reduced[3];
+    u16 step_rate;
+    u8 landing[3];
+    u16 rpm;
+} PACKED;
+
+// blockcmd.c
+int cdb_is_read(u8 *cdbcmd, u16 blocksize);
+struct disk_op_s;
+int cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data);
+int cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data);
+int cdb_test_unit_ready(struct disk_op_s *op);
+int cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data);
+int cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data);
+int cdb_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data);
+int cdb_read(struct disk_op_s *op);
+int cdb_write(struct disk_op_s *op);
+
+int scsi_is_ready(struct disk_op_s *op);
+struct drive_s;
+int scsi_drive_setup(struct drive_s *drive, const char *s, int prio);
+
+#endif // blockcmd.h
diff --git a/src/hw/cmos.h b/src/hw/cmos.h
new file mode 100644 (file)
index 0000000..067c7fa
--- /dev/null
@@ -0,0 +1,78 @@
+// Definitions for X86 CMOS non-volatile memory access.
+//
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+#ifndef __CMOS_H
+#define __CMOS_H
+
+// Standard BIOS RTC chip entries
+#define CMOS_RTC_SECONDS         0x00
+#define CMOS_RTC_SECONDS_ALARM   0x01
+#define CMOS_RTC_MINUTES         0x02
+#define CMOS_RTC_MINUTES_ALARM   0x03
+#define CMOS_RTC_HOURS           0x04
+#define CMOS_RTC_HOURS_ALARM     0x05
+#define CMOS_RTC_DAY_WEEK        0x06
+#define CMOS_RTC_DAY_MONTH       0x07
+#define CMOS_RTC_MONTH           0x08
+#define CMOS_RTC_YEAR            0x09
+#define CMOS_STATUS_A            0x0a
+#define CMOS_STATUS_B            0x0b
+#define CMOS_STATUS_C            0x0c
+#define CMOS_STATUS_D            0x0d
+#define CMOS_RESET_CODE          0x0f
+
+// QEMU cmos config fields.  DO NOT ADD MORE.  (All new content should
+// be passed via the fw_cfg "file" interface.)
+#define CMOS_FLOPPY_DRIVE_TYPE   0x10
+#define CMOS_DISK_DATA           0x12
+#define CMOS_EQUIPMENT_INFO      0x14
+#define CMOS_DISK_DRIVE1_TYPE    0x19
+#define CMOS_DISK_DRIVE2_TYPE    0x1a
+#define CMOS_DISK_DRIVE1_CYL     0x1b
+#define CMOS_DISK_DRIVE2_CYL     0x24
+#define CMOS_MEM_EXTMEM_LOW      0x30
+#define CMOS_MEM_EXTMEM_HIGH     0x31
+#define CMOS_CENTURY             0x32
+#define CMOS_MEM_EXTMEM2_LOW     0x34
+#define CMOS_MEM_EXTMEM2_HIGH    0x35
+#define CMOS_BIOS_BOOTFLAG1      0x38
+#define CMOS_BIOS_DISKTRANSFLAG  0x39
+#define CMOS_BIOS_BOOTFLAG2      0x3d
+#define CMOS_MEM_HIGHMEM_LOW     0x5b
+#define CMOS_MEM_HIGHMEM_MID     0x5c
+#define CMOS_MEM_HIGHMEM_HIGH    0x5d
+#define CMOS_BIOS_SMP_COUNT      0x5f
+
+// CMOS_FLOPPY_DRIVE_TYPE bitdefs
+#define CFD_NO_DRIVE 0
+#define CFD_360KB    1
+#define CFD_12MB     2
+#define CFD_720KB    3
+#define CFD_144MB    4
+#define CFD_288MB    5
+
+#ifndef __ASSEMBLY__
+
+#include "ioport.h" // inb, outb
+
+static inline u8
+inb_cmos(u8 reg)
+{
+    reg |= NMI_DISABLE_BIT;
+    outb(reg, PORT_CMOS_INDEX);
+    return inb(PORT_CMOS_DATA);
+}
+
+static inline void
+outb_cmos(u8 val, u8 reg)
+{
+    reg |= NMI_DISABLE_BIT;
+    outb(reg, PORT_CMOS_INDEX);
+    outb(val, PORT_CMOS_DATA);
+}
+
+#endif // !__ASSEMBLY__
+
+#endif // cmos.h
diff --git a/src/hw/esp-scsi.c b/src/hw/esp-scsi.c
new file mode 100644 (file)
index 0000000..fe70366
--- /dev/null
@@ -0,0 +1,234 @@
+// AMD PCscsi boot support.
+//
+// Copyright (C) 2012 Red Hat Inc.
+//
+// Authors:
+//  Paolo Bonzini <pbonzini@redhat.com>
+//
+// based on lsi-scsi.c which is written by:
+//  Gerd Hoffman <kraxel@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+#include "pci_ids.h" // PCI_DEVICE_ID
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "boot.h" // bootprio_find_scsi_device
+#include "blockcmd.h" // scsi_drive_setup
+#include "paravirt.h" // runningOnQEMU
+#include "disk.h"
+
+#define ESP_TCLO      0x00
+#define ESP_TCMID     0x04
+#define ESP_FIFO      0x08
+#define ESP_CMD       0x0c
+#define ESP_WBUSID    0x10
+#define ESP_TCHI      0x38
+
+#define ESP_RSTAT     0x10
+#define ESP_RINTR     0x14
+#define ESP_RFLAGS    0x1c
+
+#define ESP_DMA_CMD   0x40
+#define ESP_DMA_STC   0x44
+#define ESP_DMA_SPA   0x48
+#define ESP_DMA_WBC   0x4c
+#define ESP_DMA_WAC   0x50
+#define ESP_DMA_STAT  0x54
+#define ESP_DMA_SMDLA 0x58
+#define ESP_DMA_WMAC  0x58c
+
+#define ESP_CMD_DMA      0x80
+#define ESP_CMD_RESET    0x02
+#define ESP_CMD_TI       0x10
+#define ESP_CMD_ICCS     0x11
+#define ESP_CMD_SELATN   0x42
+
+#define ESP_STAT_DI      0x01
+#define ESP_STAT_CD      0x02
+#define ESP_STAT_MSG     0x04
+#define ESP_STAT_TC      0x10
+
+#define ESP_INTR_DC      0x20
+
+struct esp_lun_s {
+    struct drive_s drive;
+    struct pci_device *pci;
+    u32 iobase;
+    u8 target;
+    u8 lun;
+};
+
+static void
+esp_scsi_dma(u32 iobase, u32 buf, u32 len, int read)
+{
+    outb(len         & 0xff, iobase + ESP_TCLO);
+    outb((len >> 8)  & 0xff, iobase + ESP_TCMID);
+    outb((len >> 16) & 0xff, iobase + ESP_TCHI);
+    outl(buf,                iobase + ESP_DMA_SPA);
+    outl(len,                iobase + ESP_DMA_STC);
+    outb(read ? 0x83 : 0x03, iobase + ESP_DMA_CMD);
+}
+
+static int
+esp_scsi_cmd(struct esp_lun_s *llun, struct disk_op_s *op,
+             u8 *cdbcmd, u16 target, u16 lun, u16 blocksize)
+{
+    u32 iobase = GET_GLOBAL(llun->iobase);
+    int i, state;
+    u8 status;
+
+    outb(target, iobase + ESP_WBUSID);
+
+    /*
+     * We need to pass the LUN at the beginning of the command, and the FIFO
+     * is only 16 bytes, so we cannot support 16-byte CDBs.  The alternative
+     * would be to use DMA for the 17-byte command too, which is quite
+     * overkill.
+     */
+    outb(lun, iobase + ESP_FIFO);
+    cdbcmd[1] &= 0x1f;
+    cdbcmd[1] |= lun << 5;
+    for (i = 0; i < 12; i++)
+        outb(cdbcmd[i], iobase + ESP_FIFO);
+    outb(ESP_CMD_SELATN, iobase + ESP_CMD);
+
+    for (state = 0;;) {
+        u8 stat = inb(iobase + ESP_RSTAT);
+
+        /* Detect disconnected device.  */
+        if (state == 0 && (inb(iobase + ESP_RINTR) & ESP_INTR_DC)) {
+            return DISK_RET_ENOTREADY;
+        }
+
+        /* HBA reads command, clears CD, sets TC -> do DMA if needed.  */
+        if (state == 0 && (stat & ESP_STAT_TC)) {
+            state++;
+            if (op->count && blocksize) {
+                /* Data phase.  */
+                u32 count = (u32)op->count * blocksize;
+                esp_scsi_dma(iobase, (u32)op->buf_fl, count,
+                             cdb_is_read(cdbcmd, blocksize));
+                outb(ESP_CMD_TI | ESP_CMD_DMA, iobase + ESP_CMD);
+                continue;
+            }
+        }
+
+       /* At end of DMA TC is set again -> complete command.  */
+        if (state == 1 && (stat & ESP_STAT_TC)) {
+            state++;
+            outb(ESP_CMD_ICCS, iobase + ESP_CMD);
+            continue;
+        }
+
+       /* Finally read data from the message in phase.  */
+        if (state == 2 && (stat & ESP_STAT_MSG)) {
+            state++;
+            status = inb(iobase + ESP_FIFO);
+            inb(iobase + ESP_FIFO);
+            break;
+        }
+        usleep(5);
+    }
+
+    if (status == 0) {
+        return DISK_RET_SUCCESS;
+    }
+
+    return DISK_RET_EBADTRACK;
+}
+
+int
+esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    if (!CONFIG_ESP_SCSI)
+        return DISK_RET_EBADTRACK;
+
+    struct esp_lun_s *llun =
+        container_of(op->drive_g, struct esp_lun_s, drive);
+
+    return esp_scsi_cmd(llun, op, cdbcmd,
+                        GET_GLOBAL(llun->target), GET_GLOBAL(llun->lun),
+                        blocksize);
+}
+
+static int
+esp_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
+{
+    struct esp_lun_s *llun = malloc_fseg(sizeof(*llun));
+    if (!llun) {
+        warn_noalloc();
+        return -1;
+    }
+    memset(llun, 0, sizeof(*llun));
+    llun->drive.type = DTYPE_ESP_SCSI;
+    llun->drive.cntl_id = pci->bdf;
+    llun->pci = pci;
+    llun->target = target;
+    llun->lun = lun;
+    llun->iobase = iobase;
+
+    char *name = znprintf(16, "esp %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(&llun->drive, name, prio);
+    free(name);
+    if (ret)
+        goto fail;
+    return 0;
+
+fail:
+    free(llun);
+    return -1;
+}
+
+static void
+esp_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target)
+{
+    esp_scsi_add_lun(pci, iobase, target, 0);
+}
+
+static void
+init_esp_scsi(struct pci_device *pci)
+{
+    u16 bdf = pci->bdf;
+    u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
+        & PCI_BASE_ADDRESS_IO_MASK;
+
+    dprintf(1, "found esp at %02x:%02x.%x, io @ %x\n",
+            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
+            pci_bdf_to_fn(bdf), iobase);
+
+    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
+
+    // reset
+    outb(ESP_CMD_RESET, iobase + ESP_CMD);
+
+    int i;
+    for (i = 0; i <= 7; i++)
+        esp_scsi_scan_target(pci, iobase, i);
+
+    return;
+}
+
+void
+esp_scsi_setup(void)
+{
+    ASSERT32FLAT();
+    if (!CONFIG_ESP_SCSI || !runningOnQEMU())
+        return;
+
+    dprintf(3, "init esp\n");
+
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci->vendor != PCI_VENDOR_ID_AMD
+            || pci->device != PCI_DEVICE_ID_AMD_SCSI)
+            continue;
+        init_esp_scsi(pci);
+    }
+}
diff --git a/src/hw/esp-scsi.h b/src/hw/esp-scsi.h
new file mode 100644 (file)
index 0000000..dc555f3
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __ESP_SCSI_H
+#define __ESP_SCSI_H
+
+struct disk_op_s;
+int esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+void esp_scsi_setup(void);
+
+#endif /* __ESP_SCSI_H */
diff --git a/src/hw/floppy.c b/src/hw/floppy.c
new file mode 100644 (file)
index 0000000..37b7092
--- /dev/null
@@ -0,0 +1,701 @@
+// 16bit code to access floppy drives.
+//
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "types.h" // u8
+#include "disk.h" // DISK_RET_SUCCESS
+#include "config.h" // CONFIG_FLOPPY
+#include "biosvar.h" // SET_BDA
+#include "util.h" // dprintf
+#include "cmos.h" // inb_cmos
+#include "pic.h" // pic_eoi1
+#include "bregs.h" // struct bregs
+#include "boot.h" // boot_add_floppy
+#include "pci.h" // pci_to_bdf
+#include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA
+
+#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors
+#define FLOPPY_DATALEN 0xff   // Not used - because size code is 0x02
+#define FLOPPY_MOTOR_TICKS 37 // ~2 seconds
+#define FLOPPY_FILLBYTE 0xf6
+#define FLOPPY_GAPLEN 0x1B
+#define FLOPPY_FORMAT_GAPLEN 0x6c
+#define FLOPPY_PIO_TIMEOUT 1000
+
+// New diskette parameter table adding 3 parameters from IBM
+// Since no provisions are made for multiple drive types, most
+// values in this table are ignored.  I set parameters for 1.44M
+// floppy here
+struct floppy_ext_dbt_s diskette_param_table2 VARFSEG = {
+    .dbt = {
+        .specify1       = 0xAF, // step rate 12ms, head unload 240ms
+        .specify2       = 0x02, // head load time 4ms, DMA used
+        .shutoff_ticks  = FLOPPY_MOTOR_TICKS, // ~2 seconds
+        .bps_code       = FLOPPY_SIZE_CODE,
+        .sectors        = 18,
+        .interblock_len = FLOPPY_GAPLEN,
+        .data_len       = FLOPPY_DATALEN,
+        .gap_len        = FLOPPY_FORMAT_GAPLEN,
+        .fill_byte      = FLOPPY_FILLBYTE,
+        .settle_time    = 0x0F, // 15ms
+        .startup_time   = 0x08, // 1 second
+    },
+    .max_track      = 79,   // maximum track
+    .data_rate      = 0,    // data transfer rate
+    .drive_type     = 4,    // drive type in cmos
+};
+
+struct floppy_dbt_s diskette_param_table VAR16FIXED(0xefc7);
+
+struct floppyinfo_s {
+    struct chs_s chs;
+    u8 floppy_size;
+    u8 data_rate;
+};
+
+#define FLOPPY_SIZE_525 0x01
+#define FLOPPY_SIZE_350 0x02
+
+#define FLOPPY_RATE_500K 0x00
+#define FLOPPY_RATE_300K 0x01
+#define FLOPPY_RATE_250K 0x02
+#define FLOPPY_RATE_1M   0x03
+
+struct floppyinfo_s FloppyInfo[] VARFSEG = {
+    // Unknown
+    { {0, 0, 0}, 0x00, 0x00},
+    // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors
+    { {2, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K},
+    // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors
+    { {2, 80, 15}, FLOPPY_SIZE_525, FLOPPY_RATE_500K},
+    // 3 - 720KB, 3.5"  - 2 heads, 80 tracks, 9 sectors
+    { {2, 80, 9}, FLOPPY_SIZE_350, FLOPPY_RATE_250K},
+    // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors
+    { {2, 80, 18}, FLOPPY_SIZE_350, FLOPPY_RATE_500K},
+    // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors
+    { {2, 80, 36}, FLOPPY_SIZE_350, FLOPPY_RATE_1M},
+    // 6 - 160k, 5.25"  - 1 heads, 40 tracks, 8 sectors
+    { {1, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K},
+    // 7 - 180k, 5.25"  - 1 heads, 40 tracks, 9 sectors
+    { {1, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K},
+    // 8 - 320k, 5.25"  - 2 heads, 40 tracks, 8 sectors
+    { {2, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K},
+};
+
+struct drive_s *
+init_floppy(int floppyid, int ftype)
+{
+    if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) {
+        dprintf(1, "Bad floppy type %d\n", ftype);
+        return NULL;
+    }
+
+    struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
+    if (!drive_g) {
+        warn_noalloc();
+        return NULL;
+    }
+    memset(drive_g, 0, sizeof(*drive_g));
+    drive_g->cntl_id = floppyid;
+    drive_g->type = DTYPE_FLOPPY;
+    drive_g->blksize = DISK_SECTOR_SIZE;
+    drive_g->floppy_type = ftype;
+    drive_g->sectors = (u64)-1;
+
+    memcpy(&drive_g->lchs, &FloppyInfo[ftype].chs
+           , sizeof(FloppyInfo[ftype].chs));
+    return drive_g;
+}
+
+static void
+addFloppy(int floppyid, int ftype)
+{
+    struct drive_s *drive_g = init_floppy(floppyid, ftype);
+    if (!drive_g)
+        return;
+    char *desc = znprintf(MAXDESCSIZE, "Floppy [drive %c]", 'A' + floppyid);
+    struct pci_device *pci = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */
+    int prio = bootprio_find_fdc_device(pci, PORT_FD_BASE, floppyid);
+    boot_add_floppy(drive_g, desc, prio);
+}
+
+void
+floppy_setup(void)
+{
+    memcpy(&diskette_param_table, &diskette_param_table2
+           , sizeof(diskette_param_table));
+    SET_IVT(0x1E, SEGOFF(SEG_BIOS
+                         , (u32)&diskette_param_table2 - BUILD_BIOS_ADDR));
+
+    if (! CONFIG_FLOPPY)
+        return;
+    dprintf(3, "init floppy drives\n");
+
+    if (CONFIG_QEMU) {
+        u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE);
+        if (type & 0xf0)
+            addFloppy(0, type >> 4);
+        if (type & 0x0f)
+            addFloppy(1, type & 0x0f);
+    } else {
+        u8 type = romfile_loadint("etc/floppy0", 0);
+        if (type)
+            addFloppy(0, type);
+        type = romfile_loadint("etc/floppy1", 0);
+        if (type)
+            addFloppy(1, type);
+    }
+
+    outb(0x02, PORT_DMA1_MASK_REG);
+
+    enable_hwirq(6, FUNC16(entry_0e));
+}
+
+// Find a floppy type that matches a given image size.
+int
+find_floppy_type(u32 size)
+{
+    int i;
+    for (i=1; i<ARRAY_SIZE(FloppyInfo); i++) {
+        struct chs_s *c = &FloppyInfo[i].chs;
+        if (c->cylinders * c->heads * c->spt * DISK_SECTOR_SIZE == size)
+            return i;
+    }
+    return -1;
+}
+
+
+/****************************************************************
+ * Low-level floppy IO
+ ****************************************************************/
+
+static void
+floppy_disable_controller(void)
+{
+    outb(inb(PORT_FD_DOR) & ~0x04, PORT_FD_DOR);
+}
+
+static int
+floppy_wait_irq(void)
+{
+    u8 frs = GET_BDA(floppy_recalibration_status);
+    SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ);
+    for (;;) {
+        if (!GET_BDA(floppy_motor_counter)) {
+            floppy_disable_controller();
+            return DISK_RET_ETIMEOUT;
+        }
+        frs = GET_BDA(floppy_recalibration_status);
+        if (frs & FRS_IRQ)
+            break;
+        // Could use yield_toirq() here, but that causes issues on
+        // bochs, so use yield() instead.
+        yield();
+    }
+
+    SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ);
+    return DISK_RET_SUCCESS;
+}
+
+struct floppy_pio_s {
+    u8 cmdlen;
+    u8 resplen;
+    u8 waitirq;
+    u8 data[9];
+};
+
+static int
+floppy_pio(struct floppy_pio_s *pio)
+{
+    // Send command to controller.
+    u32 end = timer_calc(FLOPPY_PIO_TIMEOUT);
+    int i = 0;
+    for (;;) {
+        u8 sts = inb(PORT_FD_STATUS);
+        if (!(sts & 0x80)) {
+            if (timer_check(end)) {
+                floppy_disable_controller();
+                return DISK_RET_ETIMEOUT;
+            }
+            continue;
+        }
+        if (sts & 0x40) {
+            floppy_disable_controller();
+            return DISK_RET_ECONTROLLER;
+        }
+        outb(pio->data[i++], PORT_FD_DATA);
+        if (i >= pio->cmdlen)
+            break;
+    }
+
+    // Wait for command to complete.
+    if (pio->waitirq) {
+        int ret = floppy_wait_irq();
+        if (ret)
+            return ret;
+    }
+
+    // Read response from controller.
+    end = timer_calc(FLOPPY_PIO_TIMEOUT);
+    i = 0;
+    for (;;) {
+        u8 sts = inb(PORT_FD_STATUS);
+        if (!(sts & 0x80)) {
+            if (timer_check(end)) {
+                floppy_disable_controller();
+                return DISK_RET_ETIMEOUT;
+            }
+            continue;
+        }
+        if (i >= pio->resplen)
+            break;
+        if (!(sts & 0x40)) {
+            floppy_disable_controller();
+            return DISK_RET_ECONTROLLER;
+        }
+        pio->data[i++] = inb(PORT_FD_DATA);
+    }
+
+    return DISK_RET_SUCCESS;
+}
+
+static int
+floppy_enable_controller(void)
+{
+    outb(inb(PORT_FD_DOR) | 0x04, PORT_FD_DOR);
+    int ret = floppy_wait_irq();
+    if (ret)
+        return ret;
+
+    struct floppy_pio_s pio;
+    pio.cmdlen = 1;
+    pio.resplen = 2;
+    pio.waitirq = 0;
+    pio.data[0] = 0x08;  // 08: Check Interrupt Status
+    return floppy_pio(&pio);
+}
+
+static int
+floppy_select_drive(u8 floppyid)
+{
+    // reset the disk motor timeout value of INT 08
+    SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS);
+
+    // Enable controller if it isn't running.
+    u8 dor = inb(PORT_FD_DOR);
+    if (!(dor & 0x04)) {
+        int ret = floppy_enable_controller();
+        if (ret)
+            return ret;
+    }
+
+    // Turn on motor of selected drive, DMA & int enabled, normal operation
+    dor = (floppyid ? 0x20 : 0x10) | 0x0c | floppyid;
+    outb(dor, PORT_FD_DOR);
+
+    return DISK_RET_SUCCESS;
+}
+
+
+/****************************************************************
+ * Floppy media sense
+ ****************************************************************/
+
+static inline void
+set_diskette_current_cyl(u8 floppyid, u8 cyl)
+{
+    SET_BDA(floppy_track[floppyid], cyl);
+}
+
+static int
+floppy_drive_recal(u8 floppyid)
+{
+    int ret = floppy_select_drive(floppyid);
+    if (ret)
+        return ret;
+
+    // send Recalibrate command (2 bytes) to controller
+    struct floppy_pio_s pio;
+    pio.cmdlen = 2;
+    pio.resplen = 0;
+    pio.waitirq = 1;
+    pio.data[0] = 0x07;  // 07: Recalibrate
+    pio.data[1] = floppyid; // 0=drive0, 1=drive1
+    ret = floppy_pio(&pio);
+    if (ret)
+        return ret;
+
+    pio.cmdlen = 1;
+    pio.resplen = 2;
+    pio.waitirq = 0;
+    pio.data[0] = 0x08;  // 08: Check Interrupt Status
+    ret = floppy_pio(&pio);
+    if (ret)
+        return ret;
+
+    u8 frs = GET_BDA(floppy_recalibration_status);
+    SET_BDA(floppy_recalibration_status, frs | (1<<floppyid));
+    set_diskette_current_cyl(floppyid, 0);
+    return DISK_RET_SUCCESS;
+}
+
+static int
+floppy_drive_readid(u8 floppyid, u8 data_rate, u8 head)
+{
+    int ret = floppy_select_drive(floppyid);
+    if (ret)
+        return ret;
+
+    // Set data rate.
+    outb(data_rate, PORT_FD_DIR);
+
+    // send Read Sector Id command
+    struct floppy_pio_s pio;
+    pio.cmdlen = 2;
+    pio.resplen = 7;
+    pio.waitirq = 1;
+    pio.data[0] = 0x4a;  // 0a: Read Sector Id
+    pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
+    ret = floppy_pio(&pio);
+    if (ret)
+        return ret;
+    if (pio.data[0] & 0xc0)
+        return -1;
+    return 0;
+}
+
+static int
+floppy_media_sense(struct drive_s *drive_g)
+{
+    u8 ftype = GET_GLOBAL(drive_g->floppy_type), stype = ftype;
+    u8 floppyid = GET_GLOBAL(drive_g->cntl_id);
+
+    u8 data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate);
+    int ret = floppy_drive_readid(floppyid, data_rate, 0);
+    if (ret) {
+        // Attempt media sense.
+        for (stype=1; ; stype++) {
+            if (stype >= ARRAY_SIZE(FloppyInfo))
+                return DISK_RET_EMEDIA;
+            if (stype==ftype
+                || (GET_GLOBAL(FloppyInfo[stype].floppy_size)
+                    != GET_GLOBAL(FloppyInfo[ftype].floppy_size))
+                || (GET_GLOBAL(FloppyInfo[stype].chs.heads)
+                    > GET_GLOBAL(FloppyInfo[ftype].chs.heads))
+                || (GET_GLOBAL(FloppyInfo[stype].chs.cylinders)
+                    > GET_GLOBAL(FloppyInfo[ftype].chs.cylinders))
+                || (GET_GLOBAL(FloppyInfo[stype].chs.spt)
+                    > GET_GLOBAL(FloppyInfo[ftype].chs.spt)))
+                continue;
+            data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate);
+            ret = floppy_drive_readid(floppyid, data_rate, 0);
+            if (!ret)
+                break;
+        }
+    }
+
+    u8 old_data_rate = GET_BDA(floppy_media_state[floppyid]) >> 6;
+    SET_BDA(floppy_last_data_rate, (old_data_rate<<2) | (data_rate<<6));
+    u8 media = (stype == 1 ? 0x04 : (stype == 2 ? 0x05 : 0x07));
+    u8 fms = (data_rate<<6) | FMS_MEDIA_DRIVE_ESTABLISHED | media;
+    if (GET_GLOBAL(FloppyInfo[stype].chs.cylinders)
+        < GET_GLOBAL(FloppyInfo[ftype].chs.cylinders))
+        fms |= FMS_DOUBLE_STEPPING;
+    SET_BDA(floppy_media_state[floppyid], fms);
+
+    return DISK_RET_SUCCESS;
+}
+
+static int
+check_recal_drive(struct drive_s *drive_g)
+{
+    u8 floppyid = GET_GLOBAL(drive_g->cntl_id);
+    if ((GET_BDA(floppy_recalibration_status) & (1<<floppyid))
+        && (GET_BDA(floppy_media_state[floppyid]) & FMS_MEDIA_DRIVE_ESTABLISHED))
+        // Media is known.
+        return DISK_RET_SUCCESS;
+
+    // Recalibrate drive.
+    int ret = floppy_drive_recal(floppyid);
+    if (ret)
+        return ret;
+
+    // Sense media.
+    return floppy_media_sense(drive_g);
+}
+
+
+/****************************************************************
+ * Floppy DMA
+ ****************************************************************/
+
+// Perform a floppy transfer command (setup DMA and issue PIO).
+static int
+floppy_cmd(struct disk_op_s *op, int blocksize, struct floppy_pio_s *pio)
+{
+    int ret = check_recal_drive(op->drive_g);
+    if (ret)
+        return ret;
+
+    // es:bx = pointer to where to place information from diskette
+    u32 addr = (u32)op->buf_fl;
+    int count = op->count * blocksize;
+
+    // check for 64K boundary overrun
+    u16 end = count - 1;
+    u32 last_addr = addr + end;
+    if ((addr >> 16) != (last_addr >> 16))
+        return DISK_RET_EBOUNDARY;
+
+    u8 mode_register = 0x4a; // single mode, increment, autoinit disable,
+    if (pio->data[0] == 0xe6)
+        // read
+        mode_register = 0x46;
+
+    //DEBUGF("floppy dma c2\n");
+    outb(0x06, PORT_DMA1_MASK_REG);
+    outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
+    outb(addr, PORT_DMA_ADDR_2);
+    outb(addr>>8, PORT_DMA_ADDR_2);
+    outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
+    outb(end, PORT_DMA_CNT_2);
+    outb(end>>8, PORT_DMA_CNT_2);
+
+    // port 0b: DMA-1 Mode Register
+    // transfer type=write, channel 2
+    outb(mode_register, PORT_DMA1_MODE_REG);
+
+    // port 81: DMA-1 Page Register, channel 2
+    outb(addr>>16, PORT_DMA_PAGE_2);
+
+    outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2
+
+    ret = floppy_select_drive(pio->data[1] & 1);
+    if (ret)
+        return ret;
+    pio->resplen = 7;
+    pio->waitirq = 1;
+    ret = floppy_pio(pio);
+    if (ret)
+        return ret;
+
+    // Populate floppy_return_status in BDA
+    int i;
+    for (i=0; i<7; i++)
+        SET_BDA(floppy_return_status[i], pio->data[i]);
+
+    if (pio->data[0] & 0xc0) {
+        if (pio->data[1] & 0x02)
+            return DISK_RET_EWRITEPROTECT;
+        dprintf(1, "floppy error: %02x %02x %02x %02x %02x %02x %02x\n"
+                , pio->data[0], pio->data[1], pio->data[2], pio->data[3]
+                , pio->data[4], pio->data[5], pio->data[6]);
+        return DISK_RET_ECONTROLLER;
+    }
+
+    u8 track = (pio->cmdlen == 9 ? pio->data[3] : 0);
+    set_diskette_current_cyl(pio->data[0] & 1, track);
+
+    return DISK_RET_SUCCESS;
+}
+
+
+/****************************************************************
+ * Floppy handlers
+ ****************************************************************/
+
+static void
+lba2chs(struct disk_op_s *op, u8 *track, u8 *sector, u8 *head)
+{
+    u32 lba = op->lba;
+
+    u32 tmp = lba + 1;
+    u16 nlspt = GET_GLOBAL(op->drive_g->lchs.spt);
+    *sector = tmp % nlspt;
+
+    tmp /= nlspt;
+    u16 nlh = GET_GLOBAL(op->drive_g->lchs.heads);
+    *head = tmp % nlh;
+
+    tmp /= nlh;
+    *track = tmp;
+}
+
+// diskette controller reset
+static int
+floppy_reset(struct disk_op_s *op)
+{
+    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
+    SET_BDA(floppy_recalibration_status, 0);
+    SET_BDA(floppy_media_state[0], 0);
+    SET_BDA(floppy_media_state[1], 0);
+    SET_BDA(floppy_track[0], 0);
+    SET_BDA(floppy_track[1], 0);
+    SET_BDA(floppy_last_data_rate, 0);
+    floppy_disable_controller();
+    return floppy_select_drive(floppyid);
+}
+
+// Read Diskette Sectors
+static int
+floppy_read(struct disk_op_s *op)
+{
+    u8 track, sector, head;
+    lba2chs(op, &track, &sector, &head);
+
+    // send read-normal-data command (9 bytes) to controller
+    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
+    struct floppy_pio_s pio;
+    pio.cmdlen = 9;
+    pio.data[0] = 0xe6; // e6: read normal data
+    pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
+    pio.data[2] = track;
+    pio.data[3] = head;
+    pio.data[4] = sector;
+    pio.data[5] = FLOPPY_SIZE_CODE;
+    pio.data[6] = sector + op->count - 1; // last sector to read on track
+    pio.data[7] = FLOPPY_GAPLEN;
+    pio.data[8] = FLOPPY_DATALEN;
+
+    int res = floppy_cmd(op, DISK_SECTOR_SIZE, &pio);
+    if (res)
+        goto fail;
+    return DISK_RET_SUCCESS;
+fail:
+    op->count = 0; // no sectors read
+    return res;
+}
+
+// Write Diskette Sectors
+static int
+floppy_write(struct disk_op_s *op)
+{
+    u8 track, sector, head;
+    lba2chs(op, &track, &sector, &head);
+
+    // send write-normal-data command (9 bytes) to controller
+    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
+    struct floppy_pio_s pio;
+    pio.cmdlen = 9;
+    pio.data[0] = 0xc5; // c5: write normal data
+    pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
+    pio.data[2] = track;
+    pio.data[3] = head;
+    pio.data[4] = sector;
+    pio.data[5] = FLOPPY_SIZE_CODE;
+    pio.data[6] = sector + op->count - 1; // last sector to write on track
+    pio.data[7] = FLOPPY_GAPLEN;
+    pio.data[8] = FLOPPY_DATALEN;
+
+    int res = floppy_cmd(op, DISK_SECTOR_SIZE, &pio);
+    if (res)
+        goto fail;
+    return DISK_RET_SUCCESS;
+fail:
+    op->count = 0; // no sectors read
+    return res;
+}
+
+// Verify Diskette Sectors
+static int
+floppy_verify(struct disk_op_s *op)
+{
+    int res = check_recal_drive(op->drive_g);
+    if (res)
+        goto fail;
+
+    u8 track, sector, head;
+    lba2chs(op, &track, &sector, &head);
+
+    // ??? should track be new val from return_status[3] ?
+    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
+    set_diskette_current_cyl(floppyid, track);
+    return DISK_RET_SUCCESS;
+fail:
+    op->count = 0; // no sectors read
+    return res;
+}
+
+// format diskette track
+static int
+floppy_format(struct disk_op_s *op)
+{
+    u8 head = op->lba;
+
+    // send format-track command (6 bytes) to controller
+    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
+    struct floppy_pio_s pio;
+    pio.cmdlen = 6;
+    pio.data[0] = 0x4d; // 4d: format track
+    pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
+    pio.data[2] = FLOPPY_SIZE_CODE;
+    pio.data[3] = op->count; // number of sectors per track
+    pio.data[4] = FLOPPY_FORMAT_GAPLEN;
+    pio.data[5] = FLOPPY_FILLBYTE;
+
+    return floppy_cmd(op, 4, &pio);
+}
+
+int
+process_floppy_op(struct disk_op_s *op)
+{
+    if (!CONFIG_FLOPPY)
+        return 0;
+
+    switch (op->command) {
+    case CMD_RESET:
+        return floppy_reset(op);
+    case CMD_READ:
+        return floppy_read(op);
+    case CMD_WRITE:
+        return floppy_write(op);
+    case CMD_VERIFY:
+        return floppy_verify(op);
+    case CMD_FORMAT:
+        return floppy_format(op);
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
+
+
+/****************************************************************
+ * HW irqs
+ ****************************************************************/
+
+// INT 0Eh Diskette Hardware ISR Entry Point
+void VISIBLE16
+handle_0e(void)
+{
+    if (! CONFIG_FLOPPY)
+        return;
+    debug_isr(DEBUG_ISR_0e);
+
+    // diskette interrupt has occurred
+    u8 frs = GET_BDA(floppy_recalibration_status);
+    SET_BDA(floppy_recalibration_status, frs | FRS_IRQ);
+
+    pic_eoi1();
+}
+
+// Called from int08 handler.
+void
+floppy_tick(void)
+{
+    if (! CONFIG_FLOPPY)
+        return;
+
+    // time to turn off drive(s)?
+    u8 fcount = GET_BDA(floppy_motor_counter);
+    if (fcount) {
+        fcount--;
+        SET_BDA(floppy_motor_counter, fcount);
+        if (fcount == 0)
+            // turn motor(s) off
+            outb(inb(PORT_FD_DOR) & 0xcf, PORT_FD_DOR);
+    }
+}
diff --git a/src/hw/lsi-scsi.c b/src/hw/lsi-scsi.c
new file mode 100644 (file)
index 0000000..305610a
--- /dev/null
@@ -0,0 +1,213 @@
+// (qemu-emulated) lsi53c895a boot support.
+//
+// Copyright (C) 2012 Red Hat Inc.
+//
+// Authors:
+//  Gerd Hoffmann <kraxel@redhat.com>
+//
+// based on virtio-scsi.c which is written by:
+//  Paolo Bonzini <pbonzini@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "boot.h" // bootprio_find_scsi_device
+#include "blockcmd.h" // scsi_drive_setup
+#include "paravirt.h" // runningOnQEMU
+#include "disk.h"
+
+#define LSI_REG_DSTAT     0x0c
+#define LSI_REG_ISTAT0    0x14
+#define LSI_REG_DSP0      0x2c
+#define LSI_REG_DSP1      0x2d
+#define LSI_REG_DSP2      0x2e
+#define LSI_REG_DSP3      0x2f
+#define LSI_REG_SIST0     0x42
+#define LSI_REG_SIST1     0x43
+
+#define LSI_ISTAT0_DIP    0x01
+#define LSI_ISTAT0_SIP    0x02
+#define LSI_ISTAT0_INTF   0x04
+#define LSI_ISTAT0_CON    0x08
+#define LSI_ISTAT0_SEM    0x10
+#define LSI_ISTAT0_SIGP   0x20
+#define LSI_ISTAT0_SRST   0x40
+#define LSI_ISTAT0_ABRT   0x80
+
+struct lsi_lun_s {
+    struct drive_s drive;
+    struct pci_device *pci;
+    u32 iobase;
+    u8 target;
+    u8 lun;
+};
+
+static int
+lsi_scsi_cmd(struct lsi_lun_s *llun, struct disk_op_s *op,
+             void *cdbcmd, u16 target, u16 lun, u16 blocksize)
+{
+    u32 iobase = GET_GLOBAL(llun->iobase);
+    u32 dma = ((cdb_is_read(cdbcmd, blocksize) ? 0x01000000 : 0x00000000) |
+               (op->count * blocksize));
+    u8 msgout[] = {
+        0x80 | lun,                 // select lun
+        0x08,
+    };
+    u8 status = 0xff;
+    u8 msgin_tmp[2];
+    u8 msgin = 0xff;
+
+    u32 script[] = {
+        /* select target, send scsi command */
+        0x40000000 | target << 16,  // select target
+        0x00000000,
+        0x06000001,                 // msgout
+        (u32)MAKE_FLATPTR(GET_SEG(SS), &msgout),
+        0x02000010,                 // scsi command
+        (u32)MAKE_FLATPTR(GET_SEG(SS), cdbcmd),
+
+        /* handle disconnect */
+        0x87820000,                 // phase == msgin ?
+        0x00000018,
+        0x07000002,                 // msgin
+        (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin_tmp),
+        0x50000000,                 // re-select
+        0x00000000,
+        0x07000002,                 // msgin
+        (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin_tmp),
+
+        /* dma data, get status, raise irq */
+        dma,                        // dma data
+        (u32)op->buf_fl,
+        0x03000001,                 // status
+        (u32)MAKE_FLATPTR(GET_SEG(SS), &status),
+        0x07000001,                 // msgin
+        (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin),
+        0x98080000,                 // dma irq
+        0x00000000,
+    };
+    u32 dsp = (u32)MAKE_FLATPTR(GET_SEG(SS), &script);
+
+    outb(dsp         & 0xff, iobase + LSI_REG_DSP0);
+    outb((dsp >>  8) & 0xff, iobase + LSI_REG_DSP1);
+    outb((dsp >> 16) & 0xff, iobase + LSI_REG_DSP2);
+    outb((dsp >> 24) & 0xff, iobase + LSI_REG_DSP3);
+
+    for (;;) {
+        u8 dstat = inb(iobase + LSI_REG_DSTAT);
+        u8 sist0 = inb(iobase + LSI_REG_SIST0);
+        u8 sist1 = inb(iobase + LSI_REG_SIST1);
+        if (sist0 || sist1) {
+            goto fail;
+        }
+        if (dstat & 0x04) {
+            break;
+        }
+        usleep(5);
+    }
+
+    if (msgin == 0 && status == 0) {
+        return DISK_RET_SUCCESS;
+    }
+
+fail:
+    return DISK_RET_EBADTRACK;
+}
+
+int
+lsi_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    if (!CONFIG_LSI_SCSI)
+        return DISK_RET_EBADTRACK;
+
+    struct lsi_lun_s *llun =
+        container_of(op->drive_g, struct lsi_lun_s, drive);
+
+    return lsi_scsi_cmd(llun, op, cdbcmd,
+                        GET_GLOBAL(llun->target), GET_GLOBAL(llun->lun),
+                        blocksize);
+}
+
+static int
+lsi_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
+{
+    struct lsi_lun_s *llun = malloc_fseg(sizeof(*llun));
+    if (!llun) {
+        warn_noalloc();
+        return -1;
+    }
+    memset(llun, 0, sizeof(*llun));
+    llun->drive.type = DTYPE_LSI_SCSI;
+    llun->drive.cntl_id = pci->bdf;
+    llun->pci = pci;
+    llun->target = target;
+    llun->lun = lun;
+    llun->iobase = iobase;
+
+    char *name = znprintf(16, "lsi %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(&llun->drive, name, prio);
+    free(name);
+    if (ret)
+        goto fail;
+    return 0;
+
+fail:
+    free(llun);
+    return -1;
+}
+
+static void
+lsi_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target)
+{
+    /* TODO: send REPORT LUNS.  For now, only LUN 0 is recognized.  */
+    lsi_scsi_add_lun(pci, iobase, target, 0);
+}
+
+static void
+init_lsi_scsi(struct pci_device *pci)
+{
+    u16 bdf = pci->bdf;
+    u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
+        & PCI_BASE_ADDRESS_IO_MASK;
+
+    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
+
+    dprintf(1, "found lsi53c895a at %02x:%02x.%x, io @ %x\n",
+            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
+            pci_bdf_to_fn(bdf), iobase);
+
+    // reset
+    outb(LSI_ISTAT0_SRST, iobase + LSI_REG_ISTAT0);
+
+    int i;
+    for (i = 0; i < 7; i++)
+        lsi_scsi_scan_target(pci, iobase, i);
+
+    return;
+}
+
+void
+lsi_scsi_setup(void)
+{
+    ASSERT32FLAT();
+    if (!CONFIG_LSI_SCSI || !runningOnQEMU())
+        return;
+
+    dprintf(3, "init lsi53c895a\n");
+
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci->vendor != PCI_VENDOR_ID_LSI_LOGIC
+            || pci->device != PCI_DEVICE_ID_LSI_53C895A)
+            continue;
+        init_lsi_scsi(pci);
+    }
+}
diff --git a/src/hw/lsi-scsi.h b/src/hw/lsi-scsi.h
new file mode 100644 (file)
index 0000000..9c5a9b2
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __LSI_SCSI_H
+#define __LSI_SCSI_H
+
+struct disk_op_s;
+int lsi_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+void lsi_scsi_setup(void);
+
+#endif /* __LSI_SCSI_H */
diff --git a/src/hw/megasas.c b/src/hw/megasas.c
new file mode 100644 (file)
index 0000000..f4eeba0
--- /dev/null
@@ -0,0 +1,396 @@
+// MegaRAID SAS boot support.
+//
+// Copyright (C) 2012 Hannes Reinecke, SUSE Linux Products GmbH
+//
+// Authors:
+//  Hannes Reinecke <hare@suse.de>
+//
+// based on virtio-scsi.c which is written by:
+//  Paolo Bonzini <pbonzini@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+#include "pci_ids.h" // PCI_DEVICE_ID_XXX
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "boot.h" // bootprio_find_scsi_device
+#include "blockcmd.h" // scsi_drive_setup
+#include "disk.h"
+
+#define MFI_DB 0x0 // Doorbell
+#define MFI_OMSG0 0x18 // Outbound message 0
+#define MFI_IDB 0x20 // Inbound doorbell
+#define MFI_ODB 0x2c // Outbound doorbell
+#define MFI_IQP 0x40 // Inbound queue port
+#define MFI_OSP0 0xb0 // Outbound scratch pad0
+#define MFI_IQPL 0xc0 // Inbound queue port (low bytes)
+#define MFI_IQPH 0xc4 // Inbound queue port (high bytes)
+
+#define MFI_STATE_MASK                0xf0000000
+#define MFI_STATE_WAIT_HANDSHAKE      0x60000000
+#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000
+#define MFI_STATE_READY               0xb0000000
+#define MFI_STATE_OPERATIONAL         0xc0000000
+#define MFI_STATE_FAULT               0xf0000000
+
+/* MFI Commands */
+typedef enum {
+    MFI_CMD_INIT = 0x00,
+    MFI_CMD_LD_READ,
+    MFI_CMD_LD_WRITE,
+    MFI_CMD_LD_SCSI_IO,
+    MFI_CMD_PD_SCSI_IO,
+    MFI_CMD_DCMD,
+    MFI_CMD_ABORT,
+    MFI_CMD_SMP,
+    MFI_CMD_STP
+} mfi_cmd_t;
+
+struct megasas_cmd_frame {
+    u8 cmd;             /*00h */
+    u8 sense_len;       /*01h */
+    u8 cmd_status;      /*02h */
+    u8 scsi_status;     /*03h */
+
+    u8 target_id;       /*04h */
+    u8 lun;             /*05h */
+    u8 cdb_len;         /*06h */
+    u8 sge_count;       /*07h */
+
+    u32 context;        /*08h */
+    u32 context_64;     /*0Ch */
+
+    u16 flags;          /*10h */
+    u16 timeout;        /*12h */
+    u32 data_xfer_len;   /*14h */
+
+    union {
+        struct {
+            u32 opcode;       /*18h */
+            u8 mbox[12];      /*1Ch */
+            u32 sgl_addr;     /*28h */
+            u32 sgl_len;      /*32h */
+            u32 pad;          /*34h */
+        } dcmd;
+        struct {
+            u32 sense_buf_lo; /*18h */
+            u32 sense_buf_hi; /*1Ch */
+            u8 cdb[16];       /*20h */
+            u32 sgl_addr;     /*30h */
+            u32 sgl_len;      /*34h */
+        } pthru;
+        struct {
+            u8 pad[22];       /*18h */
+        } gen;
+    };
+} __attribute__ ((packed));
+
+struct mfi_ld_list_s {
+    u32     count;
+    u32     reserved_0;
+    struct {
+        u8          target;
+        u8          lun;
+        u16         seq;
+        u8          state;
+        u8          reserved_1[3];
+        u64         size;
+    } lds[64];
+} __attribute__ ((packed));
+
+#define MEGASAS_POLL_TIMEOUT 60000 // 60 seconds polling timeout
+
+struct megasas_lun_s {
+    struct drive_s drive;
+    struct pci_device *pci;
+    struct megasas_cmd_frame *frame;
+    u32 iobase;
+    u8 target;
+    u8 lun;
+};
+
+static int megasas_fire_cmd(u16 pci_id, u32 ioaddr,
+                            struct megasas_cmd_frame *frame)
+{
+    u32 frame_addr = (u32)frame;
+    int frame_count = 1;
+    u8 cmd_state;
+
+    dprintf(2, "Frame 0x%x\n", frame_addr);
+    if (pci_id == PCI_DEVICE_ID_LSI_SAS2004 ||
+        pci_id == PCI_DEVICE_ID_LSI_SAS2008) {
+        outl(0, ioaddr + MFI_IQPH);
+        outl(frame_addr | frame_count << 1 | 1, ioaddr + MFI_IQPL);
+    } else if (pci_id == PCI_DEVICE_ID_DELL_PERC5 ||
+               pci_id == PCI_DEVICE_ID_LSI_SAS1064R ||
+               pci_id == PCI_DEVICE_ID_LSI_VERDE_ZCR) {
+        outl(frame_addr >> 3 | frame_count, ioaddr + MFI_IQP);
+    } else {
+        outl(frame_addr | frame_count << 1 | 1, ioaddr + MFI_IQP);
+    }
+
+    u32 end = timer_calc(MEGASAS_POLL_TIMEOUT);
+    do {
+        for (;;) {
+            cmd_state = GET_LOWFLAT(frame->cmd_status);
+            if (cmd_state != 0xff)
+                break;
+            if (timer_check(end)) {
+                warn_timeout();
+                return -1;
+            }
+            yield();
+        }
+    } while (cmd_state == 0xff);
+
+    if (cmd_state == 0 || cmd_state == 0x2d)
+        return 0;
+    dprintf(1, "ERROR: Frame 0x%x, status 0x%x\n", frame_addr, cmd_state);
+    return -1;
+}
+
+int
+megasas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    struct megasas_lun_s *mlun =
+        container_of(op->drive_g, struct megasas_lun_s, drive);
+    u8 *cdb = cdbcmd;
+    struct megasas_cmd_frame *frame = GET_GLOBAL(mlun->frame);
+    u16 pci_id = GET_GLOBAL(mlun->pci->device);
+    int i;
+
+    if (!CONFIG_MEGASAS)
+        return DISK_RET_EBADTRACK;
+
+    memset_fl(frame, 0, sizeof(*frame));
+    SET_LOWFLAT(frame->cmd, MFI_CMD_LD_SCSI_IO);
+    SET_LOWFLAT(frame->cmd_status, 0xFF);
+    SET_LOWFLAT(frame->target_id, GET_GLOBAL(mlun->target));
+    SET_LOWFLAT(frame->lun, GET_GLOBAL(mlun->lun));
+    SET_LOWFLAT(frame->flags, 0x0001);
+    SET_LOWFLAT(frame->data_xfer_len, op->count * blocksize);
+    SET_LOWFLAT(frame->cdb_len, 16);
+
+    for (i = 0; i < 16; i++) {
+        SET_LOWFLAT(frame->pthru.cdb[i], cdb[i]);
+    }
+    dprintf(2, "pthru cmd 0x%x count %d bs %d\n",
+            cdb[0], op->count, blocksize);
+
+    if (op->count) {
+        SET_LOWFLAT(frame->pthru.sgl_addr, (u32)op->buf_fl);
+        SET_LOWFLAT(frame->pthru.sgl_len, op->count * blocksize);
+        SET_LOWFLAT(frame->sge_count, 1);
+    }
+    SET_LOWFLAT(frame->context, (u32)frame);
+
+    if (megasas_fire_cmd(pci_id, GET_GLOBAL(mlun->iobase), frame) == 0)
+        return DISK_RET_SUCCESS;
+
+    dprintf(2, "pthru cmd 0x%x failed\n", cdb[0]);
+    return DISK_RET_EBADTRACK;
+}
+
+static int
+megasas_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
+{
+    struct megasas_lun_s *mlun = malloc_fseg(sizeof(*mlun));
+    char *name;
+    int prio, ret = 0;
+
+    if (!mlun) {
+        warn_noalloc();
+        return -1;
+    }
+    memset(mlun, 0, sizeof(*mlun));
+    mlun->drive.type = DTYPE_MEGASAS;
+    mlun->drive.cntl_id = pci->bdf;
+    mlun->pci = pci;
+    mlun->target = target;
+    mlun->lun = lun;
+    mlun->iobase = iobase;
+    mlun->frame = memalign_low(256, sizeof(struct megasas_cmd_frame));
+    if (!mlun->frame) {
+        warn_noalloc();
+        free(mlun);
+        return -1;
+    }
+    name = znprintf(36, "MegaRAID SAS (PCI %02x:%02x.%x) LD %d:%d",
+                    pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
+                    pci_bdf_to_fn(pci->bdf), target, lun);
+    prio = bootprio_find_scsi_device(pci, target, lun);
+    ret = scsi_drive_setup(&mlun->drive, name, prio);
+    free(name);
+    if (ret) {
+        free(mlun->frame);
+        free(mlun);
+        ret = -1;
+    }
+
+    return ret;
+}
+
+static void megasas_scan_target(struct pci_device *pci, u32 iobase)
+{
+    struct mfi_ld_list_s ld_list;
+    struct megasas_cmd_frame *frame = memalign_tmp(256, sizeof(*frame));
+    int i;
+
+    memset(&ld_list, 0, sizeof(ld_list));
+    memset_fl(frame, 0, sizeof(*frame));
+
+    frame->cmd = MFI_CMD_DCMD;
+    frame->cmd_status = 0xFF;
+    frame->sge_count = 1;
+    frame->flags = 0x0011;
+    frame->data_xfer_len = sizeof(ld_list);
+    frame->dcmd.opcode = 0x03010000;
+    frame->dcmd.sgl_addr = (u32)MAKE_FLATPTR(GET_SEG(SS), &ld_list);
+    frame->dcmd.sgl_len = sizeof(ld_list);
+    frame->context = (u32)frame;
+
+    if (megasas_fire_cmd(pci->device, iobase, frame) == 0) {
+        dprintf(2, "%d LD found\n", ld_list.count);
+        for (i = 0; i < ld_list.count; i++) {
+            dprintf(2, "LD %d:%d state 0x%x\n",
+                    ld_list.lds[i].target, ld_list.lds[i].lun,
+                    ld_list.lds[i].state);
+            if (ld_list.lds[i].state != 0) {
+                megasas_add_lun(pci, iobase,
+                                ld_list.lds[i].target, ld_list.lds[i].lun);
+            }
+        }
+    }
+}
+
+static int megasas_transition_to_ready(struct pci_device *pci, u32 ioaddr)
+{
+    u32 fw_state = 0, new_state, mfi_flags = 0;
+
+    if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R ||
+        pci->device == PCI_DEVICE_ID_DELL_PERC5)
+        new_state = inl(ioaddr + MFI_OMSG0) & MFI_STATE_MASK;
+    else
+        new_state = inl(ioaddr + MFI_OSP0) & MFI_STATE_MASK;
+
+    while (fw_state != new_state) {
+        switch (new_state) {
+        case MFI_STATE_FAULT:
+            dprintf(1, "ERROR: fw in fault state\n");
+            return -1;
+            break;
+        case MFI_STATE_WAIT_HANDSHAKE:
+            mfi_flags = 0x08;
+            /* fallthrough */
+        case MFI_STATE_BOOT_MESSAGE_PENDING:
+            mfi_flags |= 0x10;
+            if (pci->device == PCI_DEVICE_ID_LSI_SAS2004 ||
+                pci->device == PCI_DEVICE_ID_LSI_SAS2008 ||
+                pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
+                pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
+                outl(ioaddr + MFI_DB, mfi_flags);
+            } else {
+                outl(ioaddr + MFI_IDB, mfi_flags);
+            }
+            break;
+        case MFI_STATE_OPERATIONAL:
+            mfi_flags = 0x07;
+            if (pci->device == PCI_DEVICE_ID_LSI_SAS2004 ||
+                pci->device == PCI_DEVICE_ID_LSI_SAS2008 ||
+                pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
+                pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
+                outl(ioaddr + MFI_DB, mfi_flags);
+                if (pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
+                    pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
+                    int j = 0;
+                    u32 doorbell;
+
+                    while (j < MEGASAS_POLL_TIMEOUT) {
+                        doorbell = inl(ioaddr + MFI_DB) & 1;
+                        if (!doorbell)
+                            break;
+                        msleep(20);
+                        j++;
+                    }
+                }
+            } else {
+                outw(ioaddr + MFI_IDB, mfi_flags);
+            }
+            break;
+        case MFI_STATE_READY:
+            dprintf(2, "MegaRAID SAS fw ready\n");
+            return 0;
+        }
+        // The current state should not last longer than poll timeout
+        u32 end = timer_calc(MEGASAS_POLL_TIMEOUT);
+        for (;;) {
+            if (timer_check(end)) {
+                break;
+            }
+            yield();
+            fw_state = new_state;
+            if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R ||
+                pci->device == PCI_DEVICE_ID_DELL_PERC5)
+                new_state = inl(ioaddr + MFI_OMSG0) & MFI_STATE_MASK;
+            else
+                new_state = inl(ioaddr + MFI_OSP0) & MFI_STATE_MASK;
+            if (new_state != fw_state) {
+                break;
+            }
+        }
+    }
+    dprintf(1, "ERROR: fw in state %x\n", new_state & MFI_STATE_MASK);
+    return -1;
+}
+
+static void
+init_megasas(struct pci_device *pci)
+{
+    u16 bdf = pci->bdf;
+    u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_2)
+        & PCI_BASE_ADDRESS_IO_MASK;
+
+    dprintf(1, "found MegaRAID SAS at %02x:%02x.%x, io @ %x\n",
+            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
+            pci_bdf_to_fn(bdf), iobase);
+
+    pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
+                     PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+    // reset
+    if (megasas_transition_to_ready(pci, iobase) == 0)
+        megasas_scan_target(pci, iobase);
+
+    return;
+}
+
+void
+megasas_setup(void)
+{
+    ASSERT32FLAT();
+    if (!CONFIG_MEGASAS)
+        return;
+
+    dprintf(3, "init megasas\n");
+
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci->vendor != PCI_VENDOR_ID_LSI_LOGIC &&
+            pci->vendor != PCI_VENDOR_ID_DELL)
+            continue;
+        if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R ||
+            pci->device == PCI_DEVICE_ID_LSI_SAS1078 ||
+            pci->device == PCI_DEVICE_ID_LSI_SAS1078DE ||
+            pci->device == PCI_DEVICE_ID_LSI_SAS2108 ||
+            pci->device == PCI_DEVICE_ID_LSI_SAS2108E ||
+            pci->device == PCI_DEVICE_ID_LSI_SAS2004 ||
+            pci->device == PCI_DEVICE_ID_LSI_SAS2008 ||
+            pci->device == PCI_DEVICE_ID_LSI_VERDE_ZCR ||
+            pci->device == PCI_DEVICE_ID_DELL_PERC5 ||
+            pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
+            pci->device == PCI_DEVICE_ID_LSI_SAS3108)
+            init_megasas(pci);
+    }
+}
diff --git a/src/hw/megasas.h b/src/hw/megasas.h
new file mode 100644 (file)
index 0000000..124042e
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __MEGASAS_H
+#define __MEGASAS_H
+
+struct disk_op_s;
+int megasas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+void megasas_setup(void);
+
+#endif /* __MEGASAS_H */
diff --git a/src/hw/pci.c b/src/hw/pci.c
new file mode 100644 (file)
index 0000000..dc62c5c
--- /dev/null
@@ -0,0 +1,277 @@
+// PCI config space access functions.
+//
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "config.h" // CONFIG_*
+#include "pci.h" // pci_config_writel
+#include "ioport.h" // outl
+#include "util.h" // dprintf
+#include "farptr.h" // MAKE_FLATPTR
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA
+
+void pci_config_writel(u16 bdf, u32 addr, u32 val)
+{
+    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
+    outl(val, PORT_PCI_DATA);
+}
+
+void pci_config_writew(u16 bdf, u32 addr, u16 val)
+{
+    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
+    outw(val, PORT_PCI_DATA + (addr & 2));
+}
+
+void pci_config_writeb(u16 bdf, u32 addr, u8 val)
+{
+    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
+    outb(val, PORT_PCI_DATA + (addr & 3));
+}
+
+u32 pci_config_readl(u16 bdf, u32 addr)
+{
+    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
+    return inl(PORT_PCI_DATA);
+}
+
+u16 pci_config_readw(u16 bdf, u32 addr)
+{
+    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
+    return inw(PORT_PCI_DATA + (addr & 2));
+}
+
+u8 pci_config_readb(u16 bdf, u32 addr)
+{
+    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
+    return inb(PORT_PCI_DATA + (addr & 3));
+}
+
+void
+pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
+{
+    u16 val = pci_config_readw(bdf, addr);
+    val = (val & ~off) | on;
+    pci_config_writew(bdf, addr, val);
+}
+
+// Helper function for foreachbdf() macro - return next device
+int
+pci_next(int bdf, int bus)
+{
+    if (pci_bdf_to_fn(bdf) == 0
+        && (pci_config_readb(bdf, PCI_HEADER_TYPE) & 0x80) == 0)
+        // Last found device wasn't a multi-function device - skip to
+        // the next device.
+        bdf += 8;
+    else
+        bdf += 1;
+
+    for (;;) {
+        if (pci_bdf_to_bus(bdf) != bus)
+            return -1;
+
+        u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
+        if (v != 0x0000 && v != 0xffff)
+            // Device is present.
+            return bdf;
+
+        if (pci_bdf_to_fn(bdf) == 0)
+            bdf += 8;
+        else
+            bdf += 1;
+    }
+}
+
+struct hlist_head PCIDevices VARVERIFY32INIT;
+int MaxPCIBus VARFSEG;
+
+// Check if PCI is available at all
+int
+pci_probe_host(void)
+{
+    outl(0x80000000, PORT_PCI_CMD);
+    if (inl(PORT_PCI_CMD) != 0x80000000) {
+        dprintf(1, "Detected non-PCI system\n");
+        return -1;
+    }
+    return 0;
+}
+
+// Find all PCI devices and populate PCIDevices linked list.
+void
+pci_probe_devices(void)
+{
+    dprintf(3, "PCI probe\n");
+    struct pci_device *busdevs[256];
+    memset(busdevs, 0, sizeof(busdevs));
+    struct hlist_node **pprev = &PCIDevices.first;
+    int extraroots = romfile_loadint("etc/extra-pci-roots", 0);
+    int bus = -1, lastbus = 0, rootbuses = 0, count=0;
+    while (bus < 0xff && (bus < MaxPCIBus || rootbuses < extraroots)) {
+        bus++;
+        int bdf;
+        foreachbdf(bdf, bus) {
+            // Create new pci_device struct and add to list.
+            struct pci_device *dev = malloc_tmp(sizeof(*dev));
+            if (!dev) {
+                warn_noalloc();
+                return;
+            }
+            memset(dev, 0, sizeof(*dev));
+            hlist_add(&dev->node, pprev);
+            pprev = &dev->node.next;
+            count++;
+
+            // Find parent device.
+            int rootbus;
+            struct pci_device *parent = busdevs[bus];
+            if (!parent) {
+                if (bus != lastbus)
+                    rootbuses++;
+                lastbus = bus;
+                rootbus = rootbuses;
+                if (bus > MaxPCIBus)
+                    MaxPCIBus = bus;
+            } else {
+                rootbus = parent->rootbus;
+            }
+
+            // Populate pci_device info.
+            dev->bdf = bdf;
+            dev->parent = parent;
+            dev->rootbus = rootbus;
+            u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
+            dev->vendor = vendev & 0xffff;
+            dev->device = vendev >> 16;
+            u32 classrev = pci_config_readl(bdf, PCI_CLASS_REVISION);
+            dev->class = classrev >> 16;
+            dev->prog_if = classrev >> 8;
+            dev->revision = classrev & 0xff;
+            dev->header_type = pci_config_readb(bdf, PCI_HEADER_TYPE);
+            u8 v = dev->header_type & 0x7f;
+            if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) {
+                u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
+                dev->secondary_bus = secbus;
+                if (secbus > bus && !busdevs[secbus])
+                    busdevs[secbus] = dev;
+                if (secbus > MaxPCIBus)
+                    MaxPCIBus = secbus;
+            }
+            dprintf(4, "PCI device %02x:%02x.%x (vd=%04x:%04x c=%04x)\n"
+                    , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)
+                    , pci_bdf_to_fn(bdf)
+                    , dev->vendor, dev->device, dev->class);
+        }
+    }
+    dprintf(1, "Found %d PCI devices (max PCI bus is %02x)\n", count, MaxPCIBus);
+}
+
+// Search for a device with the specified vendor and device ids.
+struct pci_device *
+pci_find_device(u16 vendid, u16 devid)
+{
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci->vendor == vendid && pci->device == devid)
+            return pci;
+    }
+    return NULL;
+}
+
+// Search for a device with the specified class id.
+struct pci_device *
+pci_find_class(u16 classid)
+{
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci->class == classid)
+            return pci;
+    }
+    return NULL;
+}
+
+int pci_init_device(const struct pci_device_id *ids
+                    , struct pci_device *pci, void *arg)
+{
+    while (ids->vendid || ids->class_mask) {
+        if ((ids->vendid == PCI_ANY_ID || ids->vendid == pci->vendor) &&
+            (ids->devid == PCI_ANY_ID || ids->devid == pci->device) &&
+            !((ids->class ^ pci->class) & ids->class_mask)) {
+            if (ids->func)
+                ids->func(pci, arg);
+            return 0;
+        }
+        ids++;
+    }
+    return -1;
+}
+
+struct pci_device *
+pci_find_init_device(const struct pci_device_id *ids, void *arg)
+{
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci_init_device(ids, pci, arg) == 0)
+            return pci;
+    }
+    return NULL;
+}
+
+void
+pci_reboot(void)
+{
+    u8 v = inb(PORT_PCI_REBOOT) & ~6;
+    outb(v|2, PORT_PCI_REBOOT); /* Request hard reset */
+    udelay(50);
+    outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */
+    udelay(50);
+}
+
+// helper functions to access pci mmio bars from real mode
+
+u32 VISIBLE32FLAT
+pci_readl_32(u32 addr)
+{
+    dprintf(9, "32: pci read : %x\n", addr);
+    return readl((void*)addr);
+}
+
+u32 pci_readl(u32 addr)
+{
+    if (MODESEGMENT) {
+        dprintf(9, "16: pci read : %x\n", addr);
+        extern void _cfunc32flat_pci_readl_32(u32 addr);
+        return call32(_cfunc32flat_pci_readl_32, addr, -1);
+    } else {
+        return pci_readl_32(addr);
+    }
+}
+
+struct reg32 {
+    u32 addr;
+    u32 data;
+};
+
+void VISIBLE32FLAT
+pci_writel_32(struct reg32 *reg32)
+{
+    dprintf(9, "32: pci write: %x, %x (%p)\n", reg32->addr, reg32->data, reg32);
+    writel((void*)(reg32->addr), reg32->data);
+}
+
+void pci_writel(u32 addr, u32 val)
+{
+    struct reg32 reg32 = { .addr = addr, .data = val };
+    if (MODESEGMENT) {
+        dprintf(9, "16: pci write: %x, %x (%x:%p)\n",
+                reg32.addr, reg32.data, GET_SEG(SS), &reg32);
+        void *flatptr = MAKE_FLATPTR(GET_SEG(SS), &reg32);
+        extern void _cfunc32flat_pci_writel_32(struct reg32 *reg32);
+        call32(_cfunc32flat_pci_writel_32, (u32)flatptr, -1);
+    } else {
+        pci_writel_32(&reg32);
+    }
+}
diff --git a/src/hw/pci.h b/src/hw/pci.h
new file mode 100644 (file)
index 0000000..7760d21
--- /dev/null
@@ -0,0 +1,161 @@
+#ifndef __PCI_H
+#define __PCI_H
+
+#include "types.h" // u32
+#include "list.h" // hlist_node
+
+#define PCI_ROM_SLOT 6
+#define PCI_NUM_REGIONS 7
+#define PCI_BRIDGE_NUM_REGIONS 2
+
+static inline u8 pci_bdf_to_bus(u16 bdf) {
+    return bdf >> 8;
+}
+static inline u8 pci_bdf_to_devfn(u16 bdf) {
+    return bdf & 0xff;
+}
+static inline u16 pci_bdf_to_busdev(u16 bdf) {
+    return bdf & ~0x07;
+}
+static inline u8 pci_bdf_to_dev(u16 bdf) {
+    return (bdf >> 3) & 0x1f;
+}
+static inline u8 pci_bdf_to_fn(u16 bdf) {
+    return bdf & 0x07;
+}
+static inline u16 pci_to_bdf(int bus, int dev, int fn) {
+    return (bus<<8) | (dev<<3) | fn;
+}
+static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) {
+    return (bus << 8) | devfn;
+}
+
+void pci_config_writel(u16 bdf, u32 addr, u32 val);
+void pci_config_writew(u16 bdf, u32 addr, u16 val);
+void pci_config_writeb(u16 bdf, u32 addr, u8 val);
+u32 pci_config_readl(u16 bdf, u32 addr);
+u16 pci_config_readw(u16 bdf, u32 addr);
+u8 pci_config_readb(u16 bdf, u32 addr);
+void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+
+struct pci_device *pci_find_device(u16 vendid, u16 devid);
+struct pci_device *pci_find_class(u16 classid);
+
+struct pci_device {
+    u16 bdf;
+    u8 rootbus;
+    struct hlist_node node;
+    struct pci_device *parent;
+
+    // Configuration space device information
+    u16 vendor, device;
+    u16 class;
+    u8 prog_if, revision;
+    u8 header_type;
+    u8 secondary_bus;
+
+    // Local information on device.
+    int have_driver;
+};
+extern u64 pcimem_start, pcimem_end;
+extern u64 pcimem64_start, pcimem64_end;
+extern struct hlist_head PCIDevices;
+extern int MaxPCIBus;
+int pci_probe_host(void);
+void pci_probe_devices(void);
+static inline u32 pci_classprog(struct pci_device *pci) {
+    return (pci->class << 8) | pci->prog_if;
+}
+
+#define foreachpci(PCI)                                 \
+    hlist_for_each_entry(PCI, &PCIDevices, node)
+
+int pci_next(int bdf, int bus);
+#define foreachbdf(BDF, BUS)                                    \
+    for (BDF=pci_next(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS))  \
+         ; BDF >= 0                                             \
+         ; BDF=pci_next(BDF, (BUS)))
+
+#define PCI_ANY_ID      (~0)
+struct pci_device_id {
+    u32 vendid;
+    u32 devid;
+    u32 class;
+    u32 class_mask;
+    void (*func)(struct pci_device *pci, void *arg);
+};
+
+#define PCI_DEVICE(vendor_id, device_id, init_func)     \
+    {                                                   \
+        .vendid = (vendor_id),                          \
+        .devid = (device_id),                           \
+        .class = PCI_ANY_ID,                            \
+        .class_mask = 0,                                \
+        .func = (init_func)                             \
+    }
+
+#define PCI_DEVICE_CLASS(vendor_id, device_id, class_code, init_func)   \
+    {                                                                   \
+        .vendid = (vendor_id),                                          \
+        .devid = (device_id),                                           \
+        .class = (class_code),                                          \
+        .class_mask = ~0,                                               \
+        .func = (init_func)                                             \
+    }
+
+#define PCI_DEVICE_END                          \
+    {                                           \
+        .vendid = 0,                            \
+    }
+
+int pci_init_device(const struct pci_device_id *ids
+                    , struct pci_device *pci, void *arg);
+struct pci_device *pci_find_init_device(const struct pci_device_id *ids
+                                        , void *arg);
+void pci_reboot(void);
+
+// helper functions to access pci mmio bars from real mode
+u32 pci_readl(u32 addr);
+void pci_writel(u32 addr, u32 val);
+
+// pirtable.c
+void pirtable_setup(void);
+
+
+/****************************************************************
+ * PIR table
+ ****************************************************************/
+
+struct link_info {
+    u8 link;
+    u16 bitmap;
+} PACKED;
+
+struct pir_slot {
+    u8 bus;
+    u8 dev;
+    struct link_info links[4];
+    u8 slot_nr;
+    u8 reserved;
+} PACKED;
+
+struct pir_header {
+    u32 signature;
+    u16 version;
+    u16 size;
+    u8 router_bus;
+    u8 router_devfunc;
+    u16 exclusive_irqs;
+    u32 compatible_devid;
+    u32 miniport_data;
+    u8 reserved[11];
+    u8 checksum;
+    struct pir_slot slots[0];
+} PACKED;
+
+extern struct pir_header *PirAddr;
+
+#define PIR_SIGNATURE 0x52495024 // $PIR
+
+
+#endif
diff --git a/src/hw/pci_ids.h b/src/hw/pci_ids.h
new file mode 100644 (file)
index 0000000..665e945
--- /dev/null
@@ -0,0 +1,2619 @@
+/*
+ *     PCI Class, Vendor and Device IDs
+ *
+ *     Please keep sorted.
+ */
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED          0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA      0x0001
+
+#define PCI_BASE_CLASS_STORAGE         0x01
+#define PCI_CLASS_STORAGE_SCSI         0x0100
+#define PCI_CLASS_STORAGE_IDE          0x0101
+#define PCI_CLASS_STORAGE_FLOPPY       0x0102
+#define PCI_CLASS_STORAGE_IPI          0x0103
+#define PCI_CLASS_STORAGE_RAID         0x0104
+#define PCI_CLASS_STORAGE_SATA         0x0106
+#define PCI_CLASS_STORAGE_SATA_AHCI    0x010601
+#define PCI_CLASS_STORAGE_SAS          0x0107
+#define PCI_CLASS_STORAGE_OTHER                0x0180
+
+#define PCI_BASE_CLASS_NETWORK         0x02
+#define PCI_CLASS_NETWORK_ETHERNET     0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING   0x0201
+#define PCI_CLASS_NETWORK_FDDI         0x0202
+#define PCI_CLASS_NETWORK_ATM          0x0203
+#define PCI_CLASS_NETWORK_OTHER                0x0280
+
+#define PCI_BASE_CLASS_DISPLAY         0x03
+#define PCI_CLASS_DISPLAY_VGA          0x0300
+#define PCI_CLASS_DISPLAY_XGA          0x0301
+#define PCI_CLASS_DISPLAY_3D           0x0302
+#define PCI_CLASS_DISPLAY_OTHER                0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA      0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO     0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO     0x0401
+#define PCI_CLASS_MULTIMEDIA_PHONE     0x0402
+#define PCI_CLASS_MULTIMEDIA_OTHER     0x0480
+
+#define PCI_BASE_CLASS_MEMORY          0x05
+#define PCI_CLASS_MEMORY_RAM           0x0500
+#define PCI_CLASS_MEMORY_FLASH         0x0501
+#define PCI_CLASS_MEMORY_OTHER         0x0580
+
+#define PCI_BASE_CLASS_BRIDGE          0x06
+#define PCI_CLASS_BRIDGE_HOST          0x0600
+#define PCI_CLASS_BRIDGE_ISA           0x0601
+#define PCI_CLASS_BRIDGE_EISA          0x0602
+#define PCI_CLASS_BRIDGE_MC            0x0603
+#define PCI_CLASS_BRIDGE_PCI           0x0604
+#define PCI_CLASS_BRIDGE_PCMCIA                0x0605
+#define PCI_CLASS_BRIDGE_NUBUS         0x0606
+#define PCI_CLASS_BRIDGE_CARDBUS       0x0607
+#define PCI_CLASS_BRIDGE_RACEWAY       0x0608
+#define PCI_CLASS_BRIDGE_OTHER         0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION   0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702
+#define PCI_CLASS_COMMUNICATION_MODEM  0x0703
+#define PCI_CLASS_COMMUNICATION_OTHER  0x0780
+
+#define PCI_BASE_CLASS_SYSTEM          0x08
+#define PCI_CLASS_SYSTEM_PIC           0x0800
+#define PCI_CLASS_SYSTEM_PIC_IOAPIC    0x080010
+#define PCI_CLASS_SYSTEM_PIC_IOXAPIC   0x080020
+#define PCI_CLASS_SYSTEM_DMA           0x0801
+#define PCI_CLASS_SYSTEM_TIMER         0x0802
+#define PCI_CLASS_SYSTEM_RTC           0x0803
+#define PCI_CLASS_SYSTEM_PCI_HOTPLUG   0x0804
+#define PCI_CLASS_SYSTEM_SDHCI         0x0805
+#define PCI_CLASS_SYSTEM_OTHER         0x0880
+
+#define PCI_BASE_CLASS_INPUT           0x09
+#define PCI_CLASS_INPUT_KEYBOARD       0x0900
+#define PCI_CLASS_INPUT_PEN            0x0901
+#define PCI_CLASS_INPUT_MOUSE          0x0902
+#define PCI_CLASS_INPUT_SCANNER                0x0903
+#define PCI_CLASS_INPUT_GAMEPORT       0x0904
+#define PCI_CLASS_INPUT_OTHER          0x0980
+
+#define PCI_BASE_CLASS_DOCKING         0x0a
+#define PCI_CLASS_DOCKING_GENERIC      0x0a00
+#define PCI_CLASS_DOCKING_OTHER                0x0a80
+
+#define PCI_BASE_CLASS_PROCESSOR       0x0b
+#define PCI_CLASS_PROCESSOR_386                0x0b00
+#define PCI_CLASS_PROCESSOR_486                0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM    0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA      0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC    0x0b20
+#define PCI_CLASS_PROCESSOR_MIPS       0x0b30
+#define PCI_CLASS_PROCESSOR_CO         0x0b40
+
+#define PCI_BASE_CLASS_SERIAL          0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE      0x0c00
+#define PCI_CLASS_SERIAL_FIREWIRE_OHCI 0x0c0010
+#define PCI_CLASS_SERIAL_ACCESS                0x0c01
+#define PCI_CLASS_SERIAL_SSA           0x0c02
+#define PCI_CLASS_SERIAL_USB           0x0c03
+#define PCI_CLASS_SERIAL_USB_UHCI      0x0c0300
+#define PCI_CLASS_SERIAL_USB_OHCI      0x0c0310
+#define PCI_CLASS_SERIAL_USB_EHCI      0x0c0320
+#define PCI_CLASS_SERIAL_FIBER         0x0c04
+#define PCI_CLASS_SERIAL_SMBUS         0x0c05
+
+#define PCI_BASE_CLASS_WIRELESS                        0x0d
+#define PCI_CLASS_WIRELESS_RF_CONTROLLER       0x0d10
+#define PCI_CLASS_WIRELESS_WHCI                        0x0d1010
+
+#define PCI_BASE_CLASS_INTELLIGENT     0x0e
+#define PCI_CLASS_INTELLIGENT_I2O      0x0e00
+
+#define PCI_BASE_CLASS_SATELLITE       0x0f
+#define PCI_CLASS_SATELLITE_TV         0x0f00
+#define PCI_CLASS_SATELLITE_AUDIO      0x0f01
+#define PCI_CLASS_SATELLITE_VOICE      0x0f03
+#define PCI_CLASS_SATELLITE_DATA       0x0f04
+
+#define PCI_BASE_CLASS_CRYPT           0x10
+#define PCI_CLASS_CRYPT_NETWORK                0x1000
+#define PCI_CLASS_CRYPT_ENTERTAINMENT  0x1001
+#define PCI_CLASS_CRYPT_OTHER          0x1080
+
+#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11
+#define PCI_CLASS_SP_DPIO              0x1100
+#define PCI_CLASS_SP_OTHER             0x1180
+
+#define PCI_CLASS_OTHERS               0xff
+
+/* Vendors and devices.  Sort key: vendor first, device next. */
+
+#define PCI_VENDOR_ID_TTTECH           0x0357
+#define PCI_DEVICE_ID_TTTECH_MC322     0x000a
+
+#define PCI_VENDOR_ID_DYNALINK         0x0675
+#define PCI_DEVICE_ID_DYNALINK_IS64PH  0x1702
+
+#define PCI_VENDOR_ID_BERKOM                   0x0871
+#define PCI_DEVICE_ID_BERKOM_A1T               0xffa1
+#define PCI_DEVICE_ID_BERKOM_T_CONCEPT         0xffa2
+#define PCI_DEVICE_ID_BERKOM_A4T               0xffa4
+#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO     0xffa8
+
+#define PCI_VENDOR_ID_COMPAQ           0x0e11
+#define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508
+#define PCI_DEVICE_ID_COMPAQ_TACHYON   0xa0fc
+#define PCI_DEVICE_ID_COMPAQ_SMART2P   0xae10
+#define PCI_DEVICE_ID_COMPAQ_NETEL100  0xae32
+#define PCI_DEVICE_ID_COMPAQ_NETEL10   0xae34
+#define PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE 0xae33
+#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I 0xae35
+#define PCI_DEVICE_ID_COMPAQ_NETEL100D 0xae40
+#define PCI_DEVICE_ID_COMPAQ_NETEL100PI        0xae43
+#define PCI_DEVICE_ID_COMPAQ_NETEL100I 0xb011
+#define PCI_DEVICE_ID_COMPAQ_CISS      0xb060
+#define PCI_DEVICE_ID_COMPAQ_CISSB     0xb178
+#define PCI_DEVICE_ID_COMPAQ_CISSC     0x46
+#define PCI_DEVICE_ID_COMPAQ_THUNDER   0xf130
+#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B 0xf150
+
+#define PCI_VENDOR_ID_NCR              0x1000
+#define PCI_VENDOR_ID_LSI_LOGIC                0x1000
+#define PCI_DEVICE_ID_NCR_53C810       0x0001
+#define PCI_DEVICE_ID_NCR_53C820       0x0002
+#define PCI_DEVICE_ID_NCR_53C825       0x0003
+#define PCI_DEVICE_ID_NCR_53C815       0x0004
+#define PCI_DEVICE_ID_LSI_53C810AP     0x0005
+#define PCI_DEVICE_ID_NCR_53C860       0x0006
+#define PCI_DEVICE_ID_LSI_53C1510      0x000a
+#define PCI_DEVICE_ID_NCR_53C896       0x000b
+#define PCI_DEVICE_ID_NCR_53C895       0x000c
+#define PCI_DEVICE_ID_NCR_53C885       0x000d
+#define PCI_DEVICE_ID_NCR_53C875       0x000f
+#define PCI_DEVICE_ID_NCR_53C1510      0x0010
+#define PCI_DEVICE_ID_LSI_53C895A      0x0012
+#define PCI_DEVICE_ID_LSI_53C875A      0x0013
+#define PCI_DEVICE_ID_LSI_53C1010_33   0x0020
+#define PCI_DEVICE_ID_LSI_53C1010_66   0x0021
+#define PCI_DEVICE_ID_LSI_53C1030      0x0030
+#define PCI_DEVICE_ID_LSI_1030_53C1035 0x0032
+#define PCI_DEVICE_ID_LSI_53C1035      0x0040
+#define PCI_DEVICE_ID_NCR_53C875J      0x008f
+#define PCI_DEVICE_ID_LSI_FC909                0x0621
+#define PCI_DEVICE_ID_LSI_FC929                0x0622
+#define PCI_DEVICE_ID_LSI_FC929_LAN    0x0623
+#define PCI_DEVICE_ID_LSI_FC919                0x0624
+#define PCI_DEVICE_ID_LSI_FC919_LAN    0x0625
+#define PCI_DEVICE_ID_LSI_FC929X       0x0626
+#define PCI_DEVICE_ID_LSI_FC939X       0x0642
+#define PCI_DEVICE_ID_LSI_FC949X       0x0640
+#define PCI_DEVICE_ID_LSI_FC949ES      0x0646
+#define PCI_DEVICE_ID_LSI_FC919X       0x0628
+#define PCI_DEVICE_ID_NCR_YELLOWFIN    0x0701
+#define PCI_DEVICE_ID_LSI_61C102       0x0901
+#define PCI_DEVICE_ID_LSI_63C815       0x1000
+#define PCI_DEVICE_ID_LSI_SAS1064      0x0050
+#define PCI_DEVICE_ID_LSI_SAS1064R     0x0411
+#define PCI_DEVICE_ID_LSI_VERDE_ZCR    0x0413
+#define PCI_DEVICE_ID_LSI_SAS1066      0x005E
+#define PCI_DEVICE_ID_LSI_SAS1068      0x0054
+#define PCI_DEVICE_ID_LSI_SAS1064A     0x005C
+#define PCI_DEVICE_ID_LSI_SAS1064E     0x0056
+#define PCI_DEVICE_ID_LSI_SAS1066E     0x005A
+#define PCI_DEVICE_ID_LSI_SAS1068E     0x0058
+#define PCI_DEVICE_ID_LSI_SAS1078      0x0060
+#define PCI_DEVICE_ID_LSI_SAS1078DE    0x007C
+#define PCI_DEVICE_ID_LSI_SAS2108E     0x0078
+#define PCI_DEVICE_ID_LSI_SAS2108      0x0079
+#define PCI_DEVICE_ID_LSI_SAS2208      0x005B
+#define PCI_DEVICE_ID_LSI_SAS3108      0x005D
+#define PCI_DEVICE_ID_LSI_SAS2004      0x0071
+#define PCI_DEVICE_ID_LSI_SAS2008      0x0073
+
+#define PCI_VENDOR_ID_ATI              0x1002
+/* Mach64 */
+#define PCI_DEVICE_ID_ATI_68800                0x4158
+#define PCI_DEVICE_ID_ATI_215CT222     0x4354
+#define PCI_DEVICE_ID_ATI_210888CX     0x4358
+#define PCI_DEVICE_ID_ATI_215ET222     0x4554
+/* Mach64 / Rage */
+#define PCI_DEVICE_ID_ATI_215GB                0x4742
+#define PCI_DEVICE_ID_ATI_215GD                0x4744
+#define PCI_DEVICE_ID_ATI_215GI                0x4749
+#define PCI_DEVICE_ID_ATI_215GP                0x4750
+#define PCI_DEVICE_ID_ATI_215GQ                0x4751
+#define PCI_DEVICE_ID_ATI_215XL                0x4752
+#define PCI_DEVICE_ID_ATI_215GT                0x4754
+#define PCI_DEVICE_ID_ATI_215GTB       0x4755
+#define PCI_DEVICE_ID_ATI_215_IV       0x4756
+#define PCI_DEVICE_ID_ATI_215_IW       0x4757
+#define PCI_DEVICE_ID_ATI_215_IZ       0x475A
+#define PCI_DEVICE_ID_ATI_210888GX     0x4758
+#define PCI_DEVICE_ID_ATI_215_LB       0x4c42
+#define PCI_DEVICE_ID_ATI_215_LD       0x4c44
+#define PCI_DEVICE_ID_ATI_215_LG       0x4c47
+#define PCI_DEVICE_ID_ATI_215_LI       0x4c49
+#define PCI_DEVICE_ID_ATI_215_LM       0x4c4D
+#define PCI_DEVICE_ID_ATI_215_LN       0x4c4E
+#define PCI_DEVICE_ID_ATI_215_LR       0x4c52
+#define PCI_DEVICE_ID_ATI_215_LS       0x4c53
+#define PCI_DEVICE_ID_ATI_264_LT       0x4c54
+/* Mach64 VT */
+#define PCI_DEVICE_ID_ATI_264VT                0x5654
+#define PCI_DEVICE_ID_ATI_264VU                0x5655
+#define PCI_DEVICE_ID_ATI_264VV                0x5656
+/* Rage128 GL */
+#define PCI_DEVICE_ID_ATI_RAGE128_RE   0x5245
+#define PCI_DEVICE_ID_ATI_RAGE128_RF   0x5246
+#define PCI_DEVICE_ID_ATI_RAGE128_RG   0x5247
+/* Rage128 VR */
+#define PCI_DEVICE_ID_ATI_RAGE128_RK   0x524b
+#define PCI_DEVICE_ID_ATI_RAGE128_RL   0x524c
+#define PCI_DEVICE_ID_ATI_RAGE128_SE   0x5345
+#define PCI_DEVICE_ID_ATI_RAGE128_SF   0x5346
+#define PCI_DEVICE_ID_ATI_RAGE128_SG   0x5347
+#define PCI_DEVICE_ID_ATI_RAGE128_SH   0x5348
+#define PCI_DEVICE_ID_ATI_RAGE128_SK   0x534b
+#define PCI_DEVICE_ID_ATI_RAGE128_SL   0x534c
+#define PCI_DEVICE_ID_ATI_RAGE128_SM   0x534d
+#define PCI_DEVICE_ID_ATI_RAGE128_SN   0x534e
+/* Rage128 Ultra */
+#define PCI_DEVICE_ID_ATI_RAGE128_TF   0x5446
+#define PCI_DEVICE_ID_ATI_RAGE128_TL   0x544c
+#define PCI_DEVICE_ID_ATI_RAGE128_TR   0x5452
+#define PCI_DEVICE_ID_ATI_RAGE128_TS   0x5453
+#define PCI_DEVICE_ID_ATI_RAGE128_TT   0x5454
+#define PCI_DEVICE_ID_ATI_RAGE128_TU   0x5455
+/* Rage128 M3 */
+#define PCI_DEVICE_ID_ATI_RAGE128_LE   0x4c45
+#define PCI_DEVICE_ID_ATI_RAGE128_LF   0x4c46
+/* Rage128 M4 */
+#define PCI_DEVICE_ID_ATI_RAGE128_MF    0x4d46
+#define PCI_DEVICE_ID_ATI_RAGE128_ML    0x4d4c
+/* Rage128 Pro GL */
+#define PCI_DEVICE_ID_ATI_RAGE128_PA   0x5041
+#define PCI_DEVICE_ID_ATI_RAGE128_PB   0x5042
+#define PCI_DEVICE_ID_ATI_RAGE128_PC   0x5043
+#define PCI_DEVICE_ID_ATI_RAGE128_PD   0x5044
+#define PCI_DEVICE_ID_ATI_RAGE128_PE   0x5045
+#define PCI_DEVICE_ID_ATI_RAGE128_PF   0x5046
+/* Rage128 Pro VR */
+#define PCI_DEVICE_ID_ATI_RAGE128_PG   0x5047
+#define PCI_DEVICE_ID_ATI_RAGE128_PH   0x5048
+#define PCI_DEVICE_ID_ATI_RAGE128_PI   0x5049
+#define PCI_DEVICE_ID_ATI_RAGE128_PJ   0x504A
+#define PCI_DEVICE_ID_ATI_RAGE128_PK   0x504B
+#define PCI_DEVICE_ID_ATI_RAGE128_PL   0x504C
+#define PCI_DEVICE_ID_ATI_RAGE128_PM   0x504D
+#define PCI_DEVICE_ID_ATI_RAGE128_PN   0x504E
+#define PCI_DEVICE_ID_ATI_RAGE128_PO   0x504F
+#define PCI_DEVICE_ID_ATI_RAGE128_PP   0x5050
+#define PCI_DEVICE_ID_ATI_RAGE128_PQ   0x5051
+#define PCI_DEVICE_ID_ATI_RAGE128_PR   0x5052
+#define PCI_DEVICE_ID_ATI_RAGE128_PS   0x5053
+#define PCI_DEVICE_ID_ATI_RAGE128_PT   0x5054
+#define PCI_DEVICE_ID_ATI_RAGE128_PU   0x5055
+#define PCI_DEVICE_ID_ATI_RAGE128_PV   0x5056
+#define PCI_DEVICE_ID_ATI_RAGE128_PW   0x5057
+#define PCI_DEVICE_ID_ATI_RAGE128_PX   0x5058
+/* Rage128 M4 */
+/* Radeon R100 */
+#define PCI_DEVICE_ID_ATI_RADEON_QD    0x5144
+#define PCI_DEVICE_ID_ATI_RADEON_QE    0x5145
+#define PCI_DEVICE_ID_ATI_RADEON_QF    0x5146
+#define PCI_DEVICE_ID_ATI_RADEON_QG    0x5147
+/* Radeon RV100 (VE) */
+#define PCI_DEVICE_ID_ATI_RADEON_QY    0x5159
+#define PCI_DEVICE_ID_ATI_RADEON_QZ    0x515a
+/* Radeon R200 (8500) */
+#define PCI_DEVICE_ID_ATI_RADEON_QL    0x514c
+#define PCI_DEVICE_ID_ATI_RADEON_QN    0x514e
+#define PCI_DEVICE_ID_ATI_RADEON_QO    0x514f
+#define PCI_DEVICE_ID_ATI_RADEON_Ql    0x516c
+#define PCI_DEVICE_ID_ATI_RADEON_BB    0x4242
+/* Radeon R200 (9100) */
+#define PCI_DEVICE_ID_ATI_RADEON_QM    0x514d
+/* Radeon RV200 (7500) */
+#define PCI_DEVICE_ID_ATI_RADEON_QW    0x5157
+#define PCI_DEVICE_ID_ATI_RADEON_QX    0x5158
+/* Radeon NV-100 */
+/* Radeon RV250 (9000) */
+#define PCI_DEVICE_ID_ATI_RADEON_Id    0x4964
+#define PCI_DEVICE_ID_ATI_RADEON_Ie    0x4965
+#define PCI_DEVICE_ID_ATI_RADEON_If    0x4966
+#define PCI_DEVICE_ID_ATI_RADEON_Ig    0x4967
+/* Radeon RV280 (9200) */
+#define PCI_DEVICE_ID_ATI_RADEON_Ya    0x5961
+#define PCI_DEVICE_ID_ATI_RADEON_Yd    0x5964
+/* Radeon R300 (9500) */
+/* Radeon R300 (9700) */
+#define PCI_DEVICE_ID_ATI_RADEON_ND    0x4e44
+#define PCI_DEVICE_ID_ATI_RADEON_NE    0x4e45
+#define PCI_DEVICE_ID_ATI_RADEON_NF    0x4e46
+#define PCI_DEVICE_ID_ATI_RADEON_NG    0x4e47
+/* Radeon R350 (9800) */
+/* Radeon RV350 (9600) */
+/* Radeon M6 */
+#define PCI_DEVICE_ID_ATI_RADEON_LY    0x4c59
+#define PCI_DEVICE_ID_ATI_RADEON_LZ    0x4c5a
+/* Radeon M7 */
+#define PCI_DEVICE_ID_ATI_RADEON_LW    0x4c57
+#define PCI_DEVICE_ID_ATI_RADEON_LX    0x4c58
+/* Radeon M9 */
+#define PCI_DEVICE_ID_ATI_RADEON_Ld    0x4c64
+#define PCI_DEVICE_ID_ATI_RADEON_Le    0x4c65
+#define PCI_DEVICE_ID_ATI_RADEON_Lf    0x4c66
+#define PCI_DEVICE_ID_ATI_RADEON_Lg    0x4c67
+/* Radeon */
+/* RadeonIGP */
+#define PCI_DEVICE_ID_ATI_RS100                0xcab0
+#define PCI_DEVICE_ID_ATI_RS200                0xcab2
+#define PCI_DEVICE_ID_ATI_RS200_B      0xcbb2
+#define PCI_DEVICE_ID_ATI_RS250                0xcab3
+#define PCI_DEVICE_ID_ATI_RS300_100    0x5830
+#define PCI_DEVICE_ID_ATI_RS300_133    0x5831
+#define PCI_DEVICE_ID_ATI_RS300_166    0x5832
+#define PCI_DEVICE_ID_ATI_RS300_200    0x5833
+#define PCI_DEVICE_ID_ATI_RS350_100     0x7830
+#define PCI_DEVICE_ID_ATI_RS350_133     0x7831
+#define PCI_DEVICE_ID_ATI_RS350_166     0x7832
+#define PCI_DEVICE_ID_ATI_RS350_200     0x7833
+#define PCI_DEVICE_ID_ATI_RS400_100     0x5a30
+#define PCI_DEVICE_ID_ATI_RS400_133     0x5a31
+#define PCI_DEVICE_ID_ATI_RS400_166     0x5a32
+#define PCI_DEVICE_ID_ATI_RS400_200     0x5a33
+#define PCI_DEVICE_ID_ATI_RS480         0x5950
+/* ATI IXP Chipset */
+#define PCI_DEVICE_ID_ATI_IXP200_IDE   0x4349
+#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353
+#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363
+#define PCI_DEVICE_ID_ATI_IXP300_IDE   0x4369
+#define PCI_DEVICE_ID_ATI_IXP300_SATA   0x436e
+#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372
+#define PCI_DEVICE_ID_ATI_IXP400_IDE   0x4376
+#define PCI_DEVICE_ID_ATI_IXP400_SATA   0x4379
+#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a
+#define PCI_DEVICE_ID_ATI_IXP600_SATA  0x4380
+#define PCI_DEVICE_ID_ATI_SBX00_SMBUS  0x4385
+#define PCI_DEVICE_ID_ATI_IXP600_IDE   0x438c
+#define PCI_DEVICE_ID_ATI_IXP700_SATA  0x4390
+#define PCI_DEVICE_ID_ATI_IXP700_IDE   0x439c
+
+#define PCI_VENDOR_ID_VLSI             0x1004
+#define PCI_DEVICE_ID_VLSI_82C592      0x0005
+#define PCI_DEVICE_ID_VLSI_82C593      0x0006
+#define PCI_DEVICE_ID_VLSI_82C594      0x0007
+#define PCI_DEVICE_ID_VLSI_82C597      0x0009
+#define PCI_DEVICE_ID_VLSI_82C541      0x000c
+#define PCI_DEVICE_ID_VLSI_82C543      0x000d
+#define PCI_DEVICE_ID_VLSI_82C532      0x0101
+#define PCI_DEVICE_ID_VLSI_82C534      0x0102
+#define PCI_DEVICE_ID_VLSI_82C535      0x0104
+#define PCI_DEVICE_ID_VLSI_82C147      0x0105
+#define PCI_DEVICE_ID_VLSI_VAS96011    0x0702
+
+#define PCI_VENDOR_ID_ADL              0x1005
+#define PCI_DEVICE_ID_ADL_2301         0x2301
+
+#define PCI_VENDOR_ID_NS               0x100b
+#define PCI_DEVICE_ID_NS_87415         0x0002
+#define PCI_DEVICE_ID_NS_87560_LIO     0x000e
+#define PCI_DEVICE_ID_NS_87560_USB     0x0012
+#define PCI_DEVICE_ID_NS_83815         0x0020
+#define PCI_DEVICE_ID_NS_83820         0x0022
+#define PCI_DEVICE_ID_NS_CS5535_ISA    0x002b
+#define PCI_DEVICE_ID_NS_CS5535_IDE    0x002d
+#define PCI_DEVICE_ID_NS_CS5535_AUDIO  0x002e
+#define PCI_DEVICE_ID_NS_CS5535_USB    0x002f
+#define PCI_DEVICE_ID_NS_GX_VIDEO      0x0030
+#define PCI_DEVICE_ID_NS_SATURN                0x0035
+#define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500
+#define PCI_DEVICE_ID_NS_SCx200_SMI    0x0501
+#define PCI_DEVICE_ID_NS_SCx200_IDE    0x0502
+#define PCI_DEVICE_ID_NS_SCx200_AUDIO  0x0503
+#define PCI_DEVICE_ID_NS_SCx200_VIDEO  0x0504
+#define PCI_DEVICE_ID_NS_SCx200_XBUS   0x0505
+#define PCI_DEVICE_ID_NS_SC1100_BRIDGE 0x0510
+#define PCI_DEVICE_ID_NS_SC1100_SMI    0x0511
+#define PCI_DEVICE_ID_NS_SC1100_XBUS   0x0515
+#define PCI_DEVICE_ID_NS_87410         0xd001
+
+#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE  0x0028
+
+#define PCI_VENDOR_ID_TSENG            0x100c
+#define PCI_DEVICE_ID_TSENG_W32P_2     0x3202
+#define PCI_DEVICE_ID_TSENG_W32P_b     0x3205
+#define PCI_DEVICE_ID_TSENG_W32P_c     0x3206
+#define PCI_DEVICE_ID_TSENG_W32P_d     0x3207
+#define PCI_DEVICE_ID_TSENG_ET6000     0x3208
+
+#define PCI_VENDOR_ID_WEITEK           0x100e
+#define PCI_DEVICE_ID_WEITEK_P9000     0x9001
+#define PCI_DEVICE_ID_WEITEK_P9100     0x9100
+
+#define PCI_VENDOR_ID_DEC              0x1011
+#define PCI_DEVICE_ID_DEC_BRD          0x0001
+#define PCI_DEVICE_ID_DEC_TULIP                0x0002
+#define PCI_DEVICE_ID_DEC_TGA          0x0004
+#define PCI_DEVICE_ID_DEC_TULIP_FAST   0x0009
+#define PCI_DEVICE_ID_DEC_TGA2         0x000D
+#define PCI_DEVICE_ID_DEC_FDDI         0x000F
+#define PCI_DEVICE_ID_DEC_TULIP_PLUS   0x0014
+#define PCI_DEVICE_ID_DEC_21142                0x0019
+#define PCI_DEVICE_ID_DEC_21052                0x0021
+#define PCI_DEVICE_ID_DEC_21150                0x0022
+#define PCI_DEVICE_ID_DEC_21152                0x0024
+#define PCI_DEVICE_ID_DEC_21153                0x0025
+#define PCI_DEVICE_ID_DEC_21154                0x0026
+#define PCI_DEVICE_ID_DEC_21285                0x1065
+#define PCI_DEVICE_ID_COMPAQ_42XX      0x0046
+
+#define PCI_VENDOR_ID_CIRRUS           0x1013
+#define PCI_DEVICE_ID_CIRRUS_7548      0x0038
+#define PCI_DEVICE_ID_CIRRUS_5430      0x00a0
+#define PCI_DEVICE_ID_CIRRUS_5434_4    0x00a4
+#define PCI_DEVICE_ID_CIRRUS_5434_8    0x00a8
+#define PCI_DEVICE_ID_CIRRUS_5436      0x00ac
+#define PCI_DEVICE_ID_CIRRUS_5446      0x00b8
+#define PCI_DEVICE_ID_CIRRUS_5480      0x00bc
+#define PCI_DEVICE_ID_CIRRUS_5462      0x00d0
+#define PCI_DEVICE_ID_CIRRUS_5464      0x00d4
+#define PCI_DEVICE_ID_CIRRUS_5465      0x00d6
+#define PCI_DEVICE_ID_CIRRUS_6729      0x1100
+#define PCI_DEVICE_ID_CIRRUS_6832      0x1110
+#define PCI_DEVICE_ID_CIRRUS_7543      0x1202
+#define PCI_DEVICE_ID_CIRRUS_4610      0x6001
+#define PCI_DEVICE_ID_CIRRUS_4612      0x6003
+#define PCI_DEVICE_ID_CIRRUS_4615      0x6004
+
+#define PCI_VENDOR_ID_IBM              0x1014
+#define PCI_DEVICE_ID_IBM_TR           0x0018
+#define PCI_DEVICE_ID_IBM_TR_WAKE      0x003e
+#define PCI_DEVICE_ID_IBM_CPC710_PCI64 0x00fc
+#define PCI_DEVICE_ID_IBM_SNIPE                0x0180
+#define PCI_DEVICE_ID_IBM_CITRINE              0x028C
+#define PCI_DEVICE_ID_IBM_GEMSTONE             0xB166
+#define PCI_DEVICE_ID_IBM_OBSIDIAN             0x02BD
+#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1        0x0031
+#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2        0x0219
+#define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX                0x021A
+#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM    0x0251
+#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
+#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
+
+#define PCI_VENDOR_ID_UNISYS           0x1018
+#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C
+
+#define PCI_VENDOR_ID_COMPEX2          0x101a /* pci.ids says "AT&T GIS (NCR)" */
+#define PCI_DEVICE_ID_COMPEX2_100VG    0x0005
+
+#define PCI_VENDOR_ID_WD               0x101c
+#define PCI_DEVICE_ID_WD_90C           0xc24a
+
+#define PCI_VENDOR_ID_AMI              0x101e
+#define PCI_DEVICE_ID_AMI_MEGARAID3    0x1960
+#define PCI_DEVICE_ID_AMI_MEGARAID     0x9010
+#define PCI_DEVICE_ID_AMI_MEGARAID2    0x9060
+
+#define PCI_VENDOR_ID_AMD              0x1022
+#define PCI_DEVICE_ID_AMD_K8_NB                0x1100
+#define PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP        0x1101
+#define PCI_DEVICE_ID_AMD_K8_NB_MEMCTL 0x1102
+#define PCI_DEVICE_ID_AMD_K8_NB_MISC   0x1103
+#define PCI_DEVICE_ID_AMD_10H_NB_HT    0x1200
+#define PCI_DEVICE_ID_AMD_10H_NB_MAP   0x1201
+#define PCI_DEVICE_ID_AMD_10H_NB_DRAM  0x1202
+#define PCI_DEVICE_ID_AMD_10H_NB_MISC  0x1203
+#define PCI_DEVICE_ID_AMD_10H_NB_LINK  0x1204
+#define PCI_DEVICE_ID_AMD_11H_NB_HT    0x1300
+#define PCI_DEVICE_ID_AMD_11H_NB_MAP   0x1301
+#define PCI_DEVICE_ID_AMD_11H_NB_DRAM  0x1302
+#define PCI_DEVICE_ID_AMD_11H_NB_MISC  0x1303
+#define PCI_DEVICE_ID_AMD_11H_NB_LINK  0x1304
+#define PCI_DEVICE_ID_AMD_LANCE                0x2000
+#define PCI_DEVICE_ID_AMD_LANCE_HOME   0x2001
+#define PCI_DEVICE_ID_AMD_SCSI         0x2020
+#define PCI_DEVICE_ID_AMD_SERENADE     0x36c0
+#define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006
+#define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007
+#define PCI_DEVICE_ID_AMD_FE_GATE_700C 0x700C
+#define PCI_DEVICE_ID_AMD_FE_GATE_700E 0x700E
+#define PCI_DEVICE_ID_AMD_COBRA_7401   0x7401
+#define PCI_DEVICE_ID_AMD_VIPER_7409   0x7409
+#define PCI_DEVICE_ID_AMD_VIPER_740B   0x740B
+#define PCI_DEVICE_ID_AMD_VIPER_7410   0x7410
+#define PCI_DEVICE_ID_AMD_VIPER_7411   0x7411
+#define PCI_DEVICE_ID_AMD_VIPER_7413   0x7413
+#define PCI_DEVICE_ID_AMD_VIPER_7440   0x7440
+#define PCI_DEVICE_ID_AMD_OPUS_7441    0x7441
+#define PCI_DEVICE_ID_AMD_OPUS_7443    0x7443
+#define PCI_DEVICE_ID_AMD_VIPER_7443   0x7443
+#define PCI_DEVICE_ID_AMD_OPUS_7445    0x7445
+#define PCI_DEVICE_ID_AMD_8111_LPC     0x7468
+#define PCI_DEVICE_ID_AMD_8111_IDE     0x7469
+#define PCI_DEVICE_ID_AMD_8111_SMBUS2  0x746a
+#define PCI_DEVICE_ID_AMD_8111_SMBUS   0x746b
+#define PCI_DEVICE_ID_AMD_8111_AUDIO   0x746d
+#define PCI_DEVICE_ID_AMD_8151_0       0x7454
+#define PCI_DEVICE_ID_AMD_8131_BRIDGE  0x7450
+#define PCI_DEVICE_ID_AMD_8131_APIC    0x7451
+#define PCI_DEVICE_ID_AMD_8132_BRIDGE  0x7458
+#define PCI_DEVICE_ID_AMD_CS5536_ISA    0x2090
+#define PCI_DEVICE_ID_AMD_CS5536_FLASH  0x2091
+#define PCI_DEVICE_ID_AMD_CS5536_AUDIO  0x2093
+#define PCI_DEVICE_ID_AMD_CS5536_OHC    0x2094
+#define PCI_DEVICE_ID_AMD_CS5536_EHC    0x2095
+#define PCI_DEVICE_ID_AMD_CS5536_UDC    0x2096
+#define PCI_DEVICE_ID_AMD_CS5536_UOC    0x2097
+#define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
+
+#define PCI_DEVICE_ID_AMD_LX_VIDEO  0x2081
+#define PCI_DEVICE_ID_AMD_LX_AES    0x2082
+
+#define PCI_VENDOR_ID_TRIDENT          0x1023
+#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX        0x2000
+#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX        0x2001
+#define PCI_DEVICE_ID_TRIDENT_9320     0x9320
+#define PCI_DEVICE_ID_TRIDENT_9388     0x9388
+#define PCI_DEVICE_ID_TRIDENT_9397     0x9397
+#define PCI_DEVICE_ID_TRIDENT_939A     0x939A
+#define PCI_DEVICE_ID_TRIDENT_9520     0x9520
+#define PCI_DEVICE_ID_TRIDENT_9525     0x9525
+#define PCI_DEVICE_ID_TRIDENT_9420     0x9420
+#define PCI_DEVICE_ID_TRIDENT_9440     0x9440
+#define PCI_DEVICE_ID_TRIDENT_9660     0x9660
+#define PCI_DEVICE_ID_TRIDENT_9750     0x9750
+#define PCI_DEVICE_ID_TRIDENT_9850     0x9850
+#define PCI_DEVICE_ID_TRIDENT_9880     0x9880
+#define PCI_DEVICE_ID_TRIDENT_8400     0x8400
+#define PCI_DEVICE_ID_TRIDENT_8420     0x8420
+#define PCI_DEVICE_ID_TRIDENT_8500     0x8500
+
+#define PCI_VENDOR_ID_AI               0x1025
+#define PCI_DEVICE_ID_AI_M1435         0x1435
+
+#define PCI_VENDOR_ID_DELL             0x1028
+#define PCI_DEVICE_ID_DELL_RACIII      0x0008
+#define PCI_DEVICE_ID_DELL_RAC4                0x0012
+#define PCI_DEVICE_ID_DELL_PERC5       0x0015
+
+#define PCI_VENDOR_ID_MATROX           0x102B
+#define PCI_DEVICE_ID_MATROX_MGA_2     0x0518
+#define PCI_DEVICE_ID_MATROX_MIL       0x0519
+#define PCI_DEVICE_ID_MATROX_MYS       0x051A
+#define PCI_DEVICE_ID_MATROX_MIL_2     0x051b
+#define PCI_DEVICE_ID_MATROX_MYS_AGP   0x051e
+#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f
+#define PCI_DEVICE_ID_MATROX_MGA_IMP   0x0d10
+#define PCI_DEVICE_ID_MATROX_G100_MM   0x1000
+#define PCI_DEVICE_ID_MATROX_G100_AGP  0x1001
+#define PCI_DEVICE_ID_MATROX_G200_PCI  0x0520
+#define PCI_DEVICE_ID_MATROX_G200_AGP  0x0521
+#define        PCI_DEVICE_ID_MATROX_G400       0x0525
+#define        PCI_DEVICE_ID_MATROX_G200EV_PCI 0x0530
+#define PCI_DEVICE_ID_MATROX_G550      0x2527
+#define PCI_DEVICE_ID_MATROX_VIA       0x4536
+
+#define PCI_VENDOR_ID_CT               0x102c
+#define PCI_DEVICE_ID_CT_69000         0x00c0
+#define PCI_DEVICE_ID_CT_65545         0x00d8
+#define PCI_DEVICE_ID_CT_65548         0x00dc
+#define PCI_DEVICE_ID_CT_65550         0x00e0
+#define PCI_DEVICE_ID_CT_65554         0x00e4
+#define PCI_DEVICE_ID_CT_65555         0x00e5
+
+#define PCI_VENDOR_ID_MIRO             0x1031
+#define PCI_DEVICE_ID_MIRO_36050       0x5601
+#define PCI_DEVICE_ID_MIRO_DC10PLUS    0x7efe
+#define PCI_DEVICE_ID_MIRO_DC30PLUS    0xd801
+
+#define PCI_VENDOR_ID_NEC              0x1033
+#define PCI_DEVICE_ID_NEC_CBUS_1       0x0001 /* PCI-Cbus Bridge */
+#define PCI_DEVICE_ID_NEC_LOCAL                0x0002 /* Local Bridge */
+#define PCI_DEVICE_ID_NEC_ATM          0x0003 /* ATM LAN Controller */
+#define PCI_DEVICE_ID_NEC_R4000                0x0004 /* R4000 Bridge */
+#define PCI_DEVICE_ID_NEC_486          0x0005 /* 486 Like Peripheral Bus Bridge */
+#define PCI_DEVICE_ID_NEC_ACCEL_1      0x0006 /* Graphic Accelerator */
+#define PCI_DEVICE_ID_NEC_UXBUS                0x0007 /* UX-Bus Bridge */
+#define PCI_DEVICE_ID_NEC_ACCEL_2      0x0008 /* Graphic Accelerator */
+#define PCI_DEVICE_ID_NEC_GRAPH                0x0009 /* PCI-CoreGraph Bridge */
+#define PCI_DEVICE_ID_NEC_VL           0x0016 /* PCI-VL Bridge */
+#define PCI_DEVICE_ID_NEC_STARALPHA2   0x002c /* STAR ALPHA2 */
+#define PCI_DEVICE_ID_NEC_CBUS_2       0x002d /* PCI-Cbus Bridge */
+#define PCI_DEVICE_ID_NEC_USB          0x0035 /* PCI-USB Host */
+#define PCI_DEVICE_ID_NEC_CBUS_3       0x003b
+#define PCI_DEVICE_ID_NEC_NAPCCARD     0x003e
+#define PCI_DEVICE_ID_NEC_PCX2         0x0046 /* PowerVR */
+#define PCI_DEVICE_ID_NEC_VRC5476       0x009b
+#define PCI_DEVICE_ID_NEC_VRC4173      0x00a5
+#define PCI_DEVICE_ID_NEC_VRC5477_AC97  0x00a6
+#define PCI_DEVICE_ID_NEC_PC9821CS01    0x800c /* PC-9821-CS01 */
+#define PCI_DEVICE_ID_NEC_PC9821NRB06   0x800d /* PC-9821NR-B06 */
+
+#define PCI_VENDOR_ID_FD               0x1036
+#define PCI_DEVICE_ID_FD_36C70         0x0000
+
+#define PCI_VENDOR_ID_SI               0x1039
+#define PCI_DEVICE_ID_SI_5591_AGP      0x0001
+#define PCI_DEVICE_ID_SI_6202          0x0002
+#define PCI_DEVICE_ID_SI_503           0x0008
+#define PCI_DEVICE_ID_SI_ACPI          0x0009
+#define PCI_DEVICE_ID_SI_SMBUS         0x0016
+#define PCI_DEVICE_ID_SI_LPC           0x0018
+#define PCI_DEVICE_ID_SI_5597_VGA      0x0200
+#define PCI_DEVICE_ID_SI_6205          0x0205
+#define PCI_DEVICE_ID_SI_501           0x0406
+#define PCI_DEVICE_ID_SI_496           0x0496
+#define PCI_DEVICE_ID_SI_300           0x0300
+#define PCI_DEVICE_ID_SI_315H          0x0310
+#define PCI_DEVICE_ID_SI_315           0x0315
+#define PCI_DEVICE_ID_SI_315PRO                0x0325
+#define PCI_DEVICE_ID_SI_530           0x0530
+#define PCI_DEVICE_ID_SI_540           0x0540
+#define PCI_DEVICE_ID_SI_550           0x0550
+#define PCI_DEVICE_ID_SI_540_VGA       0x5300
+#define PCI_DEVICE_ID_SI_550_VGA       0x5315
+#define PCI_DEVICE_ID_SI_620           0x0620
+#define PCI_DEVICE_ID_SI_630           0x0630
+#define PCI_DEVICE_ID_SI_633           0x0633
+#define PCI_DEVICE_ID_SI_635           0x0635
+#define PCI_DEVICE_ID_SI_640           0x0640
+#define PCI_DEVICE_ID_SI_645           0x0645
+#define PCI_DEVICE_ID_SI_646           0x0646
+#define PCI_DEVICE_ID_SI_648           0x0648
+#define PCI_DEVICE_ID_SI_650           0x0650
+#define PCI_DEVICE_ID_SI_651           0x0651
+#define PCI_DEVICE_ID_SI_655           0x0655
+#define PCI_DEVICE_ID_SI_661           0x0661
+#define PCI_DEVICE_ID_SI_730           0x0730
+#define PCI_DEVICE_ID_SI_733           0x0733
+#define PCI_DEVICE_ID_SI_630_VGA       0x6300
+#define PCI_DEVICE_ID_SI_735           0x0735
+#define PCI_DEVICE_ID_SI_740           0x0740
+#define PCI_DEVICE_ID_SI_741           0x0741
+#define PCI_DEVICE_ID_SI_745           0x0745
+#define PCI_DEVICE_ID_SI_746           0x0746
+#define PCI_DEVICE_ID_SI_755           0x0755
+#define PCI_DEVICE_ID_SI_760           0x0760
+#define PCI_DEVICE_ID_SI_900           0x0900
+#define PCI_DEVICE_ID_SI_961           0x0961
+#define PCI_DEVICE_ID_SI_962           0x0962
+#define PCI_DEVICE_ID_SI_963           0x0963
+#define PCI_DEVICE_ID_SI_965           0x0965
+#define PCI_DEVICE_ID_SI_966           0x0966
+#define PCI_DEVICE_ID_SI_968           0x0968
+#define PCI_DEVICE_ID_SI_1180          0x1180
+#define PCI_DEVICE_ID_SI_5511          0x5511
+#define PCI_DEVICE_ID_SI_5513          0x5513
+#define PCI_DEVICE_ID_SI_5517          0x5517
+#define PCI_DEVICE_ID_SI_5518          0x5518
+#define PCI_DEVICE_ID_SI_5571          0x5571
+#define PCI_DEVICE_ID_SI_5581          0x5581
+#define PCI_DEVICE_ID_SI_5582          0x5582
+#define PCI_DEVICE_ID_SI_5591          0x5591
+#define PCI_DEVICE_ID_SI_5596          0x5596
+#define PCI_DEVICE_ID_SI_5597          0x5597
+#define PCI_DEVICE_ID_SI_5598          0x5598
+#define PCI_DEVICE_ID_SI_5600          0x5600
+#define PCI_DEVICE_ID_SI_7012          0x7012
+#define PCI_DEVICE_ID_SI_7013          0x7013
+#define PCI_DEVICE_ID_SI_7016          0x7016
+#define PCI_DEVICE_ID_SI_7018          0x7018
+
+#define PCI_VENDOR_ID_HP               0x103c
+#define PCI_DEVICE_ID_HP_VISUALIZE_EG  0x1005
+#define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006
+#define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008
+#define PCI_DEVICE_ID_HP_VISUALIZE_FX2 0x100a
+#define PCI_DEVICE_ID_HP_TACHYON       0x1028
+#define PCI_DEVICE_ID_HP_TACHLITE      0x1029
+#define PCI_DEVICE_ID_HP_J2585A                0x1030
+#define PCI_DEVICE_ID_HP_J2585B                0x1031
+#define PCI_DEVICE_ID_HP_J2973A                0x1040
+#define PCI_DEVICE_ID_HP_J2970A                0x1042
+#define PCI_DEVICE_ID_HP_DIVA          0x1048
+#define PCI_DEVICE_ID_HP_DIVA_TOSCA1   0x1049
+#define PCI_DEVICE_ID_HP_DIVA_TOSCA2   0x104A
+#define PCI_DEVICE_ID_HP_DIVA_MAESTRO  0x104B
+#define PCI_DEVICE_ID_HP_REO_IOC       0x10f1
+#define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b
+#define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223
+#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226
+#define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227
+#define PCI_DEVICE_ID_HP_ZX1_IOC       0x122a
+#define PCI_DEVICE_ID_HP_PCIX_LBA      0x122e
+#define PCI_DEVICE_ID_HP_SX1000_IOC    0x127c
+#define PCI_DEVICE_ID_HP_DIVA_EVEREST  0x1282
+#define PCI_DEVICE_ID_HP_DIVA_AUX      0x1290
+#define PCI_DEVICE_ID_HP_DIVA_RMP3     0x1301
+#define PCI_DEVICE_ID_HP_DIVA_HURRICANE        0x132a
+#define PCI_DEVICE_ID_HP_CISSA         0x3220
+#define PCI_DEVICE_ID_HP_CISSC         0x3230
+#define PCI_DEVICE_ID_HP_CISSD         0x3238
+#define PCI_DEVICE_ID_HP_CISSE         0x323a
+#define PCI_DEVICE_ID_HP_ZX2_IOC       0x4031
+
+#define PCI_VENDOR_ID_PCTECH           0x1042
+#define PCI_DEVICE_ID_PCTECH_RZ1000    0x1000
+#define PCI_DEVICE_ID_PCTECH_RZ1001    0x1001
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
+
+#define PCI_VENDOR_ID_ASUSTEK          0x1043
+#define PCI_DEVICE_ID_ASUSTEK_0675     0x0675
+
+#define PCI_VENDOR_ID_DPT              0x1044
+#define PCI_DEVICE_ID_DPT              0xa400
+
+#define PCI_VENDOR_ID_OPTI             0x1045
+#define PCI_DEVICE_ID_OPTI_82C558      0xc558
+#define PCI_DEVICE_ID_OPTI_82C621      0xc621
+#define PCI_DEVICE_ID_OPTI_82C700      0xc700
+#define PCI_DEVICE_ID_OPTI_82C825      0xd568
+
+#define PCI_VENDOR_ID_ELSA             0x1048
+#define PCI_DEVICE_ID_ELSA_MICROLINK   0x1000
+#define PCI_DEVICE_ID_ELSA_QS3000      0x3000
+
+#define PCI_VENDOR_ID_BUSLOGIC               0x104B
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER    0x1040
+#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT     0x8130
+
+#define PCI_VENDOR_ID_TI               0x104c
+#define PCI_DEVICE_ID_TI_TVP4020       0x3d07
+#define PCI_DEVICE_ID_TI_4450          0x8011
+#define PCI_DEVICE_ID_TI_TSB43AB22     0x8023
+#define PCI_DEVICE_ID_TI_XX21_XX11     0x8031
+#define PCI_DEVICE_ID_TI_XX21_XX11_FM  0x8033
+#define PCI_DEVICE_ID_TI_XX21_XX11_SD  0x8034
+#define PCI_DEVICE_ID_TI_X515          0x8036
+#define PCI_DEVICE_ID_TI_XX12          0x8039
+#define PCI_DEVICE_ID_TI_XX12_FM       0x803b
+#define PCI_DEVICE_ID_TI_1130          0xac12
+#define PCI_DEVICE_ID_TI_1031          0xac13
+#define PCI_DEVICE_ID_TI_1131          0xac15
+#define PCI_DEVICE_ID_TI_1250          0xac16
+#define PCI_DEVICE_ID_TI_1220          0xac17
+#define PCI_DEVICE_ID_TI_1221          0xac19
+#define PCI_DEVICE_ID_TI_1210          0xac1a
+#define PCI_DEVICE_ID_TI_1450          0xac1b
+#define PCI_DEVICE_ID_TI_1225          0xac1c
+#define PCI_DEVICE_ID_TI_1251A         0xac1d
+#define PCI_DEVICE_ID_TI_1211          0xac1e
+#define PCI_DEVICE_ID_TI_1251B         0xac1f
+#define PCI_DEVICE_ID_TI_4410          0xac41
+#define PCI_DEVICE_ID_TI_4451          0xac42
+#define PCI_DEVICE_ID_TI_4510          0xac44
+#define PCI_DEVICE_ID_TI_4520          0xac46
+#define PCI_DEVICE_ID_TI_7510          0xac47
+#define PCI_DEVICE_ID_TI_7610          0xac48
+#define PCI_DEVICE_ID_TI_7410          0xac49
+#define PCI_DEVICE_ID_TI_1410          0xac50
+#define PCI_DEVICE_ID_TI_1420          0xac51
+#define PCI_DEVICE_ID_TI_1451A         0xac52
+#define PCI_DEVICE_ID_TI_1620          0xac54
+#define PCI_DEVICE_ID_TI_1520          0xac55
+#define PCI_DEVICE_ID_TI_1510          0xac56
+#define PCI_DEVICE_ID_TI_X620          0xac8d
+#define PCI_DEVICE_ID_TI_X420          0xac8e
+#define PCI_DEVICE_ID_TI_XX20_FM       0xac8f
+
+#define PCI_VENDOR_ID_SONY             0x104d
+
+/* Winbond have two vendor IDs! See 0x10ad as well */
+#define PCI_VENDOR_ID_WINBOND2         0x1050
+#define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a
+#define PCI_DEVICE_ID_WINBOND2_6692    0x6692
+
+#define PCI_VENDOR_ID_ANIGMA           0x1051
+#define PCI_DEVICE_ID_ANIGMA_MC145575  0x0100
+  
+#define PCI_VENDOR_ID_EFAR             0x1055
+#define PCI_DEVICE_ID_EFAR_SLC90E66_1  0x9130
+#define PCI_DEVICE_ID_EFAR_SLC90E66_3  0x9463
+
+#define PCI_VENDOR_ID_MOTOROLA         0x1057
+#define PCI_DEVICE_ID_MOTOROLA_MPC105  0x0001
+#define PCI_DEVICE_ID_MOTOROLA_MPC106  0x0002
+#define PCI_DEVICE_ID_MOTOROLA_MPC107  0x0004
+#define PCI_DEVICE_ID_MOTOROLA_RAVEN   0x4801
+#define PCI_DEVICE_ID_MOTOROLA_FALCON  0x4802
+#define PCI_DEVICE_ID_MOTOROLA_HAWK    0x4803
+#define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b
+#define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803
+#define PCI_DEVICE_ID_MOTOROLA_MPC5200B        0x5809
+
+#define PCI_VENDOR_ID_PROMISE          0x105a
+#define PCI_DEVICE_ID_PROMISE_20265    0x0d30
+#define PCI_DEVICE_ID_PROMISE_20267    0x4d30
+#define PCI_DEVICE_ID_PROMISE_20246    0x4d33
+#define PCI_DEVICE_ID_PROMISE_20262    0x4d38
+#define PCI_DEVICE_ID_PROMISE_20263    0x0D38
+#define PCI_DEVICE_ID_PROMISE_20268    0x4d68
+#define PCI_DEVICE_ID_PROMISE_20269    0x4d69
+#define PCI_DEVICE_ID_PROMISE_20270    0x6268
+#define PCI_DEVICE_ID_PROMISE_20271    0x6269
+#define PCI_DEVICE_ID_PROMISE_20275    0x1275
+#define PCI_DEVICE_ID_PROMISE_20276    0x5275
+#define PCI_DEVICE_ID_PROMISE_20277    0x7275
+
+#define PCI_VENDOR_ID_UMC              0x1060
+#define PCI_DEVICE_ID_UMC_UM8673F      0x0101
+#define PCI_DEVICE_ID_UMC_UM8886BF     0x673a
+#define PCI_DEVICE_ID_UMC_UM8886A      0x886a
+
+#define PCI_VENDOR_ID_PICOPOWER                0x1066
+#define PCI_DEVICE_ID_PICOPOWER_PT86C523       0x0002
+#define PCI_DEVICE_ID_PICOPOWER_PT86C523BBP    0x8002
+
+#define PCI_VENDOR_ID_MYLEX            0x1069
+#define PCI_DEVICE_ID_MYLEX_DAC960_P   0x0001
+#define PCI_DEVICE_ID_MYLEX_DAC960_PD  0x0002
+#define PCI_DEVICE_ID_MYLEX_DAC960_PG  0x0010
+#define PCI_DEVICE_ID_MYLEX_DAC960_LA  0x0020
+#define PCI_DEVICE_ID_MYLEX_DAC960_LP  0x0050
+#define PCI_DEVICE_ID_MYLEX_DAC960_BA  0xBA56
+#define PCI_DEVICE_ID_MYLEX_DAC960_GEM 0xB166
+
+#define PCI_VENDOR_ID_APPLE            0x106b
+#define PCI_DEVICE_ID_APPLE_BANDIT     0x0001
+#define PCI_DEVICE_ID_APPLE_HYDRA      0x000e
+#define PCI_DEVICE_ID_APPLE_UNI_N_FW   0x0018
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP  0x0020
+#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021
+#define PCI_DEVICE_ID_APPLE_UNI_N_GMACP        0x0024
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P        0x0027
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP15        0x002d
+#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15        0x002e
+#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2        0x0032
+#define PCI_DEVICE_ID_APPLE_UNI_N_ATA  0x0033
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP2 0x0034
+#define PCI_DEVICE_ID_APPLE_IPID_ATA100        0x003b
+#define PCI_DEVICE_ID_APPLE_K2_ATA100  0x0043
+#define PCI_DEVICE_ID_APPLE_U3_AGP     0x004b
+#define PCI_DEVICE_ID_APPLE_K2_GMAC    0x004c
+#define PCI_DEVICE_ID_APPLE_SH_ATA      0x0050
+#define PCI_DEVICE_ID_APPLE_SH_SUNGEM   0x0051
+#define PCI_DEVICE_ID_APPLE_U3L_AGP    0x0058
+#define PCI_DEVICE_ID_APPLE_U3H_AGP    0x0059
+#define PCI_DEVICE_ID_APPLE_IPID2_AGP  0x0066
+#define PCI_DEVICE_ID_APPLE_IPID2_ATA  0x0069
+#define PCI_DEVICE_ID_APPLE_IPID2_FW   0x006a
+#define PCI_DEVICE_ID_APPLE_IPID2_GMAC 0x006b
+#define PCI_DEVICE_ID_APPLE_TIGON3     0x1645
+
+#define PCI_VENDOR_ID_YAMAHA           0x1073
+#define PCI_DEVICE_ID_YAMAHA_724       0x0004
+#define PCI_DEVICE_ID_YAMAHA_724F      0x000d
+#define PCI_DEVICE_ID_YAMAHA_740       0x000a
+#define PCI_DEVICE_ID_YAMAHA_740C      0x000c
+#define PCI_DEVICE_ID_YAMAHA_744       0x0010
+#define PCI_DEVICE_ID_YAMAHA_754       0x0012
+
+#define PCI_VENDOR_ID_QLOGIC           0x1077
+#define PCI_DEVICE_ID_QLOGIC_ISP10160  0x1016
+#define PCI_DEVICE_ID_QLOGIC_ISP1020   0x1020
+#define PCI_DEVICE_ID_QLOGIC_ISP1080   0x1080
+#define PCI_DEVICE_ID_QLOGIC_ISP12160  0x1216
+#define PCI_DEVICE_ID_QLOGIC_ISP1240   0x1240
+#define PCI_DEVICE_ID_QLOGIC_ISP1280   0x1280
+#define PCI_DEVICE_ID_QLOGIC_ISP2100   0x2100
+#define PCI_DEVICE_ID_QLOGIC_ISP2200   0x2200
+#define PCI_DEVICE_ID_QLOGIC_ISP2300   0x2300
+#define PCI_DEVICE_ID_QLOGIC_ISP2312   0x2312
+#define PCI_DEVICE_ID_QLOGIC_ISP2322   0x2322
+#define PCI_DEVICE_ID_QLOGIC_ISP6312   0x6312
+#define PCI_DEVICE_ID_QLOGIC_ISP6322   0x6322
+#define PCI_DEVICE_ID_QLOGIC_ISP2422   0x2422
+#define PCI_DEVICE_ID_QLOGIC_ISP2432   0x2432
+#define PCI_DEVICE_ID_QLOGIC_ISP2512   0x2512
+#define PCI_DEVICE_ID_QLOGIC_ISP2522   0x2522
+#define PCI_DEVICE_ID_QLOGIC_ISP5422   0x5422
+#define PCI_DEVICE_ID_QLOGIC_ISP5432   0x5432
+
+#define PCI_VENDOR_ID_CYRIX            0x1078
+#define PCI_DEVICE_ID_CYRIX_5510       0x0000
+#define PCI_DEVICE_ID_CYRIX_PCI_MASTER 0x0001
+#define PCI_DEVICE_ID_CYRIX_5520       0x0002
+#define PCI_DEVICE_ID_CYRIX_5530_LEGACY        0x0100
+#define PCI_DEVICE_ID_CYRIX_5530_IDE   0x0102
+#define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103
+#define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104
+
+#define PCI_VENDOR_ID_CONTAQ           0x1080
+#define PCI_DEVICE_ID_CONTAQ_82C693    0xc693
+
+#define PCI_VENDOR_ID_OLICOM           0x108d
+#define PCI_DEVICE_ID_OLICOM_OC2325    0x0012
+#define PCI_DEVICE_ID_OLICOM_OC2183    0x0013
+#define PCI_DEVICE_ID_OLICOM_OC2326    0x0014
+
+#define PCI_VENDOR_ID_SUN              0x108e
+#define PCI_DEVICE_ID_SUN_EBUS         0x1000
+#define PCI_DEVICE_ID_SUN_HAPPYMEAL    0x1001
+#define PCI_DEVICE_ID_SUN_RIO_EBUS     0x1100
+#define PCI_DEVICE_ID_SUN_RIO_GEM      0x1101
+#define PCI_DEVICE_ID_SUN_RIO_1394     0x1102
+#define PCI_DEVICE_ID_SUN_RIO_USB      0x1103
+#define PCI_DEVICE_ID_SUN_GEM          0x2bad
+#define PCI_DEVICE_ID_SUN_SIMBA                0x5000
+#define PCI_DEVICE_ID_SUN_PBM          0x8000
+#define PCI_DEVICE_ID_SUN_SCHIZO       0x8001
+#define PCI_DEVICE_ID_SUN_SABRE                0xa000
+#define PCI_DEVICE_ID_SUN_HUMMINGBIRD  0xa001
+#define PCI_DEVICE_ID_SUN_TOMATILLO    0xa801
+#define PCI_DEVICE_ID_SUN_CASSINI      0xabba
+
+#define PCI_VENDOR_ID_CMD              0x1095
+#define PCI_DEVICE_ID_CMD_643          0x0643
+#define PCI_DEVICE_ID_CMD_646          0x0646
+#define PCI_DEVICE_ID_CMD_648          0x0648
+#define PCI_DEVICE_ID_CMD_649          0x0649
+
+#define PCI_DEVICE_ID_SII_680          0x0680
+#define PCI_DEVICE_ID_SII_3112         0x3112
+#define PCI_DEVICE_ID_SII_1210SA       0x0240
+
+#define PCI_VENDOR_ID_BROOKTREE                0x109e
+#define PCI_DEVICE_ID_BROOKTREE_878    0x0878
+#define PCI_DEVICE_ID_BROOKTREE_879    0x0879
+
+#define PCI_VENDOR_ID_SGI              0x10a9
+#define PCI_DEVICE_ID_SGI_IOC3         0x0003
+#define PCI_DEVICE_ID_SGI_LITHIUM      0x1002
+#define PCI_DEVICE_ID_SGI_IOC4         0x100a
+
+#define PCI_VENDOR_ID_WINBOND          0x10ad
+#define PCI_DEVICE_ID_WINBOND_82C105   0x0105
+#define PCI_DEVICE_ID_WINBOND_83C553   0x0565
+
+#define PCI_VENDOR_ID_PLX              0x10b5
+#define PCI_DEVICE_ID_PLX_R685         0x1030
+#define PCI_DEVICE_ID_PLX_ROMULUS      0x106a
+#define PCI_DEVICE_ID_PLX_SPCOM800     0x1076
+#define PCI_DEVICE_ID_PLX_1077         0x1077
+#define PCI_DEVICE_ID_PLX_SPCOM200     0x1103
+#define PCI_DEVICE_ID_PLX_DJINN_ITOO   0x1151
+#define PCI_DEVICE_ID_PLX_R753         0x1152
+#define PCI_DEVICE_ID_PLX_OLITEC       0x1187
+#define PCI_DEVICE_ID_PLX_PCI200SYN    0x3196
+#define PCI_DEVICE_ID_PLX_9030          0x9030
+#define PCI_DEVICE_ID_PLX_9050         0x9050
+#define PCI_DEVICE_ID_PLX_9080         0x9080
+#define PCI_DEVICE_ID_PLX_GTEK_SERIAL2 0xa001
+
+#define PCI_VENDOR_ID_MADGE            0x10b6
+#define PCI_DEVICE_ID_MADGE_MK2                0x0002
+
+#define PCI_VENDOR_ID_3COM             0x10b7
+#define PCI_DEVICE_ID_3COM_3C985       0x0001
+#define PCI_DEVICE_ID_3COM_3C940       0x1700
+#define PCI_DEVICE_ID_3COM_3C339       0x3390
+#define PCI_DEVICE_ID_3COM_3C359       0x3590
+#define PCI_DEVICE_ID_3COM_3C940B      0x80eb
+#define PCI_DEVICE_ID_3COM_3CR990      0x9900
+#define PCI_DEVICE_ID_3COM_3CR990_TX_95        0x9902
+#define PCI_DEVICE_ID_3COM_3CR990_TX_97        0x9903
+#define PCI_DEVICE_ID_3COM_3CR990B     0x9904
+#define PCI_DEVICE_ID_3COM_3CR990_FX   0x9905
+#define PCI_DEVICE_ID_3COM_3CR990SVR95 0x9908
+#define PCI_DEVICE_ID_3COM_3CR990SVR97 0x9909
+#define PCI_DEVICE_ID_3COM_3CR990SVR   0x990a
+
+#define PCI_VENDOR_ID_AL               0x10b9
+#define PCI_DEVICE_ID_AL_M1533         0x1533
+#define PCI_DEVICE_ID_AL_M1535                 0x1535
+#define PCI_DEVICE_ID_AL_M1541         0x1541
+#define PCI_DEVICE_ID_AL_M1563         0x1563
+#define PCI_DEVICE_ID_AL_M1621         0x1621
+#define PCI_DEVICE_ID_AL_M1631         0x1631
+#define PCI_DEVICE_ID_AL_M1632         0x1632
+#define PCI_DEVICE_ID_AL_M1641         0x1641
+#define PCI_DEVICE_ID_AL_M1644         0x1644
+#define PCI_DEVICE_ID_AL_M1647         0x1647
+#define PCI_DEVICE_ID_AL_M1651         0x1651
+#define PCI_DEVICE_ID_AL_M1671         0x1671
+#define PCI_DEVICE_ID_AL_M1681         0x1681
+#define PCI_DEVICE_ID_AL_M1683         0x1683
+#define PCI_DEVICE_ID_AL_M1689         0x1689
+#define PCI_DEVICE_ID_AL_M5219         0x5219
+#define PCI_DEVICE_ID_AL_M5228         0x5228
+#define PCI_DEVICE_ID_AL_M5229         0x5229
+#define PCI_DEVICE_ID_AL_M5451         0x5451
+#define PCI_DEVICE_ID_AL_M7101         0x7101
+
+#define PCI_VENDOR_ID_NEOMAGIC         0x10c8
+#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
+#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
+#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
+
+#define PCI_VENDOR_ID_TCONRAD          0x10da
+#define PCI_DEVICE_ID_TCONRAD_TOKENRING        0x0508
+
+#define PCI_VENDOR_ID_NVIDIA                   0x10de
+#define PCI_DEVICE_ID_NVIDIA_TNT               0x0020
+#define PCI_DEVICE_ID_NVIDIA_TNT2              0x0028
+#define PCI_DEVICE_ID_NVIDIA_UTNT2             0x0029
+#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN        0x002a
+#define PCI_DEVICE_ID_NVIDIA_VTNT2             0x002C
+#define PCI_DEVICE_ID_NVIDIA_UVTNT2            0x002D
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS        0x0034
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE  0x0035
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA 0x0036
+#define PCI_DEVICE_ID_NVIDIA_NVENET_10         0x0037
+#define PCI_DEVICE_ID_NVIDIA_NVENET_11         0x0038
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2        0x003e
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800       0x0041
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE    0x0042
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT    0x0045
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000     0x004E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS     0x0052
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE  0x0053
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA 0x0054
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2        0x0055
+#define PCI_DEVICE_ID_NVIDIA_NVENET_8          0x0056
+#define PCI_DEVICE_ID_NVIDIA_NVENET_9          0x0057
+#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO       0x0059
+#define PCI_DEVICE_ID_NVIDIA_CK804_PCIE                0x005d
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS     0x0064
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE       0x0065
+#define PCI_DEVICE_ID_NVIDIA_NVENET_2          0x0066
+#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM                0x0069
+#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO                0x006a
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS    0x0084
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE      0x0085
+#define PCI_DEVICE_ID_NVIDIA_NVENET_4          0x0086
+#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM       0x0089
+#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO         0x008a
+#define PCI_DEVICE_ID_NVIDIA_NVENET_5          0x008c
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA     0x008e
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT   0x0090
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX  0x0091
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800   0x0098
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX 0x0099
+#define PCI_DEVICE_ID_NVIDIA_ITNT2             0x00A0
+#define PCI_DEVICE_ID_GEFORCE_6800A             0x00c1
+#define PCI_DEVICE_ID_GEFORCE_6800A_LE          0x00c2
+#define PCI_DEVICE_ID_GEFORCE_GO_6800           0x00c8
+#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA     0x00c9
+#define PCI_DEVICE_ID_QUADRO_FX_GO1400          0x00cc
+#define PCI_DEVICE_ID_QUADRO_FX_1400            0x00ce
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3           0x00d1
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS     0x00d4
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE       0x00d5
+#define PCI_DEVICE_ID_NVIDIA_NVENET_3          0x00d6
+#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM                0x00d9
+#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO                0x00da
+#define PCI_DEVICE_ID_NVIDIA_NVENET_7          0x00df
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S          0x00e1
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA     0x00e3
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS    0x00e4
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE      0x00e5
+#define PCI_DEVICE_ID_NVIDIA_NVENET_6          0x00e6
+#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO                0x00ea
+#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2    0x00ee
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1 0x00f1
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT   0x00f9
+#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280    0x00fd
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR       0x0100
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR       0x0101
+#define PCI_DEVICE_ID_NVIDIA_QUADRO            0x0103
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX       0x0110
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2      0x0111
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO       0x0112
+#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR       0x0113
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT   0x0140
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600      0x0141
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL   0x0145
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540     0x014E
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200      0x014F
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS      0x0150
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2     0x0151
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA    0x0152
+#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO       0x0153
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200    0x0164
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250    0x0166
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1  0x0167
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1  0x0168
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460   0x0170
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440   0x0171
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420   0x0172
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE        0x0173
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO   0x0174
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO   0x0175
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO    0x0177
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL    0x0178
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_200       0x017A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL    0x017B
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL  0x017C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000   0x0185
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO    0x0186
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO    0x0187
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL    0x0188
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC    0x0189
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS    0x018A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL    0x018B
+#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2         0x01a0
+#define PCI_DEVICE_ID_NVIDIA_NFORCE            0x01a4
+#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO                0x01b1
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS      0x01b4
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE                0x01bc
+#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM                0x01c1
+#define PCI_DEVICE_ID_NVIDIA_NVENET_1          0x01c3
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2           0x01e0
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3          0x0200
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1                0x0201
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2                0x0202
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC                0x0203
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B      0x0211
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE   0x0212
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT   0x0215
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600  0x0250
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400  0x0251
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200  0x0253
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL    0x0258
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL    0x0259
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL    0x025B
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS        0x0264
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE  0x0265
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2        0x0267
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS        0x0368
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE  0x036E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2        0x037F
+#define PCI_DEVICE_ID_NVIDIA_NVENET_12         0x0268
+#define PCI_DEVICE_ID_NVIDIA_NVENET_13         0x0269
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800  0x0280
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X    0x0281
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE     0x0282
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO       0x0286
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL        0x0288
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL        0x0289
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL       0x028C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA  0x0301
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800        0x0302
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000         0x0308
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000         0x0309
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA  0x0311
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600        0x0312
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE      0x0314
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600      0x031A
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650      0x031B
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700        0x031C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200        0x0320
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA  0x0321
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1      0x0322
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE      0x0323
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200      0x0324
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250      0x0325
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500        0x0326
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100        0x0327
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32   0x0328
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200            0x0329
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI     0x032A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500          0x032B
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300      0x032C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100      0x032D
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA  0x0330
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900        0x0331
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT      0x0332
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA  0x0333
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT      0x0334
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000         0x0338
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700          0x033F
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA  0x0341
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700        0x0342
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE      0x0343
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE      0x0344
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1    0x0347
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2    0x0348
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000       0x034C
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
+#define PCI_DEVICE_ID_NVIDIA_NVENET_14              0x0372
+#define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
+#define PCI_DEVICE_ID_NVIDIA_NVENET_16              0x03E5
+#define PCI_DEVICE_ID_NVIDIA_NVENET_17              0x03E6
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA      0x03E7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS            0x03EB
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE       0x03EC
+#define PCI_DEVICE_ID_NVIDIA_NVENET_18              0x03EE
+#define PCI_DEVICE_ID_NVIDIA_NVENET_19              0x03EF
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2     0x03F6
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3     0x03F7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS            0x0446
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE      0x0448
+#define PCI_DEVICE_ID_NVIDIA_NVENET_20              0x0450
+#define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
+#define PCI_DEVICE_ID_NVIDIA_NVENET_22              0x0452
+#define PCI_DEVICE_ID_NVIDIA_NVENET_23              0x0453
+#define PCI_DEVICE_ID_NVIDIA_NVENET_24              0x054C
+#define PCI_DEVICE_ID_NVIDIA_NVENET_25              0x054D
+#define PCI_DEVICE_ID_NVIDIA_NVENET_26              0x054E
+#define PCI_DEVICE_ID_NVIDIA_NVENET_27              0x054F
+#define PCI_DEVICE_ID_NVIDIA_NVENET_28              0x07DC
+#define PCI_DEVICE_ID_NVIDIA_NVENET_29              0x07DD
+#define PCI_DEVICE_ID_NVIDIA_NVENET_30              0x07DE
+#define PCI_DEVICE_ID_NVIDIA_NVENET_31              0x07DF
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE       0x0560
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE       0x056C
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
+#define PCI_DEVICE_ID_NVIDIA_NVENET_32              0x0760
+#define PCI_DEVICE_ID_NVIDIA_NVENET_33              0x0761
+#define PCI_DEVICE_ID_NVIDIA_NVENET_34              0x0762
+#define PCI_DEVICE_ID_NVIDIA_NVENET_35              0x0763
+#define PCI_DEVICE_ID_NVIDIA_NVENET_36              0x0AB0
+#define PCI_DEVICE_ID_NVIDIA_NVENET_37              0x0AB1
+#define PCI_DEVICE_ID_NVIDIA_NVENET_38              0x0AB2
+#define PCI_DEVICE_ID_NVIDIA_NVENET_39              0x0AB3
+
+#define PCI_VENDOR_ID_IMS              0x10e0
+#define PCI_DEVICE_ID_IMS_TT128                0x9128
+#define PCI_DEVICE_ID_IMS_TT3D         0x9135
+
+#define PCI_VENDOR_ID_INTERG           0x10ea
+#define PCI_DEVICE_ID_INTERG_1682      0x1682
+#define PCI_DEVICE_ID_INTERG_2000      0x2000
+#define PCI_DEVICE_ID_INTERG_2010      0x2010
+#define PCI_DEVICE_ID_INTERG_5000      0x5000
+#define PCI_DEVICE_ID_INTERG_5050      0x5050
+
+#define PCI_VENDOR_ID_REALTEK          0x10ec
+#define PCI_DEVICE_ID_REALTEK_8139     0x8139
+
+#define PCI_VENDOR_ID_XILINX           0x10ee
+#define PCI_DEVICE_ID_RME_DIGI96       0x3fc0
+#define PCI_DEVICE_ID_RME_DIGI96_8     0x3fc1
+#define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2
+#define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
+
+#define PCI_VENDOR_ID_INIT             0x1101
+
+#define PCI_VENDOR_ID_CREATIVE         0x1102 /* duplicate: ECTIVA */
+#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
+
+#define PCI_VENDOR_ID_ECTIVA           0x1102 /* duplicate: CREATIVE */
+#define PCI_DEVICE_ID_ECTIVA_EV1938    0x8938
+
+#define PCI_VENDOR_ID_TTI              0x1103
+#define PCI_DEVICE_ID_TTI_HPT343       0x0003
+#define PCI_DEVICE_ID_TTI_HPT366       0x0004
+#define PCI_DEVICE_ID_TTI_HPT372       0x0005
+#define PCI_DEVICE_ID_TTI_HPT302       0x0006
+#define PCI_DEVICE_ID_TTI_HPT371       0x0007
+#define PCI_DEVICE_ID_TTI_HPT374       0x0008
+#define PCI_DEVICE_ID_TTI_HPT372N      0x0009  /* apparently a 372N variant? */
+
+#define PCI_VENDOR_ID_VIA              0x1106
+#define PCI_DEVICE_ID_VIA_8763_0       0x0198
+#define PCI_DEVICE_ID_VIA_8380_0       0x0204
+#define PCI_DEVICE_ID_VIA_3238_0       0x0238
+#define PCI_DEVICE_ID_VIA_PT880                0x0258
+#define PCI_DEVICE_ID_VIA_PT880ULTRA   0x0308
+#define PCI_DEVICE_ID_VIA_PX8X0_0      0x0259
+#define PCI_DEVICE_ID_VIA_3269_0       0x0269
+#define PCI_DEVICE_ID_VIA_K8T800PRO_0  0x0282
+#define PCI_DEVICE_ID_VIA_3296_0       0x0296
+#define PCI_DEVICE_ID_VIA_8363_0       0x0305
+#define PCI_DEVICE_ID_VIA_P4M800CE     0x0314
+#define PCI_DEVICE_ID_VIA_P4M890       0x0327
+#define PCI_DEVICE_ID_VIA_VT3324       0x0324
+#define PCI_DEVICE_ID_VIA_VT3336       0x0336
+#define PCI_DEVICE_ID_VIA_VT3351       0x0351
+#define PCI_DEVICE_ID_VIA_VT3364       0x0364
+#define PCI_DEVICE_ID_VIA_8371_0       0x0391
+#define PCI_DEVICE_ID_VIA_8501_0       0x0501
+#define PCI_DEVICE_ID_VIA_82C561       0x0561
+#define PCI_DEVICE_ID_VIA_82C586_1     0x0571
+#define PCI_DEVICE_ID_VIA_82C576       0x0576
+#define PCI_DEVICE_ID_VIA_82C586_0     0x0586
+#define PCI_DEVICE_ID_VIA_82C596       0x0596
+#define PCI_DEVICE_ID_VIA_82C597_0     0x0597
+#define PCI_DEVICE_ID_VIA_82C598_0     0x0598
+#define PCI_DEVICE_ID_VIA_8601_0       0x0601
+#define PCI_DEVICE_ID_VIA_8605_0       0x0605
+#define PCI_DEVICE_ID_VIA_82C686       0x0686
+#define PCI_DEVICE_ID_VIA_82C691_0     0x0691
+#define PCI_DEVICE_ID_VIA_82C576_1     0x1571
+#define PCI_DEVICE_ID_VIA_82C586_2     0x3038
+#define PCI_DEVICE_ID_VIA_82C586_3     0x3040
+#define PCI_DEVICE_ID_VIA_82C596_3     0x3050
+#define PCI_DEVICE_ID_VIA_82C596B_3    0x3051
+#define PCI_DEVICE_ID_VIA_82C686_4     0x3057
+#define PCI_DEVICE_ID_VIA_82C686_5     0x3058
+#define PCI_DEVICE_ID_VIA_8233_5       0x3059
+#define PCI_DEVICE_ID_VIA_8233_0       0x3074
+#define PCI_DEVICE_ID_VIA_8633_0       0x3091
+#define PCI_DEVICE_ID_VIA_8367_0       0x3099
+#define PCI_DEVICE_ID_VIA_8653_0       0x3101
+#define PCI_DEVICE_ID_VIA_8622         0x3102
+#define PCI_DEVICE_ID_VIA_8235_USB_2   0x3104
+#define PCI_DEVICE_ID_VIA_8233C_0      0x3109
+#define PCI_DEVICE_ID_VIA_8361         0x3112
+#define PCI_DEVICE_ID_VIA_XM266                0x3116
+#define PCI_DEVICE_ID_VIA_612X         0x3119
+#define PCI_DEVICE_ID_VIA_862X_0       0x3123
+#define PCI_DEVICE_ID_VIA_8753_0       0x3128
+#define PCI_DEVICE_ID_VIA_8233A                0x3147
+#define PCI_DEVICE_ID_VIA_8703_51_0    0x3148
+#define PCI_DEVICE_ID_VIA_8237_SATA    0x3149
+#define PCI_DEVICE_ID_VIA_XN266                0x3156
+#define PCI_DEVICE_ID_VIA_6410         0x3164
+#define PCI_DEVICE_ID_VIA_8754C_0      0x3168
+#define PCI_DEVICE_ID_VIA_8235         0x3177
+#define PCI_DEVICE_ID_VIA_8385_0       0x3188
+#define PCI_DEVICE_ID_VIA_8377_0       0x3189
+#define PCI_DEVICE_ID_VIA_8378_0       0x3205
+#define PCI_DEVICE_ID_VIA_8783_0       0x3208
+#define PCI_DEVICE_ID_VIA_8237         0x3227
+#define PCI_DEVICE_ID_VIA_8251         0x3287
+#define PCI_DEVICE_ID_VIA_8237A                0x3337
+#define PCI_DEVICE_ID_VIA_8237S                0x3372
+#define PCI_DEVICE_ID_VIA_SATA_EIDE    0x5324
+#define PCI_DEVICE_ID_VIA_8231         0x8231
+#define PCI_DEVICE_ID_VIA_8231_4       0x8235
+#define PCI_DEVICE_ID_VIA_8365_1       0x8305
+#define PCI_DEVICE_ID_VIA_CX700                0x8324
+#define PCI_DEVICE_ID_VIA_CX700_IDE    0x0581
+#define PCI_DEVICE_ID_VIA_VX800                0x8353
+#define PCI_DEVICE_ID_VIA_8371_1       0x8391
+#define PCI_DEVICE_ID_VIA_82C598_1     0x8598
+#define PCI_DEVICE_ID_VIA_838X_1       0xB188
+#define PCI_DEVICE_ID_VIA_83_87XX_1    0xB198
+
+#define PCI_VENDOR_ID_SIEMENS           0x110A
+#define PCI_DEVICE_ID_SIEMENS_DSCC4     0x2102
+
+#define PCI_VENDOR_ID_VORTEX           0x1119
+#define PCI_DEVICE_ID_VORTEX_GDT60x0   0x0000
+#define PCI_DEVICE_ID_VORTEX_GDT6000B  0x0001
+#define PCI_DEVICE_ID_VORTEX_GDT6x10   0x0002
+#define PCI_DEVICE_ID_VORTEX_GDT6x20   0x0003
+#define PCI_DEVICE_ID_VORTEX_GDT6530   0x0004
+#define PCI_DEVICE_ID_VORTEX_GDT6550   0x0005
+#define PCI_DEVICE_ID_VORTEX_GDT6x17   0x0006
+#define PCI_DEVICE_ID_VORTEX_GDT6x27   0x0007
+#define PCI_DEVICE_ID_VORTEX_GDT6537   0x0008
+#define PCI_DEVICE_ID_VORTEX_GDT6557   0x0009
+#define PCI_DEVICE_ID_VORTEX_GDT6x15   0x000a
+#define PCI_DEVICE_ID_VORTEX_GDT6x25   0x000b
+#define PCI_DEVICE_ID_VORTEX_GDT6535   0x000c
+#define PCI_DEVICE_ID_VORTEX_GDT6555   0x000d
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP 0x0100
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP 0x0101
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP 0x0102
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP 0x0103
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x0104
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x0105
+
+#define PCI_VENDOR_ID_EF               0x111a
+#define PCI_DEVICE_ID_EF_ATM_FPGA      0x0000
+#define PCI_DEVICE_ID_EF_ATM_ASIC      0x0002
+#define PCI_DEVICE_ID_EF_ATM_LANAI2    0x0003
+#define PCI_DEVICE_ID_EF_ATM_LANAIHB   0x0005
+
+#define PCI_VENDOR_ID_IDT              0x111d
+#define PCI_DEVICE_ID_IDT_IDT77201     0x0001
+
+#define PCI_VENDOR_ID_FORE             0x1127
+#define PCI_DEVICE_ID_FORE_PCA200E     0x0300
+
+#define PCI_VENDOR_ID_PHILIPS          0x1131
+#define PCI_DEVICE_ID_PHILIPS_SAA7146  0x7146
+#define PCI_DEVICE_ID_PHILIPS_SAA9730  0x9730
+
+#define PCI_VENDOR_ID_EICON            0x1133
+#define PCI_DEVICE_ID_EICON_DIVA20     0xe002
+#define PCI_DEVICE_ID_EICON_DIVA20_U   0xe004
+#define PCI_DEVICE_ID_EICON_DIVA201    0xe005
+#define PCI_DEVICE_ID_EICON_DIVA202    0xe00b
+#define PCI_DEVICE_ID_EICON_MAESTRA    0xe010
+#define PCI_DEVICE_ID_EICON_MAESTRAQ   0xe012
+#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
+#define PCI_DEVICE_ID_EICON_MAESTRAP   0xe014
+
+#define PCI_VENDOR_ID_CISCO            0x1137
+
+#define PCI_VENDOR_ID_ZIATECH          0x1138
+#define PCI_DEVICE_ID_ZIATECH_5550_HC  0x5550
+
+#define PCI_VENDOR_ID_SYSKONNECT       0x1148
+#define PCI_DEVICE_ID_SYSKONNECT_TR    0x4200
+#define PCI_DEVICE_ID_SYSKONNECT_GE    0x4300
+#define PCI_DEVICE_ID_SYSKONNECT_YU    0x4320
+#define PCI_DEVICE_ID_SYSKONNECT_9DXX  0x4400
+#define PCI_DEVICE_ID_SYSKONNECT_9MXX  0x4500
+
+#define PCI_VENDOR_ID_DIGI             0x114f
+#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
+#define PCI_DEVICE_ID_DIGI_DF_M_E      0x0071
+#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
+#define PCI_DEVICE_ID_DIGI_DF_M_A      0x0073
+#define PCI_DEVICE_ID_NEO_2DB9          0x00C8
+#define PCI_DEVICE_ID_NEO_2DB9PRI       0x00C9
+#define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
+#define PCI_DEVICE_ID_NEO_2RJ45PRI      0x00CB
+#define PCIE_DEVICE_ID_NEO_4_IBM        0x00F4
+
+#define PCI_VENDOR_ID_XIRCOM           0x115d
+#define PCI_DEVICE_ID_XIRCOM_RBM56G    0x0101
+#define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103
+
+#define PCI_VENDOR_ID_SERVERWORKS        0x1166
+#define PCI_DEVICE_ID_SERVERWORKS_HE     0x0008
+#define PCI_DEVICE_ID_SERVERWORKS_LE     0x0009
+#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
+#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB   0x0036
+#define PCI_DEVICE_ID_SERVERWORKS_EPB    0x0103
+#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE  0x0132
+#define PCI_DEVICE_ID_SERVERWORKS_OSB4   0x0200
+#define PCI_DEVICE_ID_SERVERWORKS_CSB5   0x0201
+#define PCI_DEVICE_ID_SERVERWORKS_CSB6    0x0203
+#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205
+#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211
+#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212
+#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213
+#define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
+#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
+#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
+
+#define PCI_VENDOR_ID_SBE              0x1176
+#define PCI_DEVICE_ID_SBE_WANXL100     0x0301
+#define PCI_DEVICE_ID_SBE_WANXL200     0x0302
+#define PCI_DEVICE_ID_SBE_WANXL400     0x0104
+
+#define PCI_VENDOR_ID_TOSHIBA          0x1179
+#define PCI_DEVICE_ID_TOSHIBA_PICCOLO  0x0102
+#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_1        0x0103
+#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_2        0x0105
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC95  0x060a
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC97  0x060f
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC100 0x0617
+
+#define PCI_VENDOR_ID_TOSHIBA_2                0x102f
+#define PCI_DEVICE_ID_TOSHIBA_TC35815CF        0x0030
+#define PCI_DEVICE_ID_TOSHIBA_TC35815_NWU      0x0031
+#define PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939   0x0032
+#define PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE     0x0105
+#define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC    0x0108
+#define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3
+
+#define PCI_VENDOR_ID_ATTO             0x117c
+
+#define PCI_VENDOR_ID_RICOH            0x1180
+#define PCI_DEVICE_ID_RICOH_RL5C465    0x0465
+#define PCI_DEVICE_ID_RICOH_RL5C466    0x0466
+#define PCI_DEVICE_ID_RICOH_RL5C475    0x0475
+#define PCI_DEVICE_ID_RICOH_RL5C476    0x0476
+#define PCI_DEVICE_ID_RICOH_RL5C478    0x0478
+#define PCI_DEVICE_ID_RICOH_R5C822     0x0822
+#define PCI_DEVICE_ID_RICOH_R5C832     0x0832
+#define PCI_DEVICE_ID_RICOH_R5C843     0x0843
+
+#define PCI_VENDOR_ID_DLINK            0x1186
+#define PCI_DEVICE_ID_DLINK_DGE510T    0x4c00
+
+#define PCI_VENDOR_ID_ARTOP            0x1191
+#define PCI_DEVICE_ID_ARTOP_ATP850UF   0x0005
+#define PCI_DEVICE_ID_ARTOP_ATP860     0x0006
+#define PCI_DEVICE_ID_ARTOP_ATP860R    0x0007
+#define PCI_DEVICE_ID_ARTOP_ATP865     0x0008
+#define PCI_DEVICE_ID_ARTOP_ATP865R    0x0009
+#define PCI_DEVICE_ID_ARTOP_AEC7610    0x8002
+#define PCI_DEVICE_ID_ARTOP_AEC7612UW  0x8010
+#define PCI_DEVICE_ID_ARTOP_AEC7612U   0x8020
+#define PCI_DEVICE_ID_ARTOP_AEC7612S   0x8030
+#define PCI_DEVICE_ID_ARTOP_AEC7612D   0x8040
+#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050
+#define PCI_DEVICE_ID_ARTOP_8060       0x8060
+
+#define PCI_VENDOR_ID_ZEITNET          0x1193
+#define PCI_DEVICE_ID_ZEITNET_1221     0x0001
+#define PCI_DEVICE_ID_ZEITNET_1225     0x0002
+
+#define PCI_VENDOR_ID_FUJITSU_ME       0x119e
+#define PCI_DEVICE_ID_FUJITSU_FS155    0x0001
+#define PCI_DEVICE_ID_FUJITSU_FS50     0x0003
+
+#define PCI_SUBVENDOR_ID_KEYSPAN       0x11a9
+#define PCI_SUBDEVICE_ID_KEYSPAN_SX2   0x5334
+
+#define PCI_VENDOR_ID_MARVELL          0x11ab
+#define PCI_DEVICE_ID_MARVELL_GT64111  0x4146
+#define PCI_DEVICE_ID_MARVELL_GT64260  0x6430
+#define PCI_DEVICE_ID_MARVELL_MV64360  0x6460
+#define PCI_DEVICE_ID_MARVELL_MV64460  0x6480
+#define PCI_DEVICE_ID_MARVELL_88ALP01_NAND     0x4100
+#define PCI_DEVICE_ID_MARVELL_88ALP01_SD       0x4101
+#define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC     0x4102
+
+#define PCI_VENDOR_ID_V3               0x11b0
+#define PCI_DEVICE_ID_V3_V960          0x0001
+#define PCI_DEVICE_ID_V3_V351          0x0002
+
+#define PCI_VENDOR_ID_ATT              0x11c1
+#define PCI_DEVICE_ID_ATT_VENUS_MODEM  0x480
+
+#define PCI_VENDOR_ID_SPECIALIX                0x11cb
+#define PCI_DEVICE_ID_SPECIALIX_IO8    0x2000
+#define PCI_DEVICE_ID_SPECIALIX_RIO    0x8000
+#define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004
+
+#define PCI_VENDOR_ID_ANALOG_DEVICES   0x11d4
+#define PCI_DEVICE_ID_AD1889JS         0x1889
+
+#define PCI_DEVICE_ID_SEGA_BBA         0x1234
+
+#define PCI_VENDOR_ID_ZORAN            0x11de
+#define PCI_DEVICE_ID_ZORAN_36057      0x6057
+#define PCI_DEVICE_ID_ZORAN_36120      0x6120
+
+#define PCI_VENDOR_ID_COMPEX           0x11f6
+#define PCI_DEVICE_ID_COMPEX_ENET100VG4        0x0112
+
+#define PCI_VENDOR_ID_RP               0x11fe
+#define PCI_DEVICE_ID_RP32INTF         0x0001
+#define PCI_DEVICE_ID_RP8INTF          0x0002
+#define PCI_DEVICE_ID_RP16INTF         0x0003
+#define PCI_DEVICE_ID_RP4QUAD          0x0004
+#define PCI_DEVICE_ID_RP8OCTA          0x0005
+#define PCI_DEVICE_ID_RP8J             0x0006
+#define PCI_DEVICE_ID_RP4J             0x0007
+#define PCI_DEVICE_ID_RP8SNI           0x0008  
+#define PCI_DEVICE_ID_RP16SNI          0x0009  
+#define PCI_DEVICE_ID_RPP4             0x000A
+#define PCI_DEVICE_ID_RPP8             0x000B
+#define PCI_DEVICE_ID_RP4M             0x000D
+#define PCI_DEVICE_ID_RP2_232          0x000E
+#define PCI_DEVICE_ID_RP2_422          0x000F
+#define PCI_DEVICE_ID_URP32INTF                0x0801
+#define PCI_DEVICE_ID_URP8INTF         0x0802
+#define PCI_DEVICE_ID_URP16INTF                0x0803
+#define PCI_DEVICE_ID_URP8OCTA         0x0805
+#define PCI_DEVICE_ID_UPCI_RM3_8PORT   0x080C       
+#define PCI_DEVICE_ID_UPCI_RM3_4PORT   0x080D
+#define PCI_DEVICE_ID_CRP16INTF                0x0903       
+
+#define PCI_VENDOR_ID_CYCLADES         0x120e
+#define PCI_DEVICE_ID_CYCLOM_Y_Lo      0x0100
+#define PCI_DEVICE_ID_CYCLOM_Y_Hi      0x0101
+#define PCI_DEVICE_ID_CYCLOM_4Y_Lo     0x0102
+#define PCI_DEVICE_ID_CYCLOM_4Y_Hi     0x0103
+#define PCI_DEVICE_ID_CYCLOM_8Y_Lo     0x0104
+#define PCI_DEVICE_ID_CYCLOM_8Y_Hi     0x0105
+#define PCI_DEVICE_ID_CYCLOM_Z_Lo      0x0200
+#define PCI_DEVICE_ID_CYCLOM_Z_Hi      0x0201
+#define PCI_DEVICE_ID_PC300_RX_2       0x0300
+#define PCI_DEVICE_ID_PC300_RX_1       0x0301
+#define PCI_DEVICE_ID_PC300_TE_2       0x0310
+#define PCI_DEVICE_ID_PC300_TE_1       0x0311
+#define PCI_DEVICE_ID_PC300_TE_M_2     0x0320
+#define PCI_DEVICE_ID_PC300_TE_M_1     0x0321
+
+#define PCI_VENDOR_ID_ESSENTIAL                0x120f
+#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER     0x0001
+
+#define PCI_VENDOR_ID_O2               0x1217
+#define PCI_DEVICE_ID_O2_6729          0x6729
+#define PCI_DEVICE_ID_O2_6730          0x673a
+#define PCI_DEVICE_ID_O2_6832          0x6832
+#define PCI_DEVICE_ID_O2_6836          0x6836
+
+#define PCI_VENDOR_ID_3DFX             0x121a
+#define PCI_DEVICE_ID_3DFX_VOODOO      0x0001
+#define PCI_DEVICE_ID_3DFX_VOODOO2     0x0002
+#define PCI_DEVICE_ID_3DFX_BANSHEE     0x0003
+#define PCI_DEVICE_ID_3DFX_VOODOO3     0x0005
+#define PCI_DEVICE_ID_3DFX_VOODOO5     0x0009
+
+#define PCI_VENDOR_ID_AVM              0x1244
+#define PCI_DEVICE_ID_AVM_B1           0x0700
+#define PCI_DEVICE_ID_AVM_C4           0x0800
+#define PCI_DEVICE_ID_AVM_A1           0x0a00
+#define PCI_DEVICE_ID_AVM_A1_V2                0x0e00
+#define PCI_DEVICE_ID_AVM_C2           0x1100
+#define PCI_DEVICE_ID_AVM_T1           0x1200
+
+#define PCI_VENDOR_ID_STALLION         0x124d
+
+/* Allied Telesyn */
+#define PCI_VENDOR_ID_AT               0x1259
+#define PCI_SUBDEVICE_ID_AT_2700FX     0x2701
+#define PCI_SUBDEVICE_ID_AT_2701FX     0x2703
+
+#define PCI_VENDOR_ID_ESS              0x125d
+#define PCI_DEVICE_ID_ESS_ESS1968      0x1968
+#define PCI_DEVICE_ID_ESS_ESS1978      0x1978
+#define PCI_DEVICE_ID_ESS_ALLEGRO_1    0x1988
+#define PCI_DEVICE_ID_ESS_ALLEGRO      0x1989
+#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990
+#define PCI_DEVICE_ID_ESS_CANYON3D_2   0x1992
+#define PCI_DEVICE_ID_ESS_MAESTRO3     0x1998
+#define PCI_DEVICE_ID_ESS_MAESTRO3_1   0x1999
+#define PCI_DEVICE_ID_ESS_MAESTRO3_HW  0x199a
+#define PCI_DEVICE_ID_ESS_MAESTRO3_2   0x199b
+
+#define PCI_VENDOR_ID_SATSAGEM         0x1267
+#define PCI_DEVICE_ID_SATSAGEM_NICCY   0x1016
+
+#define PCI_VENDOR_ID_ENSONIQ          0x1274
+#define PCI_DEVICE_ID_ENSONIQ_CT5880   0x5880
+#define PCI_DEVICE_ID_ENSONIQ_ES1370   0x5000
+#define PCI_DEVICE_ID_ENSONIQ_ES1371   0x1371
+
+#define PCI_VENDOR_ID_TRANSMETA                0x1279
+#define PCI_DEVICE_ID_EFFICEON         0x0060
+
+#define PCI_VENDOR_ID_ROCKWELL         0x127A
+
+#define PCI_VENDOR_ID_ITE              0x1283
+#define PCI_DEVICE_ID_ITE_8211         0x8211
+#define PCI_DEVICE_ID_ITE_8212         0x8212
+#define PCI_DEVICE_ID_ITE_8213         0x8213
+#define PCI_DEVICE_ID_ITE_8152         0x8152
+#define PCI_DEVICE_ID_ITE_8872         0x8872
+#define PCI_DEVICE_ID_ITE_IT8330G_0    0xe886
+
+/* formerly Platform Tech */
+#define PCI_DEVICE_ID_ESS_ESS0100      0x0100
+
+#define PCI_VENDOR_ID_ALTEON           0x12ae
+
+#define PCI_SUBVENDOR_ID_CONNECT_TECH                  0x12c4
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232          0x0001
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232          0x0002
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232          0x0003
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485          0x0004
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4      0x0005
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485          0x0006
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2      0x0007
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485          0x0008
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6      0x0009
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1       0x000A
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1       0x000B
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ                0x000C
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_PTM          0x000D
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_NT960PCI         0x0100
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2          0x0201
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4          0x0202
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232   0x0300
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232   0x0301
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232   0x0302
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1     0x0310
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2     0x0311
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4     0x0312
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2       0x0320
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4       0x0321
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8       0x0322
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485   0x0330
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485   0x0331
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485   0x0332
+
+#define PCI_VENDOR_ID_NVIDIA_SGS       0x12d2
+#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
+
+#define PCI_SUBVENDOR_ID_CHASE_PCIFAST         0x12E0
+#define PCI_SUBDEVICE_ID_CHASE_PCIFAST4                0x0031
+#define PCI_SUBDEVICE_ID_CHASE_PCIFAST8                0x0021
+#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16       0x0011
+#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC    0x0041
+#define PCI_SUBVENDOR_ID_CHASE_PCIRAS          0x124D
+#define PCI_SUBDEVICE_ID_CHASE_PCIRAS4         0xF001
+#define PCI_SUBDEVICE_ID_CHASE_PCIRAS8         0xF010
+
+#define PCI_VENDOR_ID_AUREAL           0x12eb
+#define PCI_DEVICE_ID_AUREAL_VORTEX_1  0x0001
+#define PCI_DEVICE_ID_AUREAL_VORTEX_2  0x0002
+#define PCI_DEVICE_ID_AUREAL_ADVANTAGE 0x0003
+
+#define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8
+#define PCI_DEVICE_ID_LML_33R10                0x8a02
+
+#define PCI_VENDOR_ID_ESDGMBH          0x12fe
+#define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111
+
+#define PCI_VENDOR_ID_SIIG             0x131f
+#define PCI_SUBVENDOR_ID_SIIG          0x131f
+#define PCI_DEVICE_ID_SIIG_1S_10x_550  0x1000
+#define PCI_DEVICE_ID_SIIG_1S_10x_650  0x1001
+#define PCI_DEVICE_ID_SIIG_1S_10x_850  0x1002
+#define PCI_DEVICE_ID_SIIG_1S1P_10x_550        0x1010
+#define PCI_DEVICE_ID_SIIG_1S1P_10x_650        0x1011
+#define PCI_DEVICE_ID_SIIG_1S1P_10x_850        0x1012
+#define PCI_DEVICE_ID_SIIG_1P_10x      0x1020
+#define PCI_DEVICE_ID_SIIG_2P_10x      0x1021
+#define PCI_DEVICE_ID_SIIG_2S_10x_550  0x1030
+#define PCI_DEVICE_ID_SIIG_2S_10x_650  0x1031
+#define PCI_DEVICE_ID_SIIG_2S_10x_850  0x1032
+#define PCI_DEVICE_ID_SIIG_2S1P_10x_550        0x1034
+#define PCI_DEVICE_ID_SIIG_2S1P_10x_650        0x1035
+#define PCI_DEVICE_ID_SIIG_2S1P_10x_850        0x1036
+#define PCI_DEVICE_ID_SIIG_4S_10x_550  0x1050
+#define PCI_DEVICE_ID_SIIG_4S_10x_650  0x1051
+#define PCI_DEVICE_ID_SIIG_4S_10x_850  0x1052
+#define PCI_DEVICE_ID_SIIG_1S_20x_550  0x2000
+#define PCI_DEVICE_ID_SIIG_1S_20x_650  0x2001
+#define PCI_DEVICE_ID_SIIG_1S_20x_850  0x2002
+#define PCI_DEVICE_ID_SIIG_1P_20x      0x2020
+#define PCI_DEVICE_ID_SIIG_2P_20x      0x2021
+#define PCI_DEVICE_ID_SIIG_2S_20x_550  0x2030
+#define PCI_DEVICE_ID_SIIG_2S_20x_650  0x2031
+#define PCI_DEVICE_ID_SIIG_2S_20x_850  0x2032
+#define PCI_DEVICE_ID_SIIG_2P1S_20x_550        0x2040
+#define PCI_DEVICE_ID_SIIG_2P1S_20x_650        0x2041
+#define PCI_DEVICE_ID_SIIG_2P1S_20x_850        0x2042
+#define PCI_DEVICE_ID_SIIG_1S1P_20x_550        0x2010
+#define PCI_DEVICE_ID_SIIG_1S1P_20x_650        0x2011
+#define PCI_DEVICE_ID_SIIG_1S1P_20x_850        0x2012
+#define PCI_DEVICE_ID_SIIG_4S_20x_550  0x2050
+#define PCI_DEVICE_ID_SIIG_4S_20x_650  0x2051
+#define PCI_DEVICE_ID_SIIG_4S_20x_850  0x2052
+#define PCI_DEVICE_ID_SIIG_2S1P_20x_550        0x2060
+#define PCI_DEVICE_ID_SIIG_2S1P_20x_650        0x2061
+#define PCI_DEVICE_ID_SIIG_2S1P_20x_850        0x2062
+#define PCI_DEVICE_ID_SIIG_8S_20x_550  0x2080
+#define PCI_DEVICE_ID_SIIG_8S_20x_650  0x2081
+#define PCI_DEVICE_ID_SIIG_8S_20x_850  0x2082
+#define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL   0x2050
+
+#define PCI_VENDOR_ID_RADISYS          0x1331
+
+#define PCI_VENDOR_ID_MICRO_MEMORY             0x1332
+#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN      0x5415
+#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN      0x5425
+#define PCI_DEVICE_ID_MICRO_MEMORY_6155                0x6155
+
+#define PCI_VENDOR_ID_DOMEX            0x134a
+#define PCI_DEVICE_ID_DOMEX_DMX3191D   0x0001
+
+#define PCI_VENDOR_ID_INTASHIELD       0x135a
+#define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80
+#define PCI_DEVICE_ID_INTASHIELD_IS400 0x0dc0
+
+#define PCI_VENDOR_ID_QUATECH          0x135C
+#define PCI_DEVICE_ID_QUATECH_QSC100   0x0010
+#define PCI_DEVICE_ID_QUATECH_DSC100   0x0020
+#define PCI_DEVICE_ID_QUATECH_ESC100D  0x0050
+#define PCI_DEVICE_ID_QUATECH_ESC100M  0x0060
+#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
+
+#define PCI_VENDOR_ID_SEALEVEL         0x135e
+#define PCI_DEVICE_ID_SEALEVEL_U530    0x7101
+#define PCI_DEVICE_ID_SEALEVEL_UCOMM2  0x7201
+#define PCI_DEVICE_ID_SEALEVEL_UCOMM422        0x7402
+#define PCI_DEVICE_ID_SEALEVEL_UCOMM232        0x7202
+#define PCI_DEVICE_ID_SEALEVEL_COMM4   0x7401
+#define PCI_DEVICE_ID_SEALEVEL_COMM8   0x7801
+#define PCI_DEVICE_ID_SEALEVEL_UCOMM8  0x7804
+
+#define PCI_VENDOR_ID_HYPERCOPE                0x1365
+#define PCI_DEVICE_ID_HYPERCOPE_PLX    0x9050
+#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO    0x0104
+#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO                0x0106
+#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO       0x0107
+#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2      0x0108
+
+#define PCI_VENDOR_ID_KAWASAKI         0x136b
+#define PCI_DEVICE_ID_MCHIP_KL5A72002  0xff01
+
+#define PCI_VENDOR_ID_CNET             0x1371
+#define PCI_DEVICE_ID_CNET_GIGACARD    0x434e
+
+#define PCI_VENDOR_ID_LMC              0x1376
+#define PCI_DEVICE_ID_LMC_HSSI         0x0003
+#define PCI_DEVICE_ID_LMC_DS3          0x0004
+#define PCI_DEVICE_ID_LMC_SSI          0x0005
+#define PCI_DEVICE_ID_LMC_T1           0x0006
+
+#define PCI_VENDOR_ID_NETGEAR          0x1385
+#define PCI_DEVICE_ID_NETGEAR_GA620    0x620a
+
+#define PCI_VENDOR_ID_APPLICOM         0x1389
+#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
+#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
+#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
+
+#define PCI_VENDOR_ID_MOXA             0x1393
+#define PCI_DEVICE_ID_MOXA_RC7000      0x0001
+#define PCI_DEVICE_ID_MOXA_CP102       0x1020
+#define PCI_DEVICE_ID_MOXA_CP102UL     0x1021
+#define PCI_DEVICE_ID_MOXA_CP102U      0x1022
+#define PCI_DEVICE_ID_MOXA_C104                0x1040
+#define PCI_DEVICE_ID_MOXA_CP104U      0x1041
+#define PCI_DEVICE_ID_MOXA_CP104JU     0x1042
+#define PCI_DEVICE_ID_MOXA_CP104EL     0x1043
+#define PCI_DEVICE_ID_MOXA_CT114       0x1140
+#define PCI_DEVICE_ID_MOXA_CP114       0x1141
+#define PCI_DEVICE_ID_MOXA_CP118U      0x1180
+#define PCI_DEVICE_ID_MOXA_CP118EL     0x1181
+#define PCI_DEVICE_ID_MOXA_CP132       0x1320
+#define PCI_DEVICE_ID_MOXA_CP132U      0x1321
+#define PCI_DEVICE_ID_MOXA_CP134U      0x1340
+#define PCI_DEVICE_ID_MOXA_C168                0x1680
+#define PCI_DEVICE_ID_MOXA_CP168U      0x1681
+#define PCI_DEVICE_ID_MOXA_CP168EL     0x1682
+#define PCI_DEVICE_ID_MOXA_CP204J      0x2040
+#define PCI_DEVICE_ID_MOXA_C218                0x2180
+#define PCI_DEVICE_ID_MOXA_C320                0x3200
+
+#define PCI_VENDOR_ID_CCD              0x1397
+#define PCI_DEVICE_ID_CCD_HFC4S                0x08B4
+#define PCI_SUBDEVICE_ID_CCD_PMX2S     0x1234
+#define PCI_DEVICE_ID_CCD_HFC8S                0x16B8
+#define PCI_DEVICE_ID_CCD_2BD0         0x2bd0
+#define PCI_DEVICE_ID_CCD_HFCE1                0x30B1
+#define PCI_SUBDEVICE_ID_CCD_SPD4S     0x3136
+#define PCI_SUBDEVICE_ID_CCD_SPDE1     0x3137
+#define PCI_DEVICE_ID_CCD_B000         0xb000
+#define PCI_DEVICE_ID_CCD_B006         0xb006
+#define PCI_DEVICE_ID_CCD_B007         0xb007
+#define PCI_DEVICE_ID_CCD_B008         0xb008
+#define PCI_DEVICE_ID_CCD_B009         0xb009
+#define PCI_DEVICE_ID_CCD_B00A         0xb00a
+#define PCI_DEVICE_ID_CCD_B00B         0xb00b
+#define PCI_DEVICE_ID_CCD_B00C         0xb00c
+#define PCI_DEVICE_ID_CCD_B100         0xb100
+#define PCI_SUBDEVICE_ID_CCD_IOB4ST    0xB520
+#define PCI_SUBDEVICE_ID_CCD_IOB8STR   0xB521
+#define PCI_SUBDEVICE_ID_CCD_IOB8ST    0xB522
+#define PCI_SUBDEVICE_ID_CCD_IOB1E1    0xB523
+#define PCI_SUBDEVICE_ID_CCD_SWYX4S    0xB540
+#define PCI_SUBDEVICE_ID_CCD_JH4S20    0xB550
+#define PCI_SUBDEVICE_ID_CCD_IOB8ST_1  0xB552
+#define PCI_SUBDEVICE_ID_CCD_BN4S      0xB560
+#define PCI_SUBDEVICE_ID_CCD_BN8S      0xB562
+#define PCI_SUBDEVICE_ID_CCD_BNE1      0xB563
+#define PCI_SUBDEVICE_ID_CCD_BNE1D     0xB564
+#define PCI_SUBDEVICE_ID_CCD_BNE1DP    0xB565
+#define PCI_SUBDEVICE_ID_CCD_BN2S      0xB566
+#define PCI_SUBDEVICE_ID_CCD_BN1SM     0xB567
+#define PCI_SUBDEVICE_ID_CCD_BN4SM     0xB568
+#define PCI_SUBDEVICE_ID_CCD_BN2SM     0xB569
+#define PCI_SUBDEVICE_ID_CCD_BNE1M     0xB56A
+#define PCI_SUBDEVICE_ID_CCD_BN8SP     0xB56B
+#define PCI_SUBDEVICE_ID_CCD_HFC4S     0xB620
+#define PCI_SUBDEVICE_ID_CCD_HFC8S     0xB622
+#define PCI_DEVICE_ID_CCD_B700         0xb700
+#define PCI_DEVICE_ID_CCD_B701         0xb701
+#define PCI_SUBDEVICE_ID_CCD_HFCE1     0xC523
+#define PCI_SUBDEVICE_ID_CCD_OV2S      0xE884
+#define PCI_SUBDEVICE_ID_CCD_OV4S      0xE888
+#define PCI_SUBDEVICE_ID_CCD_OV8S      0xE998
+
+#define PCI_VENDOR_ID_EXAR             0x13a8
+#define PCI_DEVICE_ID_EXAR_XR17C152    0x0152
+#define PCI_DEVICE_ID_EXAR_XR17C154    0x0154
+#define PCI_DEVICE_ID_EXAR_XR17C158    0x0158
+
+#define PCI_VENDOR_ID_MICROGATE                0x13c0
+#define PCI_DEVICE_ID_MICROGATE_USC    0x0010
+#define PCI_DEVICE_ID_MICROGATE_SCA    0x0030
+
+#define PCI_VENDOR_ID_3WARE            0x13C1
+#define PCI_DEVICE_ID_3WARE_1000       0x1000
+#define PCI_DEVICE_ID_3WARE_7000       0x1001
+#define PCI_DEVICE_ID_3WARE_9000       0x1002
+
+#define PCI_VENDOR_ID_IOMEGA           0x13ca
+#define PCI_DEVICE_ID_IOMEGA_BUZ       0x4231
+
+#define PCI_VENDOR_ID_ABOCOM           0x13D1
+#define PCI_DEVICE_ID_ABOCOM_2BD1       0x2BD1
+
+#define PCI_VENDOR_ID_SUNDANCE         0x13f0
+
+#define PCI_VENDOR_ID_CMEDIA           0x13f6
+#define PCI_DEVICE_ID_CMEDIA_CM8338A   0x0100
+#define PCI_DEVICE_ID_CMEDIA_CM8338B   0x0101
+#define PCI_DEVICE_ID_CMEDIA_CM8738    0x0111
+#define PCI_DEVICE_ID_CMEDIA_CM8738B   0x0112
+
+#define PCI_VENDOR_ID_LAVA             0x1407
+#define PCI_DEVICE_ID_LAVA_DSERIAL     0x0100 /* 2x 16550 */
+#define PCI_DEVICE_ID_LAVA_QUATRO_A    0x0101 /* 2x 16550, half of 4 port */
+#define PCI_DEVICE_ID_LAVA_QUATRO_B    0x0102 /* 2x 16550, half of 4 port */
+#define PCI_DEVICE_ID_LAVA_OCTO_A      0x0180 /* 4x 16550A, half of 8 port */
+#define PCI_DEVICE_ID_LAVA_OCTO_B      0x0181 /* 4x 16550A, half of 8 port */
+#define PCI_DEVICE_ID_LAVA_PORT_PLUS   0x0200 /* 2x 16650 */
+#define PCI_DEVICE_ID_LAVA_QUAD_A      0x0201 /* 2x 16650, half of 4 port */
+#define PCI_DEVICE_ID_LAVA_QUAD_B      0x0202 /* 2x 16650, half of 4 port */
+#define PCI_DEVICE_ID_LAVA_SSERIAL     0x0500 /* 1x 16550 */
+#define PCI_DEVICE_ID_LAVA_PORT_650    0x0600 /* 1x 16650 */
+#define PCI_DEVICE_ID_LAVA_PARALLEL    0x8000
+#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A  0x8002 /* The Lava Dual Parallel is */
+#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B  0x8003 /* two PCI devices on a card */
+#define PCI_DEVICE_ID_LAVA_BOCA_IOPPAR 0x8800
+
+#define PCI_VENDOR_ID_TIMEDIA          0x1409
+#define PCI_DEVICE_ID_TIMEDIA_1889     0x7168
+
+#define PCI_VENDOR_ID_ICE              0x1412
+#define PCI_DEVICE_ID_ICE_1712         0x1712
+#define PCI_DEVICE_ID_VT1724           0x1724
+
+#define PCI_VENDOR_ID_OXSEMI           0x1415
+#define PCI_DEVICE_ID_OXSEMI_12PCI840  0x8403
+#define PCI_DEVICE_ID_OXSEMI_PCIe840           0xC000
+#define PCI_DEVICE_ID_OXSEMI_PCIe840_G         0xC004
+#define PCI_DEVICE_ID_OXSEMI_PCIe952_0         0xC100
+#define PCI_DEVICE_ID_OXSEMI_PCIe952_0_G       0xC104
+#define PCI_DEVICE_ID_OXSEMI_PCIe952_1         0xC110
+#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_G       0xC114
+#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_U       0xC118
+#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU      0xC11C
+#define PCI_DEVICE_ID_OXSEMI_16PCI954  0x9501
+#define PCI_DEVICE_ID_OXSEMI_16PCI95N  0x9511
+#define PCI_DEVICE_ID_OXSEMI_16PCI954PP        0x9513
+#define PCI_DEVICE_ID_OXSEMI_16PCI952  0x9521
+#define PCI_DEVICE_ID_OXSEMI_16PCI952PP        0x9523
+
+#define PCI_VENDOR_ID_CHELSIO          0x1425
+
+#define PCI_VENDOR_ID_SAMSUNG          0x144d
+
+#define PCI_VENDOR_ID_MYRICOM          0x14c1
+
+#define PCI_VENDOR_ID_TITAN            0x14D2
+#define PCI_DEVICE_ID_TITAN_010L       0x8001
+#define PCI_DEVICE_ID_TITAN_100L       0x8010
+#define PCI_DEVICE_ID_TITAN_110L       0x8011
+#define PCI_DEVICE_ID_TITAN_200L       0x8020
+#define PCI_DEVICE_ID_TITAN_210L       0x8021
+#define PCI_DEVICE_ID_TITAN_400L       0x8040
+#define PCI_DEVICE_ID_TITAN_800L       0x8080
+#define PCI_DEVICE_ID_TITAN_100                0xA001
+#define PCI_DEVICE_ID_TITAN_200                0xA005
+#define PCI_DEVICE_ID_TITAN_400                0xA003
+#define PCI_DEVICE_ID_TITAN_800B       0xA004
+
+#define PCI_VENDOR_ID_PANACOM          0x14d4
+#define PCI_DEVICE_ID_PANACOM_QUADMODEM        0x0400
+#define PCI_DEVICE_ID_PANACOM_DUALMODEM        0x0402
+
+#define PCI_VENDOR_ID_SIPACKETS                0x14d9
+#define PCI_DEVICE_ID_SP1011           0x0010
+
+#define PCI_VENDOR_ID_AFAVLAB          0x14db
+#define PCI_DEVICE_ID_AFAVLAB_P028     0x2180
+#define PCI_DEVICE_ID_AFAVLAB_P030     0x2182
+#define PCI_SUBDEVICE_ID_AFAVLAB_P061          0x2150
+
+#define PCI_VENDOR_ID_BROADCOM         0x14e4
+#define PCI_DEVICE_ID_TIGON3_5752      0x1600
+#define PCI_DEVICE_ID_TIGON3_5752M     0x1601
+#define PCI_DEVICE_ID_NX2_5709         0x1639
+#define PCI_DEVICE_ID_NX2_5709S                0x163a
+#define PCI_DEVICE_ID_TIGON3_5700      0x1644
+#define PCI_DEVICE_ID_TIGON3_5701      0x1645
+#define PCI_DEVICE_ID_TIGON3_5702      0x1646
+#define PCI_DEVICE_ID_TIGON3_5703      0x1647
+#define PCI_DEVICE_ID_TIGON3_5704      0x1648
+#define PCI_DEVICE_ID_TIGON3_5704S_2   0x1649
+#define PCI_DEVICE_ID_NX2_5706         0x164a
+#define PCI_DEVICE_ID_NX2_5708         0x164c
+#define PCI_DEVICE_ID_TIGON3_5702FE    0x164d
+#define PCI_DEVICE_ID_NX2_57710                0x164e
+#define PCI_DEVICE_ID_NX2_57711                0x164f
+#define PCI_DEVICE_ID_NX2_57711E       0x1650
+#define PCI_DEVICE_ID_TIGON3_5705      0x1653
+#define PCI_DEVICE_ID_TIGON3_5705_2    0x1654
+#define PCI_DEVICE_ID_TIGON3_5720      0x1658
+#define PCI_DEVICE_ID_TIGON3_5721      0x1659
+#define PCI_DEVICE_ID_TIGON3_5722      0x165a
+#define PCI_DEVICE_ID_TIGON3_5723      0x165b
+#define PCI_DEVICE_ID_TIGON3_5705M     0x165d
+#define PCI_DEVICE_ID_TIGON3_5705M_2   0x165e
+#define PCI_DEVICE_ID_TIGON3_5714      0x1668
+#define PCI_DEVICE_ID_TIGON3_5714S     0x1669
+#define PCI_DEVICE_ID_TIGON3_5780      0x166a
+#define PCI_DEVICE_ID_TIGON3_5780S     0x166b
+#define PCI_DEVICE_ID_TIGON3_5705F     0x166e
+#define PCI_DEVICE_ID_TIGON3_5754M     0x1672
+#define PCI_DEVICE_ID_TIGON3_5755M     0x1673
+#define PCI_DEVICE_ID_TIGON3_5756      0x1674
+#define PCI_DEVICE_ID_TIGON3_5750      0x1676
+#define PCI_DEVICE_ID_TIGON3_5751      0x1677
+#define PCI_DEVICE_ID_TIGON3_5715      0x1678
+#define PCI_DEVICE_ID_TIGON3_5715S     0x1679
+#define PCI_DEVICE_ID_TIGON3_5754      0x167a
+#define PCI_DEVICE_ID_TIGON3_5755      0x167b
+#define PCI_DEVICE_ID_TIGON3_5750M     0x167c
+#define PCI_DEVICE_ID_TIGON3_5751M     0x167d
+#define PCI_DEVICE_ID_TIGON3_5751F     0x167e
+#define PCI_DEVICE_ID_TIGON3_5787F     0x167f
+#define PCI_DEVICE_ID_TIGON3_5761E     0x1680
+#define PCI_DEVICE_ID_TIGON3_5761      0x1681
+#define PCI_DEVICE_ID_TIGON3_5764      0x1684
+#define PCI_DEVICE_ID_TIGON3_5787M     0x1693
+#define PCI_DEVICE_ID_TIGON3_5782      0x1696
+#define PCI_DEVICE_ID_TIGON3_5784      0x1698
+#define PCI_DEVICE_ID_TIGON3_5785      0x1699
+#define PCI_DEVICE_ID_TIGON3_5786      0x169a
+#define PCI_DEVICE_ID_TIGON3_5787      0x169b
+#define PCI_DEVICE_ID_TIGON3_5788      0x169c
+#define PCI_DEVICE_ID_TIGON3_5789      0x169d
+#define PCI_DEVICE_ID_TIGON3_5702X     0x16a6
+#define PCI_DEVICE_ID_TIGON3_5703X     0x16a7
+#define PCI_DEVICE_ID_TIGON3_5704S     0x16a8
+#define PCI_DEVICE_ID_NX2_5706S                0x16aa
+#define PCI_DEVICE_ID_NX2_5708S                0x16ac
+#define PCI_DEVICE_ID_TIGON3_5702A3    0x16c6
+#define PCI_DEVICE_ID_TIGON3_5703A3    0x16c7
+#define PCI_DEVICE_ID_TIGON3_5781      0x16dd
+#define PCI_DEVICE_ID_TIGON3_5753      0x16f7
+#define PCI_DEVICE_ID_TIGON3_5753M     0x16fd
+#define PCI_DEVICE_ID_TIGON3_5753F     0x16fe
+#define PCI_DEVICE_ID_TIGON3_5901      0x170d
+#define PCI_DEVICE_ID_BCM4401B1                0x170c
+#define PCI_DEVICE_ID_TIGON3_5901_2    0x170e
+#define PCI_DEVICE_ID_TIGON3_5906      0x1712
+#define PCI_DEVICE_ID_TIGON3_5906M     0x1713
+#define PCI_DEVICE_ID_BCM4401          0x4401
+#define PCI_DEVICE_ID_BCM4401B0                0x4402
+
+#define PCI_VENDOR_ID_TOPIC            0x151f
+#define PCI_DEVICE_ID_TOPIC_TP560      0x0000
+
+#define PCI_VENDOR_ID_MAINPINE         0x1522
+#define PCI_DEVICE_ID_MAINPINE_PBRIDGE 0x0100
+#define PCI_VENDOR_ID_ENE              0x1524
+#define PCI_DEVICE_ID_ENE_CB712_SD     0x0550
+#define PCI_DEVICE_ID_ENE_CB712_SD_2   0x0551
+#define PCI_DEVICE_ID_ENE_CB714_SD     0x0750
+#define PCI_DEVICE_ID_ENE_CB714_SD_2   0x0751
+#define PCI_DEVICE_ID_ENE_1211         0x1211
+#define PCI_DEVICE_ID_ENE_1225         0x1225
+#define PCI_DEVICE_ID_ENE_1410         0x1410
+#define PCI_DEVICE_ID_ENE_710          0x1411
+#define PCI_DEVICE_ID_ENE_712          0x1412
+#define PCI_DEVICE_ID_ENE_1420         0x1420
+#define PCI_DEVICE_ID_ENE_720          0x1421
+#define PCI_DEVICE_ID_ENE_722          0x1422
+
+#define PCI_SUBVENDOR_ID_PERLE          0x155f
+#define PCI_SUBDEVICE_ID_PCI_RAS4       0xf001
+#define PCI_SUBDEVICE_ID_PCI_RAS8       0xf010
+
+#define PCI_VENDOR_ID_SYBA             0x1592
+#define PCI_DEVICE_ID_SYBA_2P_EPP      0x0782
+#define PCI_DEVICE_ID_SYBA_1P_ECP      0x0783
+
+#define PCI_VENDOR_ID_MORETON          0x15aa
+#define PCI_DEVICE_ID_RASTEL_2PORT     0x2000
+
+#define PCI_VENDOR_ID_ZOLTRIX          0x15b0
+#define PCI_DEVICE_ID_ZOLTRIX_2BD0     0x2bd0 
+
+#define PCI_VENDOR_ID_MELLANOX         0x15b3
+#define PCI_DEVICE_ID_MELLANOX_TAVOR   0x5a44
+#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE    0x5a46
+#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278
+#define PCI_DEVICE_ID_MELLANOX_ARBEL   0x6282
+#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
+#define PCI_DEVICE_ID_MELLANOX_SINAI   0x6274
+
+#define PCI_VENDOR_ID_QUICKNET         0x15e2
+#define PCI_DEVICE_ID_QUICKNET_XJ      0x0500
+
+/*
+ * ADDI-DATA GmbH communication cards <info@addi-data.com>
+ */
+#define PCI_VENDOR_ID_ADDIDATA_OLD             0x10E8
+#define PCI_VENDOR_ID_ADDIDATA                 0x15B8
+#define PCI_DEVICE_ID_ADDIDATA_APCI7500        0x7000
+#define PCI_DEVICE_ID_ADDIDATA_APCI7420        0x7001
+#define PCI_DEVICE_ID_ADDIDATA_APCI7300        0x7002
+#define PCI_DEVICE_ID_ADDIDATA_APCI7800        0x818E
+#define PCI_DEVICE_ID_ADDIDATA_APCI7500_2      0x7009
+#define PCI_DEVICE_ID_ADDIDATA_APCI7420_2      0x700A
+#define PCI_DEVICE_ID_ADDIDATA_APCI7300_2      0x700B
+#define PCI_DEVICE_ID_ADDIDATA_APCI7500_3      0x700C
+#define PCI_DEVICE_ID_ADDIDATA_APCI7420_3      0x700D
+#define PCI_DEVICE_ID_ADDIDATA_APCI7300_3      0x700E
+#define PCI_DEVICE_ID_ADDIDATA_APCI7800_3      0x700F
+
+#define PCI_VENDOR_ID_PDC              0x15e9
+
+#define PCI_VENDOR_ID_FARSITE           0x1619
+#define PCI_DEVICE_ID_FARSITE_T2P       0x0400
+#define PCI_DEVICE_ID_FARSITE_T4P       0x0440
+#define PCI_DEVICE_ID_FARSITE_T1U       0x0610
+#define PCI_DEVICE_ID_FARSITE_T2U       0x0620
+#define PCI_DEVICE_ID_FARSITE_T4U       0x0640
+#define PCI_DEVICE_ID_FARSITE_TE1       0x1610
+#define PCI_DEVICE_ID_FARSITE_TE1C      0x1612
+
+#define PCI_VENDOR_ID_ARIMA            0x161f
+
+#define PCI_VENDOR_ID_BROCADE          0x1657
+
+#define PCI_VENDOR_ID_SIBYTE           0x166d
+#define PCI_DEVICE_ID_BCM1250_PCI      0x0001
+#define PCI_DEVICE_ID_BCM1250_HT       0x0002
+
+#define PCI_VENDOR_ID_ATHEROS          0x168c
+
+#define PCI_VENDOR_ID_NETCELL          0x169c
+#define PCI_DEVICE_ID_REVOLUTION       0x0044
+
+#define PCI_VENDOR_ID_CENATEK          0x16CA
+#define PCI_DEVICE_ID_CENATEK_IDE      0x0001
+
+#define PCI_VENDOR_ID_VITESSE          0x1725
+#define PCI_DEVICE_ID_VITESSE_VSC7174  0x7174
+
+#define PCI_VENDOR_ID_LINKSYS          0x1737
+#define PCI_DEVICE_ID_LINKSYS_EG1064   0x1064
+
+#define PCI_VENDOR_ID_ALTIMA           0x173b
+#define PCI_DEVICE_ID_ALTIMA_AC1000    0x03e8
+#define PCI_DEVICE_ID_ALTIMA_AC1001    0x03e9
+#define PCI_DEVICE_ID_ALTIMA_AC9100    0x03ea
+#define PCI_DEVICE_ID_ALTIMA_AC1003    0x03eb
+
+#define PCI_VENDOR_ID_BELKIN           0x1799
+#define PCI_DEVICE_ID_BELKIN_F5D7010V7 0x701f
+
+#define PCI_VENDOR_ID_RDC              0x17f3
+#define PCI_DEVICE_ID_RDC_R6020                0x6020
+#define PCI_DEVICE_ID_RDC_R6030                0x6030
+#define PCI_DEVICE_ID_RDC_R6040                0x6040
+#define PCI_DEVICE_ID_RDC_R6060                0x6060
+#define PCI_DEVICE_ID_RDC_R6061                0x6061
+
+#define PCI_VENDOR_ID_LENOVO           0x17aa
+
+#define PCI_VENDOR_ID_ARECA            0x17d3
+#define PCI_DEVICE_ID_ARECA_1110       0x1110
+#define PCI_DEVICE_ID_ARECA_1120       0x1120
+#define PCI_DEVICE_ID_ARECA_1130       0x1130
+#define PCI_DEVICE_ID_ARECA_1160       0x1160
+#define PCI_DEVICE_ID_ARECA_1170       0x1170
+#define PCI_DEVICE_ID_ARECA_1200       0x1200
+#define PCI_DEVICE_ID_ARECA_1201       0x1201
+#define PCI_DEVICE_ID_ARECA_1202       0x1202
+#define PCI_DEVICE_ID_ARECA_1210       0x1210
+#define PCI_DEVICE_ID_ARECA_1220       0x1220
+#define PCI_DEVICE_ID_ARECA_1230       0x1230
+#define PCI_DEVICE_ID_ARECA_1260       0x1260
+#define PCI_DEVICE_ID_ARECA_1270       0x1270
+#define PCI_DEVICE_ID_ARECA_1280       0x1280
+#define PCI_DEVICE_ID_ARECA_1380       0x1380
+#define PCI_DEVICE_ID_ARECA_1381       0x1381
+#define PCI_DEVICE_ID_ARECA_1680       0x1680
+#define PCI_DEVICE_ID_ARECA_1681       0x1681
+
+#define PCI_VENDOR_ID_S2IO             0x17d5
+#define        PCI_DEVICE_ID_S2IO_WIN          0x5731
+#define        PCI_DEVICE_ID_S2IO_UNI          0x5831
+#define PCI_DEVICE_ID_HERC_WIN         0x5732
+#define PCI_DEVICE_ID_HERC_UNI         0x5832
+
+#define PCI_VENDOR_ID_SITECOM          0x182d
+#define PCI_DEVICE_ID_SITECOM_DC105V2  0x3069
+
+#define PCI_VENDOR_ID_TOPSPIN          0x1867
+
+#define PCI_VENDOR_ID_TDI               0x192E
+#define PCI_DEVICE_ID_TDI_EHCI          0x0101
+
+#define PCI_VENDOR_ID_FREESCALE                0x1957
+#define PCI_DEVICE_ID_MPC8548E         0x0012
+#define PCI_DEVICE_ID_MPC8548          0x0013
+#define PCI_DEVICE_ID_MPC8543E         0x0014
+#define PCI_DEVICE_ID_MPC8543          0x0015
+#define PCI_DEVICE_ID_MPC8547E         0x0018
+#define PCI_DEVICE_ID_MPC8545E         0x0019
+#define PCI_DEVICE_ID_MPC8545          0x001a
+#define PCI_DEVICE_ID_MPC8568E         0x0020
+#define PCI_DEVICE_ID_MPC8568          0x0021
+#define PCI_DEVICE_ID_MPC8567E         0x0022
+#define PCI_DEVICE_ID_MPC8567          0x0023
+#define PCI_DEVICE_ID_MPC8533E         0x0030
+#define PCI_DEVICE_ID_MPC8533          0x0031
+#define PCI_DEVICE_ID_MPC8544E         0x0032
+#define PCI_DEVICE_ID_MPC8544          0x0033
+#define PCI_DEVICE_ID_MPC8572E         0x0040
+#define PCI_DEVICE_ID_MPC8572          0x0041
+#define PCI_DEVICE_ID_MPC8536E         0x0050
+#define PCI_DEVICE_ID_MPC8536          0x0051
+#define PCI_DEVICE_ID_MPC8641          0x7010
+#define PCI_DEVICE_ID_MPC8641D         0x7011
+#define PCI_DEVICE_ID_MPC8610          0x7018
+
+#define PCI_VENDOR_ID_PASEMI           0x1959
+
+#define PCI_VENDOR_ID_ATTANSIC         0x1969
+#define PCI_DEVICE_ID_ATTANSIC_L1      0x1048
+#define PCI_DEVICE_ID_ATTANSIC_L2      0x2048
+
+#define PCI_VENDOR_ID_JMICRON          0x197B
+#define PCI_DEVICE_ID_JMICRON_JMB360   0x2360
+#define PCI_DEVICE_ID_JMICRON_JMB361   0x2361
+#define PCI_DEVICE_ID_JMICRON_JMB363   0x2363
+#define PCI_DEVICE_ID_JMICRON_JMB365   0x2365
+#define PCI_DEVICE_ID_JMICRON_JMB366   0x2366
+#define PCI_DEVICE_ID_JMICRON_JMB368   0x2368
+#define PCI_DEVICE_ID_JMICRON_JMB38X_SD        0x2381
+#define PCI_DEVICE_ID_JMICRON_JMB38X_MMC 0x2382
+#define PCI_DEVICE_ID_JMICRON_JMB38X_MS        0x2383
+
+#define PCI_VENDOR_ID_KORENIX          0x1982
+#define PCI_DEVICE_ID_KORENIX_JETCARDF0        0x1600
+#define PCI_DEVICE_ID_KORENIX_JETCARDF1        0x16ff
+
+#define PCI_VENDOR_ID_TEKRAM           0x1de1
+#define PCI_DEVICE_ID_TEKRAM_DC290     0xdc29
+
+#define PCI_VENDOR_ID_TEHUTI           0x1fc9
+#define PCI_DEVICE_ID_TEHUTI_3009      0x3009
+#define PCI_DEVICE_ID_TEHUTI_3010      0x3010
+#define PCI_DEVICE_ID_TEHUTI_3014      0x3014
+
+#define PCI_VENDOR_ID_HINT             0x3388
+#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013
+
+#define PCI_VENDOR_ID_3DLABS           0x3d3d
+#define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007
+#define PCI_DEVICE_ID_3DLABS_PERMEDIA2V        0x0009
+
+#define PCI_VENDOR_ID_NETXEN           0x4040
+#define PCI_DEVICE_ID_NX2031_10GXSR    0x0001
+#define PCI_DEVICE_ID_NX2031_10GCX4    0x0002
+#define PCI_DEVICE_ID_NX2031_4GCU      0x0003
+#define PCI_DEVICE_ID_NX2031_IMEZ      0x0004
+#define PCI_DEVICE_ID_NX2031_HMEZ      0x0005
+#define PCI_DEVICE_ID_NX2031_XG_MGMT   0x0024
+#define PCI_DEVICE_ID_NX2031_XG_MGMT2  0x0025
+#define PCI_DEVICE_ID_NX3031           0x0100
+
+#define PCI_VENDOR_ID_AKS              0x416c
+#define PCI_DEVICE_ID_AKS_ALADDINCARD  0x0100
+
+#define PCI_VENDOR_ID_S3               0x5333
+#define PCI_DEVICE_ID_S3_TRIO          0x8811
+#define PCI_DEVICE_ID_S3_868           0x8880
+#define PCI_DEVICE_ID_S3_968           0x88f0
+#define PCI_DEVICE_ID_S3_SAVAGE4       0x8a25
+#define PCI_DEVICE_ID_S3_PROSAVAGE8    0x8d04
+#define PCI_DEVICE_ID_S3_SONICVIBES    0xca00
+
+#define PCI_VENDOR_ID_DUNORD           0x5544
+#define PCI_DEVICE_ID_DUNORD_I3000     0x0001
+
+#define PCI_VENDOR_ID_DCI              0x6666
+#define PCI_DEVICE_ID_DCI_PCCOM4       0x0001
+#define PCI_DEVICE_ID_DCI_PCCOM8       0x0002
+#define PCI_DEVICE_ID_DCI_PCCOM2       0x0004
+
+#define PCI_VENDOR_ID_INTEL            0x8086
+#define PCI_DEVICE_ID_INTEL_EESSC      0x0008
+#define PCI_DEVICE_ID_INTEL_PXHD_0     0x0320
+#define PCI_DEVICE_ID_INTEL_PXHD_1     0x0321
+#define PCI_DEVICE_ID_INTEL_PXH_0      0x0329
+#define PCI_DEVICE_ID_INTEL_PXH_1      0x032A
+#define PCI_DEVICE_ID_INTEL_PXHV       0x032C
+#define PCI_DEVICE_ID_INTEL_82375      0x0482
+#define PCI_DEVICE_ID_INTEL_82424      0x0483
+#define PCI_DEVICE_ID_INTEL_82378      0x0484
+#define PCI_DEVICE_ID_INTEL_I960       0x0960
+#define PCI_DEVICE_ID_INTEL_I960RM     0x0962
+#define PCI_DEVICE_ID_INTEL_82815_MC   0x1130
+#define PCI_DEVICE_ID_INTEL_82815_CGC  0x1132
+#define PCI_DEVICE_ID_INTEL_82092AA_0  0x1221
+#define PCI_DEVICE_ID_INTEL_7505_0     0x2550  
+#define PCI_DEVICE_ID_INTEL_7205_0     0x255d
+#define PCI_DEVICE_ID_INTEL_82437      0x122d
+#define PCI_DEVICE_ID_INTEL_82371FB_0  0x122e
+#define PCI_DEVICE_ID_INTEL_82371FB_1  0x1230
+#define PCI_DEVICE_ID_INTEL_82371MX    0x1234
+#define PCI_DEVICE_ID_INTEL_82441      0x1237
+#define PCI_DEVICE_ID_INTEL_82380FB    0x124b
+#define PCI_DEVICE_ID_INTEL_82439      0x1250
+#define PCI_DEVICE_ID_INTEL_80960_RP   0x1960
+#define PCI_DEVICE_ID_INTEL_82840_HB   0x1a21
+#define PCI_DEVICE_ID_INTEL_82845_HB   0x1a30
+#define PCI_DEVICE_ID_INTEL_IOAT       0x1a38
+#define PCI_DEVICE_ID_INTEL_82801AA_0  0x2410
+#define PCI_DEVICE_ID_INTEL_82801AA_1  0x2411
+#define PCI_DEVICE_ID_INTEL_82801AA_3  0x2413
+#define PCI_DEVICE_ID_INTEL_82801AA_5  0x2415
+#define PCI_DEVICE_ID_INTEL_82801AA_6  0x2416
+#define PCI_DEVICE_ID_INTEL_82801AA_8  0x2418
+#define PCI_DEVICE_ID_INTEL_82801AB_0  0x2420
+#define PCI_DEVICE_ID_INTEL_82801AB_1  0x2421
+#define PCI_DEVICE_ID_INTEL_82801AB_3  0x2423
+#define PCI_DEVICE_ID_INTEL_82801AB_5  0x2425
+#define PCI_DEVICE_ID_INTEL_82801AB_6  0x2426
+#define PCI_DEVICE_ID_INTEL_82801AB_8  0x2428
+#define PCI_DEVICE_ID_INTEL_82801BA_0  0x2440
+#define PCI_DEVICE_ID_INTEL_82801BA_2  0x2443
+#define PCI_DEVICE_ID_INTEL_82801BA_4  0x2445
+#define PCI_DEVICE_ID_INTEL_82801BA_6  0x2448
+#define PCI_DEVICE_ID_INTEL_82801BA_8  0x244a
+#define PCI_DEVICE_ID_INTEL_82801BA_9  0x244b
+#define PCI_DEVICE_ID_INTEL_82801BA_10 0x244c
+#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e
+#define PCI_DEVICE_ID_INTEL_82801E_0   0x2450
+#define PCI_DEVICE_ID_INTEL_82801E_11  0x245b
+#define PCI_DEVICE_ID_INTEL_82801CA_0  0x2480
+#define PCI_DEVICE_ID_INTEL_82801CA_3  0x2483
+#define PCI_DEVICE_ID_INTEL_82801CA_5  0x2485
+#define PCI_DEVICE_ID_INTEL_82801CA_6  0x2486
+#define PCI_DEVICE_ID_INTEL_82801CA_10 0x248a
+#define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b
+#define PCI_DEVICE_ID_INTEL_82801CA_12 0x248c
+#define PCI_DEVICE_ID_INTEL_82801DB_0  0x24c0
+#define PCI_DEVICE_ID_INTEL_82801DB_1  0x24c1
+#define PCI_DEVICE_ID_INTEL_82801DB_3  0x24c3
+#define PCI_DEVICE_ID_INTEL_82801DB_5  0x24c5
+#define PCI_DEVICE_ID_INTEL_82801DB_6  0x24c6
+#define PCI_DEVICE_ID_INTEL_82801DB_9  0x24c9
+#define PCI_DEVICE_ID_INTEL_82801DB_10 0x24ca
+#define PCI_DEVICE_ID_INTEL_82801DB_11 0x24cb
+#define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
+#define PCI_DEVICE_ID_INTEL_82801EB_0  0x24d0
+#define PCI_DEVICE_ID_INTEL_82801EB_1  0x24d1
+#define PCI_DEVICE_ID_INTEL_82801EB_3  0x24d3
+#define PCI_DEVICE_ID_INTEL_82801EB_5  0x24d5
+#define PCI_DEVICE_ID_INTEL_82801EB_6  0x24d6
+#define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db
+#define PCI_DEVICE_ID_INTEL_82801EB_12 0x24dc
+#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd
+#define PCI_DEVICE_ID_INTEL_ESB_1      0x25a1
+#define PCI_DEVICE_ID_INTEL_ESB_2      0x25a2
+#define PCI_DEVICE_ID_INTEL_ESB_4      0x25a4
+#define PCI_DEVICE_ID_INTEL_ESB_5      0x25a6
+#define PCI_DEVICE_ID_INTEL_ESB_9      0x25ab
+#define PCI_DEVICE_ID_INTEL_82820_HB   0x2500
+#define PCI_DEVICE_ID_INTEL_82820_UP_HB        0x2501
+#define PCI_DEVICE_ID_INTEL_82850_HB   0x2530
+#define PCI_DEVICE_ID_INTEL_82860_HB   0x2531
+#define PCI_DEVICE_ID_INTEL_E7501_MCH  0x254c
+#define PCI_DEVICE_ID_INTEL_82845G_HB  0x2560
+#define PCI_DEVICE_ID_INTEL_82845G_IG  0x2562
+#define PCI_DEVICE_ID_INTEL_82865_HB   0x2570
+#define PCI_DEVICE_ID_INTEL_82865_IG   0x2572
+#define PCI_DEVICE_ID_INTEL_82875_HB   0x2578
+#define PCI_DEVICE_ID_INTEL_82915G_HB  0x2580
+#define PCI_DEVICE_ID_INTEL_82915G_IG  0x2582
+#define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590
+#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
+#define PCI_DEVICE_ID_INTEL_5000_ERR   0x25F0
+#define PCI_DEVICE_ID_INTEL_5000_FBD0  0x25F5
+#define PCI_DEVICE_ID_INTEL_5000_FBD1  0x25F6
+#define PCI_DEVICE_ID_INTEL_82945G_HB  0x2770
+#define PCI_DEVICE_ID_INTEL_82945G_IG  0x2772
+#define PCI_DEVICE_ID_INTEL_3000_HB    0x2778
+#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0
+#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2
+#define PCI_DEVICE_ID_INTEL_ICH6_0     0x2640
+#define PCI_DEVICE_ID_INTEL_ICH6_1     0x2641
+#define PCI_DEVICE_ID_INTEL_ICH6_2     0x2642
+#define PCI_DEVICE_ID_INTEL_ICH6_16    0x266a
+#define PCI_DEVICE_ID_INTEL_ICH6_17    0x266d
+#define PCI_DEVICE_ID_INTEL_ICH6_18    0x266e
+#define PCI_DEVICE_ID_INTEL_ICH6_19    0x266f
+#define PCI_DEVICE_ID_INTEL_ESB2_0     0x2670
+#define PCI_DEVICE_ID_INTEL_ESB2_14    0x2698
+#define PCI_DEVICE_ID_INTEL_ESB2_17    0x269b
+#define PCI_DEVICE_ID_INTEL_ESB2_18    0x269e
+#define PCI_DEVICE_ID_INTEL_ICH7_0     0x27b8
+#define PCI_DEVICE_ID_INTEL_ICH7_1     0x27b9
+#define PCI_DEVICE_ID_INTEL_ICH7_30    0x27b0
+#define PCI_DEVICE_ID_INTEL_ICH7_31    0x27bd
+#define PCI_DEVICE_ID_INTEL_ICH7_17    0x27da
+#define PCI_DEVICE_ID_INTEL_ICH7_19    0x27dd
+#define PCI_DEVICE_ID_INTEL_ICH7_20    0x27de
+#define PCI_DEVICE_ID_INTEL_ICH7_21    0x27df
+#define PCI_DEVICE_ID_INTEL_ICH8_0     0x2810
+#define PCI_DEVICE_ID_INTEL_ICH8_1     0x2811
+#define PCI_DEVICE_ID_INTEL_ICH8_2     0x2812
+#define PCI_DEVICE_ID_INTEL_ICH8_3     0x2814
+#define PCI_DEVICE_ID_INTEL_ICH8_4     0x2815
+#define PCI_DEVICE_ID_INTEL_ICH8_5     0x283e
+#define PCI_DEVICE_ID_INTEL_ICH8_6     0x2850
+#define PCI_DEVICE_ID_INTEL_ICH9_0     0x2910
+#define PCI_DEVICE_ID_INTEL_ICH9_1     0x2917
+#define PCI_DEVICE_ID_INTEL_ICH9_2     0x2912
+#define PCI_DEVICE_ID_INTEL_ICH9_3     0x2913
+#define PCI_DEVICE_ID_INTEL_ICH9_4     0x2914
+#define PCI_DEVICE_ID_INTEL_ICH9_5     0x2919
+#define PCI_DEVICE_ID_INTEL_ICH9_6     0x2930
+#define PCI_DEVICE_ID_INTEL_ICH9_7     0x2916
+#define PCI_DEVICE_ID_INTEL_ICH9_8     0x2918
+#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG4  0x3429
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG5  0x342a
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG6  0x342b
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG7  0x342c
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG0  0x3430
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG1  0x3431
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG2  0x3432
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG3  0x3433
+#define PCI_DEVICE_ID_INTEL_82830_HB   0x3575
+#define PCI_DEVICE_ID_INTEL_82830_CGC  0x3577
+#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
+#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
+#define PCI_DEVICE_ID_INTEL_E7520_MCH  0x3590
+#define PCI_DEVICE_ID_INTEL_E7320_MCH  0x3592
+#define PCI_DEVICE_ID_INTEL_MCH_PA     0x3595
+#define PCI_DEVICE_ID_INTEL_MCH_PA1    0x3596
+#define PCI_DEVICE_ID_INTEL_MCH_PB     0x3597
+#define PCI_DEVICE_ID_INTEL_MCH_PB1    0x3598
+#define PCI_DEVICE_ID_INTEL_MCH_PC     0x3599
+#define PCI_DEVICE_ID_INTEL_MCH_PC1    0x359a
+#define PCI_DEVICE_ID_INTEL_E7525_MCH  0x359e
+#define PCI_DEVICE_ID_INTEL_IOAT_CNB   0x360b
+#define PCI_DEVICE_ID_INTEL_FBD_CNB    0x360c
+#define PCI_DEVICE_ID_INTEL_ICH10_0    0x3a14
+#define PCI_DEVICE_ID_INTEL_ICH10_1    0x3a16
+#define PCI_DEVICE_ID_INTEL_ICH10_2    0x3a18
+#define PCI_DEVICE_ID_INTEL_ICH10_3    0x3a1a
+#define PCI_DEVICE_ID_INTEL_ICH10_4    0x3a30
+#define PCI_DEVICE_ID_INTEL_ICH10_5    0x3a60
+#define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN        0x3b00
+#define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX        0x3b1f
+#define PCI_DEVICE_ID_INTEL_PCH_SMBUS  0x3b30
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB   0x402f
+#define PCI_DEVICE_ID_INTEL_5100_16    0x65f0
+#define PCI_DEVICE_ID_INTEL_5100_21    0x65f5
+#define PCI_DEVICE_ID_INTEL_5100_22    0x65f6
+#define PCI_DEVICE_ID_INTEL_5400_ERR   0x4030
+#define PCI_DEVICE_ID_INTEL_5400_FBD0  0x4035
+#define PCI_DEVICE_ID_INTEL_5400_FBD1  0x4036
+#define PCI_DEVICE_ID_INTEL_IOAT_SCNB  0x65ff
+#define PCI_DEVICE_ID_INTEL_TOLAPAI_0  0x5031
+#define PCI_DEVICE_ID_INTEL_TOLAPAI_1  0x5032
+#define PCI_DEVICE_ID_INTEL_82371SB_0  0x7000
+#define PCI_DEVICE_ID_INTEL_82371SB_1  0x7010
+#define PCI_DEVICE_ID_INTEL_82371SB_2  0x7020
+#define PCI_DEVICE_ID_INTEL_82437VX    0x7030
+#define PCI_DEVICE_ID_INTEL_82439TX    0x7100
+#define PCI_DEVICE_ID_INTEL_82371AB_0  0x7110
+#define PCI_DEVICE_ID_INTEL_82371AB    0x7111
+#define PCI_DEVICE_ID_INTEL_82371AB_2  0x7112
+#define PCI_DEVICE_ID_INTEL_82371AB_3  0x7113
+#define PCI_DEVICE_ID_INTEL_82810_MC1  0x7120
+#define PCI_DEVICE_ID_INTEL_82810_IG1  0x7121
+#define PCI_DEVICE_ID_INTEL_82810_MC3  0x7122
+#define PCI_DEVICE_ID_INTEL_82810_IG3  0x7123
+#define PCI_DEVICE_ID_INTEL_82810E_MC  0x7124
+#define PCI_DEVICE_ID_INTEL_82810E_IG  0x7125
+#define PCI_DEVICE_ID_INTEL_82443LX_0  0x7180
+#define PCI_DEVICE_ID_INTEL_82443LX_1  0x7181
+#define PCI_DEVICE_ID_INTEL_82443BX_0  0x7190
+#define PCI_DEVICE_ID_INTEL_82443BX_1  0x7191
+#define PCI_DEVICE_ID_INTEL_82443BX_2  0x7192
+#define PCI_DEVICE_ID_INTEL_440MX      0x7195
+#define PCI_DEVICE_ID_INTEL_440MX_6    0x7196
+#define PCI_DEVICE_ID_INTEL_82443MX_0  0x7198
+#define PCI_DEVICE_ID_INTEL_82443MX_1  0x7199
+#define PCI_DEVICE_ID_INTEL_82443MX_3  0x719b
+#define PCI_DEVICE_ID_INTEL_82443GX_0  0x71a0
+#define PCI_DEVICE_ID_INTEL_82443GX_2  0x71a2
+#define PCI_DEVICE_ID_INTEL_82372FB_1  0x7601
+#define PCI_DEVICE_ID_INTEL_SCH_LPC    0x8119
+#define PCI_DEVICE_ID_INTEL_SCH_IDE    0x811a
+#define PCI_DEVICE_ID_INTEL_82454GX    0x84c4
+#define PCI_DEVICE_ID_INTEL_82450GX    0x84c5
+#define PCI_DEVICE_ID_INTEL_82451NX    0x84ca
+#define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
+#define PCI_DEVICE_ID_INTEL_84460GX    0x84ea
+#define PCI_DEVICE_ID_INTEL_IXP4XX     0x8500
+#define PCI_DEVICE_ID_INTEL_IXP2800    0x9004
+#define PCI_DEVICE_ID_INTEL_S21152BB   0xb152
+
+#define PCI_VENDOR_ID_SCALEMP          0x8686
+#define PCI_DEVICE_ID_SCALEMP_VSMP_CTL 0x1010
+
+#define PCI_VENDOR_ID_COMPUTONE                0x8e0e
+#define PCI_DEVICE_ID_COMPUTONE_IP2EX  0x0291
+#define PCI_DEVICE_ID_COMPUTONE_PG     0x0302
+#define PCI_SUBVENDOR_ID_COMPUTONE     0x8e0e
+#define PCI_SUBDEVICE_ID_COMPUTONE_PG4 0x0001
+#define PCI_SUBDEVICE_ID_COMPUTONE_PG8 0x0002
+#define PCI_SUBDEVICE_ID_COMPUTONE_PG6 0x0003
+
+#define PCI_VENDOR_ID_KTI              0x8e2e
+
+#define PCI_VENDOR_ID_ADAPTEC          0x9004
+#define PCI_DEVICE_ID_ADAPTEC_7810     0x1078
+#define PCI_DEVICE_ID_ADAPTEC_7821     0x2178
+#define PCI_DEVICE_ID_ADAPTEC_38602    0x3860
+#define PCI_DEVICE_ID_ADAPTEC_7850     0x5078
+#define PCI_DEVICE_ID_ADAPTEC_7855     0x5578
+#define PCI_DEVICE_ID_ADAPTEC_3860     0x6038
+#define PCI_DEVICE_ID_ADAPTEC_1480A    0x6075
+#define PCI_DEVICE_ID_ADAPTEC_7860     0x6078
+#define PCI_DEVICE_ID_ADAPTEC_7861     0x6178
+#define PCI_DEVICE_ID_ADAPTEC_7870     0x7078
+#define PCI_DEVICE_ID_ADAPTEC_7871     0x7178
+#define PCI_DEVICE_ID_ADAPTEC_7872     0x7278
+#define PCI_DEVICE_ID_ADAPTEC_7873     0x7378
+#define PCI_DEVICE_ID_ADAPTEC_7874     0x7478
+#define PCI_DEVICE_ID_ADAPTEC_7895     0x7895
+#define PCI_DEVICE_ID_ADAPTEC_7880     0x8078
+#define PCI_DEVICE_ID_ADAPTEC_7881     0x8178
+#define PCI_DEVICE_ID_ADAPTEC_7882     0x8278
+#define PCI_DEVICE_ID_ADAPTEC_7883     0x8378
+#define PCI_DEVICE_ID_ADAPTEC_7884     0x8478
+#define PCI_DEVICE_ID_ADAPTEC_7885     0x8578
+#define PCI_DEVICE_ID_ADAPTEC_7886     0x8678
+#define PCI_DEVICE_ID_ADAPTEC_7887     0x8778
+#define PCI_DEVICE_ID_ADAPTEC_7888     0x8878
+
+#define PCI_VENDOR_ID_ADAPTEC2         0x9005
+#define PCI_DEVICE_ID_ADAPTEC2_2940U2  0x0010
+#define PCI_DEVICE_ID_ADAPTEC2_2930U2  0x0011
+#define PCI_DEVICE_ID_ADAPTEC2_7890B   0x0013
+#define PCI_DEVICE_ID_ADAPTEC2_7890    0x001f
+#define PCI_DEVICE_ID_ADAPTEC2_3940U2  0x0050
+#define PCI_DEVICE_ID_ADAPTEC2_3950U2D 0x0051
+#define PCI_DEVICE_ID_ADAPTEC2_7896    0x005f
+#define PCI_DEVICE_ID_ADAPTEC2_7892A   0x0080
+#define PCI_DEVICE_ID_ADAPTEC2_7892B   0x0081
+#define PCI_DEVICE_ID_ADAPTEC2_7892D   0x0083
+#define PCI_DEVICE_ID_ADAPTEC2_7892P   0x008f
+#define PCI_DEVICE_ID_ADAPTEC2_7899A   0x00c0
+#define PCI_DEVICE_ID_ADAPTEC2_7899B   0x00c1
+#define PCI_DEVICE_ID_ADAPTEC2_7899D   0x00c3
+#define PCI_DEVICE_ID_ADAPTEC2_7899P   0x00cf
+#define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN   0x0500
+#define PCI_DEVICE_ID_ADAPTEC2_SCAMP   0x0503
+
+#define PCI_VENDOR_ID_HOLTEK           0x9412
+#define PCI_DEVICE_ID_HOLTEK_6565      0x6565
+
+#define PCI_VENDOR_ID_NETMOS           0x9710
+#define PCI_DEVICE_ID_NETMOS_9705      0x9705
+#define PCI_DEVICE_ID_NETMOS_9715      0x9715
+#define PCI_DEVICE_ID_NETMOS_9735      0x9735
+#define PCI_DEVICE_ID_NETMOS_9745      0x9745
+#define PCI_DEVICE_ID_NETMOS_9755      0x9755
+#define PCI_DEVICE_ID_NETMOS_9805      0x9805
+#define PCI_DEVICE_ID_NETMOS_9815      0x9815
+#define PCI_DEVICE_ID_NETMOS_9835      0x9835
+#define PCI_DEVICE_ID_NETMOS_9845      0x9845
+#define PCI_DEVICE_ID_NETMOS_9855      0x9855
+
+#define PCI_VENDOR_ID_3COM_2           0xa727
+
+#define PCI_VENDOR_ID_DIGIUM           0xd161
+#define PCI_DEVICE_ID_DIGIUM_HFC4S     0xb410
+
+#define PCI_SUBVENDOR_ID_EXSYS         0xd84d
+#define PCI_SUBDEVICE_ID_EXSYS_4014    0x4014
+#define PCI_SUBDEVICE_ID_EXSYS_4055    0x4055
+
+#define PCI_VENDOR_ID_TIGERJET         0xe159
+#define PCI_DEVICE_ID_TIGERJET_300     0x0001
+#define PCI_DEVICE_ID_TIGERJET_100     0x0002
+
+#define PCI_VENDOR_ID_XILINX_RME       0xea60
+#define PCI_DEVICE_ID_RME_DIGI32       0x9896
+#define PCI_DEVICE_ID_RME_DIGI32_PRO   0x9897
+#define PCI_DEVICE_ID_RME_DIGI32_8     0x9898
+
+#define PCI_VENDOR_ID_REDHAT_QUMRANET  0x1af4
+#define PCI_DEVICE_ID_VIRTIO_BLK       0x1001
+#define PCI_DEVICE_ID_VIRTIO_SCSI      0x1004
diff --git a/src/hw/pci_regs.h b/src/hw/pci_regs.h
new file mode 100644 (file)
index 0000000..e5effd4
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ *     pci_regs.h
+ *
+ *     PCI standard defines
+ *     Copyright 1994, Drew Eckhardt
+ *     Copyright 1997--1999 Martin Mares <mj@ucw.cz>
+ *
+ *     For more information, please consult the following manuals (look at
+ *     http://www.pcisig.com/ for how to get them):
+ *
+ *     PCI BIOS Specification
+ *     PCI Local Bus Specification
+ *     PCI to PCI Bridge Specification
+ *     PCI System Design Guide
+ *
+ *     For hypertransport information, please consult the following manuals
+ *     from http://www.hypertransport.org
+ *
+ *     The Hypertransport I/O Link Specification
+ */
+
+#ifndef LINUX_PCI_REGS_H
+#define LINUX_PCI_REGS_H
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID          0x00    /* 16 bits */
+#define PCI_DEVICE_ID          0x02    /* 16 bits */
+#define PCI_COMMAND            0x04    /* 16 bits */
+#define  PCI_COMMAND_IO                0x1     /* Enable response in I/O space */
+#define  PCI_COMMAND_MEMORY    0x2     /* Enable response in Memory space */
+#define  PCI_COMMAND_MASTER    0x4     /* Enable bus mastering */
+#define  PCI_COMMAND_SPECIAL   0x8     /* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE        0x10    /* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20  /* Enable palette snooping */
+#define  PCI_COMMAND_PARITY    0x40    /* Enable parity checking */
+#define  PCI_COMMAND_WAIT      0x80    /* Enable address/data stepping */
+#define  PCI_COMMAND_SERR      0x100   /* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK 0x200   /* Enable back-to-back writes */
+#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
+
+#define PCI_STATUS             0x06    /* 16 bits */
+#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
+#define  PCI_STATUS_66MHZ      0x20    /* Support 66 Mhz PCI 2.1 bus */
+#define  PCI_STATUS_UDF                0x40    /* Support User Definable Features [obsolete] */
+#define  PCI_STATUS_FAST_BACK  0x80    /* Accept fast-back to back */
+#define  PCI_STATUS_PARITY     0x100   /* Detected parity error */
+#define  PCI_STATUS_DEVSEL_MASK        0x600   /* DEVSEL timing */
+#define  PCI_STATUS_DEVSEL_FAST                0x000
+#define  PCI_STATUS_DEVSEL_MEDIUM      0x200
+#define  PCI_STATUS_DEVSEL_SLOW                0x400
+#define  PCI_STATUS_SIG_TARGET_ABORT   0x800 /* Set on target abort */
+#define  PCI_STATUS_REC_TARGET_ABORT   0x1000 /* Master ack of " */
+#define  PCI_STATUS_REC_MASTER_ABORT   0x2000 /* Set on master abort */
+#define  PCI_STATUS_SIG_SYSTEM_ERROR   0x4000 /* Set when we drive SERR */
+#define  PCI_STATUS_DETECTED_PARITY    0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION     0x08    /* High 24 bits are class, low 8 revision */
+#define PCI_REVISION_ID                0x08    /* Revision ID */
+#define PCI_CLASS_PROG         0x09    /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE       0x0a    /* Device class */
+
+#define PCI_CACHE_LINE_SIZE    0x0c    /* 8 bits */
+#define PCI_LATENCY_TIMER      0x0d    /* 8 bits */
+#define PCI_HEADER_TYPE                0x0e    /* 8 bits */
+#define  PCI_HEADER_TYPE_NORMAL                0
+#define  PCI_HEADER_TYPE_BRIDGE                1
+#define  PCI_HEADER_TYPE_CARDBUS       2
+
+#define PCI_BIST               0x0f    /* 8 bits */
+#define  PCI_BIST_CODE_MASK    0x0f    /* Return result */
+#define  PCI_BIST_START                0x40    /* 1 to start BIST, 2 secs or less */
+#define  PCI_BIST_CAPABLE      0x80    /* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back.  Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0     0x10    /* 32 bits */
+#define PCI_BASE_ADDRESS_1     0x14    /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2     0x18    /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3     0x1c    /* 32 bits */
+#define PCI_BASE_ADDRESS_4     0x20    /* 32 bits */
+#define PCI_BASE_ADDRESS_5     0x24    /* 32 bits */
+#define  PCI_BASE_ADDRESS_SPACE                0x01    /* 0 = memory, 1 = I/O */
+#define  PCI_BASE_ADDRESS_SPACE_IO     0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK        0x06
+#define  PCI_BASE_ADDRESS_MEM_TYPE_32  0x00    /* 32 bit address */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_1M  0x02    /* Below 1M [obsolete] */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64  0x04    /* 64 bit address */
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH 0x08    /* prefetchable? */
+#define  PCI_BASE_ADDRESS_MEM_MASK     (~0x0fUL)
+#define  PCI_BASE_ADDRESS_IO_MASK      (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS                0x28
+#define PCI_SUBSYSTEM_VENDOR_ID        0x2c
+#define PCI_SUBSYSTEM_ID       0x2e
+#define PCI_ROM_ADDRESS                0x30    /* Bits 31..11 are address, 10..1 reserved */
+#define  PCI_ROM_ADDRESS_ENABLE        0x01
+#define PCI_ROM_ADDRESS_MASK   (~0x7ffUL)
+
+#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE     0x3c    /* 8 bits */
+#define PCI_INTERRUPT_PIN      0x3d    /* 8 bits */
+#define PCI_MIN_GNT            0x3e    /* 8 bits */
+#define PCI_MAX_LAT            0x3f    /* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS                0x18    /* Primary bus number */
+#define PCI_SECONDARY_BUS      0x19    /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS    0x1a    /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER  0x1b    /* Latency timer for secondary interface */
+#define PCI_IO_BASE            0x1c    /* I/O range behind the bridge */
+#define PCI_IO_LIMIT           0x1d
+#define  PCI_IO_RANGE_TYPE_MASK        0x0fUL  /* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16  0x00
+#define  PCI_IO_RANGE_TYPE_32  0x01
+#define  PCI_IO_RANGE_MASK     (~0x0fUL)
+#define PCI_SEC_STATUS         0x1e    /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE                0x20    /* Memory range behind */
+#define PCI_MEMORY_LIMIT       0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_MEMORY_RANGE_MASK (~0x0fUL)
+#define PCI_PREF_MEMORY_BASE   0x24    /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT  0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_PREF_RANGE_TYPE_32        0x00
+#define  PCI_PREF_RANGE_TYPE_64        0x01
+#define  PCI_PREF_RANGE_MASK   (~0x0fUL)
+#define PCI_PREF_BASE_UPPER32  0x28    /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16    0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16   0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1       0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL     0x3e
+#define  PCI_BRIDGE_CTL_PARITY 0x01    /* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR   0x02    /* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_ISA    0x04    /* Enable ISA mode */
+#define  PCI_BRIDGE_CTL_VGA    0x08    /* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT   0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET      0x40    /* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK      0x80    /* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+#define PCI_CB_CAPABILITY_LIST 0x14
+/* 0x15 reserved */
+#define PCI_CB_SEC_STATUS      0x16    /* Secondary status */
+#define PCI_CB_PRIMARY_BUS     0x18    /* PCI bus number */
+#define PCI_CB_CARD_BUS                0x19    /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a    /* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER   0x1b    /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0   0x1c
+#define PCI_CB_MEMORY_LIMIT_0  0x20
+#define PCI_CB_MEMORY_BASE_1   0x24
+#define PCI_CB_MEMORY_LIMIT_1  0x28
+#define PCI_CB_IO_BASE_0       0x2c
+#define PCI_CB_IO_BASE_0_HI    0x2e
+#define PCI_CB_IO_LIMIT_0      0x30
+#define PCI_CB_IO_LIMIT_0_HI   0x32
+#define PCI_CB_IO_BASE_1       0x34
+#define PCI_CB_IO_BASE_1_HI    0x36
+#define PCI_CB_IO_LIMIT_1      0x38
+#define PCI_CB_IO_LIMIT_1_HI   0x3a
+#define  PCI_CB_IO_RANGE_MASK  (~0x03UL)
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL  0x3e
+#define  PCI_CB_BRIDGE_CTL_PARITY      0x01    /* Similar to standard bridge control register */
+#define  PCI_CB_BRIDGE_CTL_SERR                0x02
+#define  PCI_CB_BRIDGE_CTL_ISA         0x04
+#define  PCI_CB_BRIDGE_CTL_VGA         0x08
+#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT        0x20
+#define  PCI_CB_BRIDGE_CTL_CB_RESET    0x40    /* CardBus reset */
+#define  PCI_CB_BRIDGE_CTL_16BIT_INT   0x80    /* Enable interrupt for 16-bit cards */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define  PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID     0x40
+#define PCI_CB_SUBSYSTEM_ID            0x42
+#define PCI_CB_LEGACY_MODE_BASE                0x44    /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID                0       /* Capability ID */
+#define  PCI_CAP_ID_PM         0x01    /* Power Management */
+#define  PCI_CAP_ID_AGP                0x02    /* Accelerated Graphics Port */
+#define  PCI_CAP_ID_VPD                0x03    /* Vital Product Data */
+#define  PCI_CAP_ID_SLOTID     0x04    /* Slot Identification */
+#define  PCI_CAP_ID_MSI                0x05    /* Message Signalled Interrupts */
+#define  PCI_CAP_ID_CHSWP      0x06    /* CompactPCI HotSwap */
+#define  PCI_CAP_ID_PCIX       0x07    /* PCI-X */
+#define  PCI_CAP_ID_HT         0x08    /* HyperTransport */
+#define  PCI_CAP_ID_VNDR       0x09    /* Vendor specific */
+#define  PCI_CAP_ID_DBG                0x0A    /* Debug port */
+#define  PCI_CAP_ID_CCRC       0x0B    /* CompactPCI Central Resource Control */
+#define  PCI_CAP_ID_SHPC       0x0C    /* PCI Standard Hot-Plug Controller */
+#define  PCI_CAP_ID_SSVID      0x0D    /* Bridge subsystem vendor/device ID */
+#define  PCI_CAP_ID_AGP3       0x0E    /* AGP Target PCI-PCI bridge */
+#define  PCI_CAP_ID_EXP        0x10    /* PCI Express */
+#define  PCI_CAP_ID_MSIX       0x11    /* MSI-X */
+#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
+#define PCI_CAP_FLAGS          2       /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF         4
+
+/* Power Management Registers */
+
+#define PCI_PM_PMC             2       /* PM Capabilities Register */
+#define  PCI_PM_CAP_VER_MASK   0x0007  /* Version */
+#define  PCI_PM_CAP_PME_CLOCK  0x0008  /* PME clock required */
+#define  PCI_PM_CAP_RESERVED    0x0010  /* Reserved field */
+#define  PCI_PM_CAP_DSI                0x0020  /* Device specific initialization */
+#define  PCI_PM_CAP_AUX_POWER  0x01C0  /* Auxilliary power support mask */
+#define  PCI_PM_CAP_D1         0x0200  /* D1 power state support */
+#define  PCI_PM_CAP_D2         0x0400  /* D2 power state support */
+#define  PCI_PM_CAP_PME                0x0800  /* PME pin supported */
+#define  PCI_PM_CAP_PME_MASK   0xF800  /* PME Mask of all supported states */
+#define  PCI_PM_CAP_PME_D0     0x0800  /* PME# from D0 */
+#define  PCI_PM_CAP_PME_D1     0x1000  /* PME# from D1 */
+#define  PCI_PM_CAP_PME_D2     0x2000  /* PME# from D2 */
+#define  PCI_PM_CAP_PME_D3     0x4000  /* PME# from D3 (hot) */
+#define  PCI_PM_CAP_PME_D3cold 0x8000  /* PME# from D3 (cold) */
+#define  PCI_PM_CAP_PME_SHIFT  11      /* Start of the PME Mask in PMC */
+#define PCI_PM_CTRL            4       /* PM control and status register */
+#define  PCI_PM_CTRL_STATE_MASK        0x0003  /* Current power state (D0 to D3) */
+#define  PCI_PM_CTRL_NO_SOFT_RESET     0x0004  /* No reset for D3hot->D0 */
+#define  PCI_PM_CTRL_PME_ENABLE        0x0100  /* PME pin enable */
+#define  PCI_PM_CTRL_DATA_SEL_MASK     0x1e00  /* Data select (??) */
+#define  PCI_PM_CTRL_DATA_SCALE_MASK   0x6000  /* Data scale (??) */
+#define  PCI_PM_CTRL_PME_STATUS        0x8000  /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS  6       /* PPB support extensions (??) */
+#define  PCI_PM_PPB_B2_B3      0x40    /* Stop clock when in D3hot (??) */
+#define  PCI_PM_BPCC_ENABLE    0x80    /* Bus power/clock control enable (??) */
+#define PCI_PM_DATA_REGISTER   7       /* (??) */
+#define PCI_PM_SIZEOF          8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION                2       /* BCD version number */
+#define PCI_AGP_RFU            3       /* Rest of capability flags */
+#define PCI_AGP_STATUS         4       /* Status register */
+#define  PCI_AGP_STATUS_RQ_MASK        0xff000000      /* Maximum number of requests - 1 */
+#define  PCI_AGP_STATUS_SBA    0x0200  /* Sideband addressing supported */
+#define  PCI_AGP_STATUS_64BIT  0x0020  /* 64-bit addressing supported */
+#define  PCI_AGP_STATUS_FW     0x0010  /* FW transfers supported */
+#define  PCI_AGP_STATUS_RATE4  0x0004  /* 4x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE2  0x0002  /* 2x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE1  0x0001  /* 1x transfer rate supported */
+#define PCI_AGP_COMMAND                8       /* Control register */
+#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
+#define  PCI_AGP_COMMAND_SBA   0x0200  /* Sideband addressing enabled */
+#define  PCI_AGP_COMMAND_AGP   0x0100  /* Allow processing of AGP transactions */
+#define  PCI_AGP_COMMAND_64BIT 0x0020  /* Allow processing of 64-bit addresses */
+#define  PCI_AGP_COMMAND_FW    0x0010  /* Force FW transfers */
+#define  PCI_AGP_COMMAND_RATE4 0x0004  /* Use 4x rate */
+#define  PCI_AGP_COMMAND_RATE2 0x0002  /* Use 2x rate */
+#define  PCI_AGP_COMMAND_RATE1 0x0001  /* Use 1x rate */
+#define PCI_AGP_SIZEOF         12
+
+/* Vital Product Data */
+
+#define PCI_VPD_ADDR           2       /* Address to access (15 bits!) */
+#define  PCI_VPD_ADDR_MASK     0x7fff  /* Address mask */
+#define  PCI_VPD_ADDR_F                0x8000  /* Write 0, 1 indicates completion */
+#define PCI_VPD_DATA           4       /* 32-bits of data returned here */
+
+/* Slot Identification */
+
+#define PCI_SID_ESR            2       /* Expansion Slot Register */
+#define  PCI_SID_ESR_NSLOTS    0x1f    /* Number of expansion slots available */
+#define  PCI_SID_ESR_FIC       0x20    /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR     3       /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS          2       /* Various flags */
+#define  PCI_MSI_FLAGS_64BIT   0x80    /* 64-bit addresses allowed */
+#define  PCI_MSI_FLAGS_QSIZE   0x70    /* Message queue size configured */
+#define  PCI_MSI_FLAGS_QMASK   0x0e    /* Maximum queue size available */
+#define  PCI_MSI_FLAGS_ENABLE  0x01    /* MSI feature enabled */
+#define  PCI_MSI_FLAGS_MASKBIT 0x100   /* 64-bit mask bits allowed */
+#define PCI_MSI_RFU            3       /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO     4       /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI     8       /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32                8       /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64                12      /* 16 bits of data for 64-bit devices */
+#define PCI_MSI_MASK_BIT       16      /* Mask bits register */
+
+/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */
+#define PCI_MSIX_FLAGS         2
+#define  PCI_MSIX_FLAGS_QSIZE  0x7FF
+#define  PCI_MSIX_FLAGS_ENABLE (1 << 15)
+#define  PCI_MSIX_FLAGS_MASKALL        (1 << 14)
+#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
+#define PCI_MSIX_FLAGS_BITMASK (1 << 0)
+
+/* CompactPCI Hotswap Register */
+
+#define PCI_CHSWP_CSR          2       /* Control and Status Register */
+#define  PCI_CHSWP_DHA         0x01    /* Device Hiding Arm */
+#define  PCI_CHSWP_EIM         0x02    /* ENUM# Signal Mask */
+#define  PCI_CHSWP_PIE         0x04    /* Pending Insert or Extract */
+#define  PCI_CHSWP_LOO         0x08    /* LED On / Off */
+#define  PCI_CHSWP_PI          0x30    /* Programming Interface */
+#define  PCI_CHSWP_EXT         0x40    /* ENUM# status - extraction */
+#define  PCI_CHSWP_INS         0x80    /* ENUM# status - insertion */
+
+/* PCI-X registers */
+
+#define PCI_X_CMD              2       /* Modes & Features */
+#define  PCI_X_CMD_DPERR_E     0x0001  /* Data Parity Error Recovery Enable */
+#define  PCI_X_CMD_ERO         0x0002  /* Enable Relaxed Ordering */
+#define  PCI_X_CMD_READ_512    0x0000  /* 512 byte maximum read byte count */
+#define  PCI_X_CMD_READ_1K     0x0004  /* 1Kbyte maximum read byte count */
+#define  PCI_X_CMD_READ_2K     0x0008  /* 2Kbyte maximum read byte count */
+#define  PCI_X_CMD_READ_4K     0x000c  /* 4Kbyte maximum read byte count */
+#define  PCI_X_CMD_MAX_READ    0x000c  /* Max Memory Read Byte Count */
+                               /* Max # of outstanding split transactions */
+#define  PCI_X_CMD_SPLIT_1     0x0000  /* Max 1 */
+#define  PCI_X_CMD_SPLIT_2     0x0010  /* Max 2 */
+#define  PCI_X_CMD_SPLIT_3     0x0020  /* Max 3 */
+#define  PCI_X_CMD_SPLIT_4     0x0030  /* Max 4 */
+#define  PCI_X_CMD_SPLIT_8     0x0040  /* Max 8 */
+#define  PCI_X_CMD_SPLIT_12    0x0050  /* Max 12 */
+#define  PCI_X_CMD_SPLIT_16    0x0060  /* Max 16 */
+#define  PCI_X_CMD_SPLIT_32    0x0070  /* Max 32 */
+#define  PCI_X_CMD_MAX_SPLIT   0x0070  /* Max Outstanding Split Transactions */
+#define  PCI_X_CMD_VERSION(x)  (((x) >> 12) & 3) /* Version */
+#define PCI_X_STATUS           4       /* PCI-X capabilities */
+#define  PCI_X_STATUS_DEVFN    0x000000ff      /* A copy of devfn */
+#define  PCI_X_STATUS_BUS      0x0000ff00      /* A copy of bus nr */
+#define  PCI_X_STATUS_64BIT    0x00010000      /* 64-bit device */
+#define  PCI_X_STATUS_133MHZ   0x00020000      /* 133 MHz capable */
+#define  PCI_X_STATUS_SPL_DISC 0x00040000      /* Split Completion Discarded */
+#define  PCI_X_STATUS_UNX_SPL  0x00080000      /* Unexpected Split Completion */
+#define  PCI_X_STATUS_COMPLEX  0x00100000      /* Device Complexity */
+#define  PCI_X_STATUS_MAX_READ 0x00600000      /* Designed Max Memory Read Count */
+#define  PCI_X_STATUS_MAX_SPLIT        0x03800000      /* Designed Max Outstanding Split Transactions */
+#define  PCI_X_STATUS_MAX_CUM  0x1c000000      /* Designed Max Cumulative Read Size */
+#define  PCI_X_STATUS_SPL_ERR  0x20000000      /* Rcvd Split Completion Error Msg */
+#define  PCI_X_STATUS_266MHZ   0x40000000      /* 266 MHz capable */
+#define  PCI_X_STATUS_533MHZ   0x80000000      /* 533 MHz capable */
+
+/* PCI Express capability registers */
+
+#define PCI_EXP_FLAGS          2       /* Capabilities register */
+#define PCI_EXP_FLAGS_VERS     0x000f  /* Capability version */
+#define PCI_EXP_FLAGS_TYPE     0x00f0  /* Device/Port type */
+#define  PCI_EXP_TYPE_ENDPOINT 0x0     /* Express Endpoint */
+#define  PCI_EXP_TYPE_LEG_END  0x1     /* Legacy Endpoint */
+#define  PCI_EXP_TYPE_ROOT_PORT 0x4    /* Root Port */
+#define  PCI_EXP_TYPE_UPSTREAM 0x5     /* Upstream Port */
+#define  PCI_EXP_TYPE_DOWNSTREAM 0x6   /* Downstream Port */
+#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7   /* PCI/PCI-X Bridge */
+#define PCI_EXP_FLAGS_SLOT     0x0100  /* Slot implemented */
+#define PCI_EXP_FLAGS_IRQ      0x3e00  /* Interrupt message number */
+#define PCI_EXP_DEVCAP         4       /* Device capabilities */
+#define  PCI_EXP_DEVCAP_PAYLOAD        0x07    /* Max_Payload_Size */
+#define  PCI_EXP_DEVCAP_PHANTOM        0x18    /* Phantom functions */
+#define  PCI_EXP_DEVCAP_EXT_TAG        0x20    /* Extended tags */
+#define  PCI_EXP_DEVCAP_L0S    0x1c0   /* L0s Acceptable Latency */
+#define  PCI_EXP_DEVCAP_L1     0xe00   /* L1 Acceptable Latency */
+#define  PCI_EXP_DEVCAP_ATN_BUT        0x1000  /* Attention Button Present */
+#define  PCI_EXP_DEVCAP_ATN_IND        0x2000  /* Attention Indicator Present */
+#define  PCI_EXP_DEVCAP_PWR_IND        0x4000  /* Power Indicator Present */
+#define  PCI_EXP_DEVCAP_RBER   0x8000  /* Role-Based Error Reporting */
+#define  PCI_EXP_DEVCAP_PWR_VAL        0x3fc0000 /* Slot Power Limit Value */
+#define  PCI_EXP_DEVCAP_PWR_SCL        0xc000000 /* Slot Power Limit Scale */
+#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
+#define PCI_EXP_DEVCTL         8       /* Device Control */
+#define  PCI_EXP_DEVCTL_CERE   0x0001  /* Correctable Error Reporting En. */
+#define  PCI_EXP_DEVCTL_NFERE  0x0002  /* Non-Fatal Error Reporting Enable */
+#define  PCI_EXP_DEVCTL_FERE   0x0004  /* Fatal Error Reporting Enable */
+#define  PCI_EXP_DEVCTL_URRE   0x0008  /* Unsupported Request Reporting En. */
+#define  PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
+#define  PCI_EXP_DEVCTL_PAYLOAD        0x00e0  /* Max_Payload_Size */
+#define  PCI_EXP_DEVCTL_EXT_TAG        0x0100  /* Extended Tag Field Enable */
+#define  PCI_EXP_DEVCTL_PHANTOM        0x0200  /* Phantom Functions Enable */
+#define  PCI_EXP_DEVCTL_AUX_PME        0x0400  /* Auxiliary Power PM Enable */
+#define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
+#define  PCI_EXP_DEVCTL_READRQ 0x7000  /* Max_Read_Request_Size */
+#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
+#define PCI_EXP_DEVSTA         10      /* Device Status */
+#define  PCI_EXP_DEVSTA_CED    0x01    /* Correctable Error Detected */
+#define  PCI_EXP_DEVSTA_NFED   0x02    /* Non-Fatal Error Detected */
+#define  PCI_EXP_DEVSTA_FED    0x04    /* Fatal Error Detected */
+#define  PCI_EXP_DEVSTA_URD    0x08    /* Unsupported Request Detected */
+#define  PCI_EXP_DEVSTA_AUXPD  0x10    /* AUX Power Detected */
+#define  PCI_EXP_DEVSTA_TRPND  0x20    /* Transactions Pending */
+#define PCI_EXP_LNKCAP         12      /* Link Capabilities */
+#define  PCI_EXP_LNKCAP_ASPMS  0xc00   /* ASPM Support */
+#define  PCI_EXP_LNKCAP_L0SEL  0x7000  /* L0s Exit Latency */
+#define  PCI_EXP_LNKCAP_L1EL   0x38000 /* L1 Exit Latency */
+#define  PCI_EXP_LNKCAP_CLKPM  0x40000 /* L1 Clock Power Management */
+#define PCI_EXP_LNKCTL         16      /* Link Control */
+#define  PCI_EXP_LNKCTL_RL     0x20    /* Retrain Link */
+#define  PCI_EXP_LNKCTL_CCC    0x40    /* Common Clock COnfiguration */
+#define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100        /* Enable clkreq */
+#define PCI_EXP_LNKSTA         18      /* Link Status */
+#define  PCI_EXP_LNKSTA_LT     0x800   /* Link Training */
+#define  PCI_EXP_LNKSTA_SLC    0x1000  /* Slot Clock Configuration */
+#define PCI_EXP_SLTCAP         20      /* Slot Capabilities */
+#define PCI_EXP_SLTCTL         24      /* Slot Control */
+#define PCI_EXP_SLTSTA         26      /* Slot Status */
+#define PCI_EXP_RTCTL          28      /* Root Control */
+#define  PCI_EXP_RTCTL_SECEE   0x01    /* System Error on Correctable Error */
+#define  PCI_EXP_RTCTL_SENFEE  0x02    /* System Error on Non-Fatal Error */
+#define  PCI_EXP_RTCTL_SEFEE   0x04    /* System Error on Fatal Error */
+#define  PCI_EXP_RTCTL_PMEIE   0x08    /* PME Interrupt Enable */
+#define  PCI_EXP_RTCTL_CRSSVE  0x10    /* CRS Software Visibility Enable */
+#define PCI_EXP_RTCAP          30      /* Root Capabilities */
+#define PCI_EXP_RTSTA          32      /* Root Status */
+#define PCI_EXP_DEVCAP2                36      /* Device Capabilities 2 */
+#define  PCI_EXP_DEVCAP2_ARI   0x20    /* Alternative Routing-ID */
+#define PCI_EXP_DEVCTL2                40      /* Device Control 2 */
+#define  PCI_EXP_DEVCTL2_ARI   0x20    /* Alternative Routing-ID */
+
+/* Extended Capabilities (PCI-X 2.0 and Express) */
+#define PCI_EXT_CAP_ID(header)         (header & 0x0000ffff)
+#define PCI_EXT_CAP_VER(header)                ((header >> 16) & 0xf)
+#define PCI_EXT_CAP_NEXT(header)       ((header >> 20) & 0xffc)
+
+#define PCI_EXT_CAP_ID_ERR     1
+#define PCI_EXT_CAP_ID_VC      2
+#define PCI_EXT_CAP_ID_DSN     3
+#define PCI_EXT_CAP_ID_PWR     4
+#define PCI_EXT_CAP_ID_ARI     14
+
+/* Advanced Error Reporting */
+#define PCI_ERR_UNCOR_STATUS   4       /* Uncorrectable Error Status */
+#define  PCI_ERR_UNC_TRAIN     0x00000001      /* Training */
+#define  PCI_ERR_UNC_DLP       0x00000010      /* Data Link Protocol */
+#define  PCI_ERR_UNC_POISON_TLP        0x00001000      /* Poisoned TLP */
+#define  PCI_ERR_UNC_FCP       0x00002000      /* Flow Control Protocol */
+#define  PCI_ERR_UNC_COMP_TIME 0x00004000      /* Completion Timeout */
+#define  PCI_ERR_UNC_COMP_ABORT        0x00008000      /* Completer Abort */
+#define  PCI_ERR_UNC_UNX_COMP  0x00010000      /* Unexpected Completion */
+#define  PCI_ERR_UNC_RX_OVER   0x00020000      /* Receiver Overflow */
+#define  PCI_ERR_UNC_MALF_TLP  0x00040000      /* Malformed TLP */
+#define  PCI_ERR_UNC_ECRC      0x00080000      /* ECRC Error Status */
+#define  PCI_ERR_UNC_UNSUP     0x00100000      /* Unsupported Request */
+#define PCI_ERR_UNCOR_MASK     8       /* Uncorrectable Error Mask */
+       /* Same bits as above */
+#define PCI_ERR_UNCOR_SEVER    12      /* Uncorrectable Error Severity */
+       /* Same bits as above */
+#define PCI_ERR_COR_STATUS     16      /* Correctable Error Status */
+#define  PCI_ERR_COR_RCVR      0x00000001      /* Receiver Error Status */
+#define  PCI_ERR_COR_BAD_TLP   0x00000040      /* Bad TLP Status */
+#define  PCI_ERR_COR_BAD_DLLP  0x00000080      /* Bad DLLP Status */
+#define  PCI_ERR_COR_REP_ROLL  0x00000100      /* REPLAY_NUM Rollover */
+#define  PCI_ERR_COR_REP_TIMER 0x00001000      /* Replay Timer Timeout */
+#define PCI_ERR_COR_MASK       20      /* Correctable Error Mask */
+       /* Same bits as above */
+#define PCI_ERR_CAP            24      /* Advanced Error Capabilities */
+#define  PCI_ERR_CAP_FEP(x)    ((x) & 31)      /* First Error Pointer */
+#define  PCI_ERR_CAP_ECRC_GENC 0x00000020      /* ECRC Generation Capable */
+#define  PCI_ERR_CAP_ECRC_GENE 0x00000040      /* ECRC Generation Enable */
+#define  PCI_ERR_CAP_ECRC_CHKC 0x00000080      /* ECRC Check Capable */
+#define  PCI_ERR_CAP_ECRC_CHKE 0x00000100      /* ECRC Check Enable */
+#define PCI_ERR_HEADER_LOG     28      /* Header Log Register (16 bytes) */
+#define PCI_ERR_ROOT_COMMAND   44      /* Root Error Command */
+/* Correctable Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_COR_EN                0x00000001
+/* Non-fatal Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_NONFATAL_EN   0x00000002
+/* Fatal Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_FATAL_EN      0x00000004
+#define PCI_ERR_ROOT_STATUS    48
+#define PCI_ERR_ROOT_COR_RCV           0x00000001      /* ERR_COR Received */
+/* Multi ERR_COR Received */
+#define PCI_ERR_ROOT_MULTI_COR_RCV     0x00000002
+/* ERR_FATAL/NONFATAL Recevied */
+#define PCI_ERR_ROOT_UNCOR_RCV         0x00000004
+/* Multi ERR_FATAL/NONFATAL Recevied */
+#define PCI_ERR_ROOT_MULTI_UNCOR_RCV   0x00000008
+#define PCI_ERR_ROOT_FIRST_FATAL       0x00000010      /* First Fatal */
+#define PCI_ERR_ROOT_NONFATAL_RCV      0x00000020      /* Non-Fatal Received */
+#define PCI_ERR_ROOT_FATAL_RCV         0x00000040      /* Fatal Received */
+#define PCI_ERR_ROOT_COR_SRC   52
+#define PCI_ERR_ROOT_SRC       54
+
+/* Virtual Channel */
+#define PCI_VC_PORT_REG1       4
+#define PCI_VC_PORT_REG2       8
+#define PCI_VC_PORT_CTRL       12
+#define PCI_VC_PORT_STATUS     14
+#define PCI_VC_RES_CAP         16
+#define PCI_VC_RES_CTRL                20
+#define PCI_VC_RES_STATUS      26
+
+/* Power Budgeting */
+#define PCI_PWR_DSR            4       /* Data Select Register */
+#define PCI_PWR_DATA           8       /* Data Register */
+#define  PCI_PWR_DATA_BASE(x)  ((x) & 0xff)        /* Base Power */
+#define  PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3)    /* Data Scale */
+#define  PCI_PWR_DATA_PM_SUB(x)        (((x) >> 10) & 7)   /* PM Sub State */
+#define  PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
+#define  PCI_PWR_DATA_TYPE(x)  (((x) >> 15) & 7)   /* Type */
+#define  PCI_PWR_DATA_RAIL(x)  (((x) >> 18) & 7)   /* Power Rail */
+#define PCI_PWR_CAP            12      /* Capability */
+#define  PCI_PWR_CAP_BUDGET(x) ((x) & 1)       /* Included in system budget */
+
+/*
+ * Hypertransport sub capability types
+ *
+ * Unfortunately there are both 3 bit and 5 bit capability types defined
+ * in the HT spec, catering for that is a little messy. You probably don't
+ * want to use these directly, just use pci_find_ht_capability() and it
+ * will do the right thing for you.
+ */
+#define HT_3BIT_CAP_MASK       0xE0
+#define HT_CAPTYPE_SLAVE       0x00    /* Slave/Primary link configuration */
+#define HT_CAPTYPE_HOST                0x20    /* Host/Secondary link configuration */
+
+#define HT_5BIT_CAP_MASK       0xF8
+#define HT_CAPTYPE_IRQ         0x80    /* IRQ Configuration */
+#define HT_CAPTYPE_REMAPPING_40        0xA0    /* 40 bit address remapping */
+#define HT_CAPTYPE_REMAPPING_64 0xA2   /* 64 bit address remapping */
+#define HT_CAPTYPE_UNITID_CLUMP        0x90    /* Unit ID clumping */
+#define HT_CAPTYPE_EXTCONF     0x98    /* Extended Configuration Space Access */
+#define HT_CAPTYPE_MSI_MAPPING 0xA8    /* MSI Mapping Capability */
+#define  HT_MSI_FLAGS          0x02            /* Offset to flags */
+#define  HT_MSI_FLAGS_ENABLE   0x1             /* Mapping enable */
+#define  HT_MSI_FLAGS_FIXED    0x2             /* Fixed mapping only */
+#define  HT_MSI_FIXED_ADDR     0x00000000FEE00000ULL   /* Fixed addr */
+#define  HT_MSI_ADDR_LO                0x04            /* Offset to low addr bits */
+#define  HT_MSI_ADDR_LO_MASK   0xFFF00000      /* Low address bit mask */
+#define  HT_MSI_ADDR_HI                0x08            /* Offset to high addr bits */
+#define HT_CAPTYPE_DIRECT_ROUTE        0xB0    /* Direct routing configuration */
+#define HT_CAPTYPE_VCSET       0xB8    /* Virtual Channel configuration */
+#define HT_CAPTYPE_ERROR_RETRY 0xC0    /* Retry on error configuration */
+#define HT_CAPTYPE_GEN3                0xD0    /* Generation 3 hypertransport configuration */
+#define HT_CAPTYPE_PM          0xE0    /* Hypertransport powermanagement configuration */
+
+/* Alternative Routing-ID Interpretation */
+#define PCI_ARI_CAP            0x04    /* ARI Capability Register */
+#define  PCI_ARI_CAP_MFVC      0x0001  /* MFVC Function Groups Capability */
+#define  PCI_ARI_CAP_ACS       0x0002  /* ACS Function Groups Capability */
+#define  PCI_ARI_CAP_NFN(x)    (((x) >> 8) & 0xff) /* Next Function Number */
+#define PCI_ARI_CTRL           0x06    /* ARI Control Register */
+#define  PCI_ARI_CTRL_MFVC     0x0001  /* MFVC Function Groups Enable */
+#define  PCI_ARI_CTRL_ACS      0x0002  /* ACS Function Groups Enable */
+#define  PCI_ARI_CTRL_FG(x)    (((x) >> 4) & 7) /* Function Group */
+
+#endif /* LINUX_PCI_REGS_H */
diff --git a/src/hw/pic.c b/src/hw/pic.c
new file mode 100644 (file)
index 0000000..9a3ea0b
--- /dev/null
@@ -0,0 +1,101 @@
+// Helpers for working with i8259 interrupt controller.
+//
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "pic.h" // pic_*
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // SET_IVT
+
+u16
+pic_irqmask_read(void)
+{
+    return inb(PORT_PIC1_DATA) | (inb(PORT_PIC2_DATA) << 8);
+}
+
+void
+pic_irqmask_write(u16 mask)
+{
+    outb(mask, PORT_PIC1_DATA);
+    outb(mask >> 8, PORT_PIC2_DATA);
+}
+
+void
+pic_irqmask_mask(u16 off, u16 on)
+{
+    u8 pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8;
+    outb((inb(PORT_PIC1_DATA) & ~pic1off) | pic1on, PORT_PIC1_DATA);
+    outb((inb(PORT_PIC2_DATA) & ~pic2off) | pic2on, PORT_PIC2_DATA);
+}
+
+void
+pic_reset(u8 irq0, u8 irq8)
+{
+    // Send ICW1 (select OCW1 + will send ICW4)
+    outb(0x11, PORT_PIC1_CMD);
+    outb(0x11, PORT_PIC2_CMD);
+    // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15)
+    outb(irq0, PORT_PIC1_DATA);
+    outb(irq8, PORT_PIC2_DATA);
+    // Send ICW3 (cascaded pic ids)
+    outb(0x04, PORT_PIC1_DATA);
+    outb(0x02, PORT_PIC2_DATA);
+    // Send ICW4 (enable 8086 mode)
+    outb(0x01, PORT_PIC1_DATA);
+    outb(0x01, PORT_PIC2_DATA);
+    // Mask all irqs (except cascaded PIC2 irq)
+    pic_irqmask_write(PIC_IRQMASK_DEFAULT);
+}
+
+void
+pic_setup(void)
+{
+    dprintf(3, "init pic\n");
+    pic_reset(BIOS_HWIRQ0_VECTOR, BIOS_HWIRQ8_VECTOR);
+}
+
+void
+enable_hwirq(int hwirq, struct segoff_s func)
+{
+    pic_irqmask_mask(1 << hwirq, 0);
+    int vector;
+    if (hwirq < 8)
+        vector = BIOS_HWIRQ0_VECTOR + hwirq;
+    else
+        vector = BIOS_HWIRQ8_VECTOR + hwirq - 8;
+    SET_IVT(vector, func);
+}
+
+static u8
+pic_isr1_read(void)
+{
+    // 0x0b == select OCW1 + read ISR
+    outb(0x0b, PORT_PIC1_CMD);
+    return inb(PORT_PIC1_CMD);
+}
+
+static u8
+pic_isr2_read(void)
+{
+    // 0x0b == select OCW1 + read ISR
+    outb(0x0b, PORT_PIC2_CMD);
+    return inb(PORT_PIC2_CMD);
+}
+
+// Handler for otherwise unused hardware irqs.
+void VISIBLE16
+handle_hwpic1(struct bregs *regs)
+{
+    dprintf(DEBUG_ISR_hwpic1, "handle_hwpic1 irq=%x\n", pic_isr1_read());
+    pic_eoi1();
+}
+
+void VISIBLE16
+handle_hwpic2(struct bregs *regs)
+{
+    dprintf(DEBUG_ISR_hwpic2, "handle_hwpic2 irq=%x\n", pic_isr2_read());
+    pic_eoi2();
+}
diff --git a/src/hw/pic.h b/src/hw/pic.h
new file mode 100644 (file)
index 0000000..19aecba
--- /dev/null
@@ -0,0 +1,52 @@
+// Helpers for working with i8259 interrupt controller.
+//
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+#ifndef __PIC_H
+#define __PIC_H
+
+#include "ioport.h" // PORT_PIC*
+#include "farptr.h" // struct segoff_s
+
+// PORT_PIC1 bitdefs
+#define PIC1_IRQ0  (1<<0)
+#define PIC1_IRQ1  (1<<1)
+#define PIC1_IRQ2  (1<<2)
+#define PIC1_IRQ5  (1<<5)
+#define PIC1_IRQ6  (1<<6)
+// PORT_PIC2 bitdefs
+#define PIC2_IRQ8  (1<<8)
+#define PIC2_IRQ12 (1<<12)
+#define PIC2_IRQ13 (1<<13)
+#define PIC2_IRQ14 (1<<14)
+
+#define PIC_IRQMASK_DEFAULT ((u16)~PIC1_IRQ2)
+
+#define BIOS_HWIRQ0_VECTOR 0x08
+#define BIOS_HWIRQ8_VECTOR 0x70
+
+static inline void
+pic_eoi1(void)
+{
+    // Send eoi (select OCW2 + eoi)
+    outb(0x20, PORT_PIC1_CMD);
+}
+
+static inline void
+pic_eoi2(void)
+{
+    // Send eoi (select OCW2 + eoi)
+    outb(0x20, PORT_PIC2_CMD);
+    pic_eoi1();
+}
+
+u16 pic_irqmask_read(void);
+void pic_irqmask_write(u16 mask);
+void pic_irqmask_mask(u16 off, u16 on);
+void pic_reset(u8 irq0, u8 irq8);
+void pic_setup(void);
+void enable_hwirq(int hwirq, struct segoff_s func);
+
+#endif // pic.h
diff --git a/src/hw/pit.h b/src/hw/pit.h
new file mode 100644 (file)
index 0000000..098f270
--- /dev/null
@@ -0,0 +1,29 @@
+// Definitions for the Intel 8253 Programmable Interrupt Timer (PIT).
+#ifndef __PIT_H
+#define __PIT_H
+
+// Bits for PORT_PIT_MODE
+#define PM_SEL_TIMER0   (0<<6)
+#define PM_SEL_TIMER1   (1<<6)
+#define PM_SEL_TIMER2   (2<<6)
+#define PM_SEL_READBACK (3<<6)
+#define PM_ACCESS_LATCH  (0<<4)
+#define PM_ACCESS_LOBYTE (1<<4)
+#define PM_ACCESS_HIBYTE (2<<4)
+#define PM_ACCESS_WORD   (3<<4)
+#define PM_MODE0 (0<<1)
+#define PM_MODE1 (1<<1)
+#define PM_MODE2 (2<<1)
+#define PM_MODE3 (3<<1)
+#define PM_MODE4 (4<<1)
+#define PM_MODE5 (5<<1)
+#define PM_CNT_BINARY (0<<0)
+#define PM_CNT_BCD    (1<<0)
+#define PM_READ_COUNTER0 (1<<1)
+#define PM_READ_COUNTER1 (1<<2)
+#define PM_READ_COUNTER2 (1<<3)
+#define PM_READ_STATUSVALUE (0<<4)
+#define PM_READ_VALUE       (1<<4)
+#define PM_READ_STATUS      (2<<4)
+
+#endif // pit.h
diff --git a/src/hw/ps2port.c b/src/hw/ps2port.c
new file mode 100644 (file)
index 0000000..4b6c5df
--- /dev/null
@@ -0,0 +1,504 @@
+// Support for handling the PS/2 mouse/keyboard ports.
+//
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Several ideas taken from code Copyright (c) 1999-2004 Vojtech Pavlik
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "ioport.h" // inb
+#include "util.h" // dprintf
+#include "biosvar.h" // GET_LOW
+#include "ps2port.h" // ps2_kbd_command
+#include "pic.h" // pic_eoi1
+
+
+/****************************************************************
+ * Low level i8042 commands.
+ ****************************************************************/
+
+// Timeout value.
+#define I8042_CTL_TIMEOUT       10000
+
+#define I8042_BUFFER_SIZE       16
+
+static int
+i8042_wait_read(void)
+{
+    dprintf(7, "i8042_wait_read\n");
+    int i;
+    for (i=0; i<I8042_CTL_TIMEOUT; i++) {
+        u8 status = inb(PORT_PS2_STATUS);
+        if (status & I8042_STR_OBF)
+            return 0;
+        udelay(50);
+    }
+    warn_timeout();
+    return -1;
+}
+
+static int
+i8042_wait_write(void)
+{
+    dprintf(7, "i8042_wait_write\n");
+    int i;
+    for (i=0; i<I8042_CTL_TIMEOUT; i++) {
+        u8 status = inb(PORT_PS2_STATUS);
+        if (! (status & I8042_STR_IBF))
+            return 0;
+        udelay(50);
+    }
+    warn_timeout();
+    return -1;
+}
+
+static int
+i8042_flush(void)
+{
+    dprintf(7, "i8042_flush\n");
+    int i;
+    for (i=0; i<I8042_BUFFER_SIZE; i++) {
+        u8 status = inb(PORT_PS2_STATUS);
+        if (! (status & I8042_STR_OBF))
+            return 0;
+        udelay(50);
+        u8 data = inb(PORT_PS2_DATA);
+        dprintf(7, "i8042 flushed %x (status=%x)\n", data, status);
+    }
+
+    warn_timeout();
+    return -1;
+}
+
+static int
+__i8042_command(int command, u8 *param)
+{
+    int receive = (command >> 8) & 0xf;
+    int send = (command >> 12) & 0xf;
+
+    // Send the command.
+    int ret = i8042_wait_write();
+    if (ret)
+        return ret;
+    outb(command, PORT_PS2_STATUS);
+
+    // Send parameters (if any).
+    int i;
+    for (i = 0; i < send; i++) {
+        ret = i8042_wait_write();
+        if (ret)
+            return ret;
+        outb(param[i], PORT_PS2_DATA);
+    }
+
+    // Receive parameters (if any).
+    for (i = 0; i < receive; i++) {
+        ret = i8042_wait_read();
+        if (ret)
+            return ret;
+        param[i] = inb(PORT_PS2_DATA);
+        dprintf(7, "i8042 param=%x\n", param[i]);
+    }
+
+    return 0;
+}
+
+static int
+i8042_command(int command, u8 *param)
+{
+    dprintf(7, "i8042_command cmd=%x\n", command);
+    int ret = __i8042_command(command, param);
+    if (ret)
+        dprintf(2, "i8042 command %x failed\n", command);
+    return ret;
+}
+
+static int
+i8042_kbd_write(u8 c)
+{
+    dprintf(7, "i8042_kbd_write c=%d\n", c);
+    int ret = i8042_wait_write();
+    if (! ret)
+        outb(c, PORT_PS2_DATA);
+    return ret;
+}
+
+static int
+i8042_aux_write(u8 c)
+{
+    return i8042_command(I8042_CMD_AUX_SEND, &c);
+}
+
+void
+i8042_reboot(void)
+{
+    if (! CONFIG_PS2PORT)
+       return;
+    int i;
+    for (i=0; i<10; i++) {
+        i8042_wait_write();
+        udelay(50);
+        outb(0xfe, PORT_PS2_STATUS); /* pulse reset low */
+        udelay(50);
+    }
+}
+
+
+/****************************************************************
+ * Device commands.
+ ****************************************************************/
+
+#define PS2_RET_ACK             0xfa
+#define PS2_RET_NAK             0xfe
+
+static int
+ps2_recvbyte(int aux, int needack, int timeout)
+{
+    u32 end = timer_calc(timeout);
+    for (;;) {
+        u8 status = inb(PORT_PS2_STATUS);
+        if (status & I8042_STR_OBF) {
+            u8 data = inb(PORT_PS2_DATA);
+            dprintf(7, "ps2 read %x\n", data);
+
+            if (!!(status & I8042_STR_AUXDATA) == aux) {
+                if (!needack)
+                    return data;
+                if (data == PS2_RET_ACK)
+                    return data;
+                if (data == PS2_RET_NAK) {
+                    dprintf(1, "Got ps2 nak (status=%x)\n", status);
+                    return data;
+                }
+            }
+
+            // This data not part of command - just discard it.
+            dprintf(1, "Discarding ps2 data %02x (status=%02x)\n", data, status);
+        }
+
+        if (timer_check(end)) {
+            // Don't warn on second byte of a reset
+            if (timeout > 100)
+                warn_timeout();
+            return -1;
+        }
+        yield();
+    }
+}
+
+static int
+ps2_sendbyte(int aux, u8 command, int timeout)
+{
+    dprintf(7, "ps2_sendbyte aux=%d cmd=%x\n", aux, command);
+    int ret;
+    if (aux)
+        ret = i8042_aux_write(command);
+    else
+        ret = i8042_kbd_write(command);
+    if (ret)
+        return ret;
+
+    // Read ack.
+    ret = ps2_recvbyte(aux, 1, timeout);
+    if (ret < 0)
+        return ret;
+    if (ret != PS2_RET_ACK)
+        return -1;
+
+    return 0;
+}
+
+u8 Ps2ctr VARLOW;
+
+static int
+__ps2_command(int aux, int command, u8 *param)
+{
+    int ret2;
+    int receive = (command >> 8) & 0xf;
+    int send = (command >> 12) & 0xf;
+
+    // Disable interrupts and keyboard/mouse.
+    u8 ps2ctr = GET_LOW(Ps2ctr);
+    u8 newctr = ((ps2ctr | I8042_CTR_AUXDIS | I8042_CTR_KBDDIS)
+                 & ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT));
+    dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr);
+    int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr);
+    if (ret)
+        return ret;
+
+    // Flush any interrupts already pending.
+    yield();
+
+    // Enable port command is being sent to.
+    if (aux)
+        newctr &= ~I8042_CTR_AUXDIS;
+    else
+        newctr &= ~I8042_CTR_KBDDIS;
+    ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr);
+    if (ret)
+        goto fail;
+
+    if (command == ATKBD_CMD_RESET_BAT) {
+        // Reset is special wrt timeouts and bytes received.
+
+        // Send command.
+        ret = ps2_sendbyte(aux, command, 1000);
+        if (ret)
+            goto fail;
+
+        // Receive parameters.
+        ret = ps2_recvbyte(aux, 0, 4000);
+        if (ret < 0)
+            goto fail;
+        param[0] = ret;
+        ret = ps2_recvbyte(aux, 0, 100);
+        if (ret < 0)
+            // Some devices only respond with one byte on reset.
+            ret = 0;
+        param[1] = ret;
+    } else if (command == ATKBD_CMD_GETID) {
+        // Getid is special wrt bytes received.
+
+        // Send command.
+        ret = ps2_sendbyte(aux, command, 200);
+        if (ret)
+            goto fail;
+
+        // Receive parameters.
+        ret = ps2_recvbyte(aux, 0, 500);
+        if (ret < 0)
+            goto fail;
+        param[0] = ret;
+        if (ret == 0xab || ret == 0xac || ret == 0x2b || ret == 0x5d
+            || ret == 0x60 || ret == 0x47) {
+            // These ids (keyboards) return two bytes.
+            ret = ps2_recvbyte(aux, 0, 500);
+            if (ret < 0)
+                goto fail;
+            param[1] = ret;
+        } else {
+            param[1] = 0;
+        }
+    } else {
+        // Send command.
+        ret = ps2_sendbyte(aux, command, 200);
+        if (ret)
+            goto fail;
+
+        // Send parameters (if any).
+        int i;
+        for (i = 0; i < send; i++) {
+            ret = ps2_sendbyte(aux, param[i], 200);
+            if (ret)
+                goto fail;
+        }
+
+        // Receive parameters (if any).
+        for (i = 0; i < receive; i++) {
+            ret = ps2_recvbyte(aux, 0, 500);
+            if (ret < 0)
+                goto fail;
+            param[i] = ret;
+        }
+    }
+
+    ret = 0;
+
+fail:
+    // Restore interrupts and keyboard/mouse.
+    ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr);
+    if (ret2)
+        return ret2;
+
+    return ret;
+}
+
+static int
+ps2_command(int aux, int command, u8 *param)
+{
+    dprintf(7, "ps2_command aux=%d cmd=%x\n", aux, command);
+    int ret = __ps2_command(aux, command, param);
+    if (ret)
+        dprintf(2, "ps2 command %x failed (aux=%d)\n", command, aux);
+    return ret;
+}
+
+int
+ps2_kbd_command(int command, u8 *param)
+{
+    if (! CONFIG_PS2PORT)
+        return -1;
+    return ps2_command(0, command, param);
+}
+
+int
+ps2_mouse_command(int command, u8 *param)
+{
+    if (! CONFIG_PS2PORT)
+        return -1;
+
+    // Update ps2ctr for mouse enable/disable.
+    if (command == PSMOUSE_CMD_ENABLE || command == PSMOUSE_CMD_DISABLE) {
+        u8 ps2ctr = GET_LOW(Ps2ctr);
+        if (command == PSMOUSE_CMD_ENABLE)
+            ps2ctr = (ps2ctr | I8042_CTR_AUXINT) & ~I8042_CTR_AUXDIS;
+        else
+            ps2ctr = (ps2ctr | I8042_CTR_AUXDIS) & ~I8042_CTR_AUXINT;
+        SET_LOW(Ps2ctr, ps2ctr);
+    }
+
+    return ps2_command(1, command, param);
+}
+
+
+/****************************************************************
+ * IRQ handlers
+ ****************************************************************/
+
+// INT74h : PS/2 mouse hardware interrupt
+void VISIBLE16
+handle_74(void)
+{
+    if (! CONFIG_PS2PORT)
+        return;
+
+    debug_isr(DEBUG_ISR_74);
+
+    u8 v = inb(PORT_PS2_STATUS);
+    if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA))
+        != (I8042_STR_OBF|I8042_STR_AUXDATA)) {
+        dprintf(1, "ps2 mouse irq but no mouse data.\n");
+        goto done;
+    }
+    v = inb(PORT_PS2_DATA);
+
+    if (!(GET_LOW(Ps2ctr) & I8042_CTR_AUXINT))
+        // Interrupts not enabled.
+        goto done;
+
+    process_mouse(v);
+
+done:
+    pic_eoi2();
+}
+
+// INT09h : Keyboard Hardware Service Entry Point
+void VISIBLE16
+handle_09(void)
+{
+    if (! CONFIG_PS2PORT)
+        return;
+
+    debug_isr(DEBUG_ISR_09);
+
+    // read key from keyboard controller
+    u8 v = inb(PORT_PS2_STATUS);
+    if (v & I8042_STR_AUXDATA) {
+        dprintf(1, "ps2 keyboard irq but found mouse data?!\n");
+        goto done;
+    }
+    v = inb(PORT_PS2_DATA);
+
+    if (!(GET_LOW(Ps2ctr) & I8042_CTR_KBDINT))
+        // Interrupts not enabled.
+        goto done;
+
+    process_key(v);
+
+    // Some old programs expect ISR to turn keyboard back on.
+    i8042_command(I8042_CMD_KBD_ENABLE, NULL);
+
+done:
+    pic_eoi1();
+}
+
+
+/****************************************************************
+ * Setup
+ ****************************************************************/
+
+static void
+ps2_keyboard_setup(void *data)
+{
+    /* flush incoming keys */
+    int ret = i8042_flush();
+    if (ret)
+        return;
+
+    // Controller self-test.
+    u8 param[2];
+    ret = i8042_command(I8042_CMD_CTL_TEST, param);
+    if (ret)
+        return;
+    if (param[0] != 0x55) {
+        dprintf(1, "i8042 self test failed (got %x not 0x55)\n", param[0]);
+        return;
+    }
+
+    // Controller keyboard test.
+    ret = i8042_command(I8042_CMD_KBD_TEST, param);
+    if (ret)
+        return;
+    if (param[0] != 0x00) {
+        dprintf(1, "i8042 keyboard test failed (got %x not 0x00)\n", param[0]);
+        return;
+    }
+
+    // Disable keyboard and mouse events.
+    SET_LOW(Ps2ctr, I8042_CTR_KBDDIS | I8042_CTR_AUXDIS);
+
+
+    /* ------------------- keyboard side ------------------------*/
+    /* reset keyboard and self test  (keyboard side) */
+    int spinupdelay = romfile_loadint("etc/ps2-keyboard-spinup", 0);
+    u32 end = timer_calc(spinupdelay);
+    for (;;) {
+        ret = ps2_kbd_command(ATKBD_CMD_RESET_BAT, param);
+        if (!ret)
+            break;
+        if (timer_check(end)) {
+            if (spinupdelay)
+                warn_timeout();
+            return;
+        }
+        yield();
+    }
+    if (param[0] != 0xaa) {
+        dprintf(1, "keyboard self test failed (got %x not 0xaa)\n", param[0]);
+        return;
+    }
+
+    /* Disable keyboard */
+    ret = ps2_kbd_command(ATKBD_CMD_RESET_DIS, NULL);
+    if (ret)
+        return;
+
+    // Set scancode command (mode 2)
+    param[0] = 0x02;
+    ret = ps2_kbd_command(ATKBD_CMD_SSCANSET, param);
+    if (ret)
+        return;
+
+    // Keyboard Mode: disable mouse, scan code convert, enable kbd IRQ
+    SET_LOW(Ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT);
+
+    /* Enable keyboard */
+    ret = ps2_kbd_command(ATKBD_CMD_ENABLE, NULL);
+    if (ret)
+        return;
+
+    dprintf(1, "PS2 keyboard initialized\n");
+}
+
+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(ps2_keyboard_setup, NULL);
+}
diff --git a/src/hw/ps2port.h b/src/hw/ps2port.h
new file mode 100644 (file)
index 0000000..dcae391
--- /dev/null
@@ -0,0 +1,63 @@
+// Basic ps2 port (keyboard/mouse) command handling.
+#ifndef __PS2PORT_H
+#define __PS2PORT_H
+
+#include "types.h" // u8
+
+// Standard commands.
+#define I8042_CMD_CTL_RCTR      0x0120
+#define I8042_CMD_CTL_WCTR      0x1060
+#define I8042_CMD_CTL_TEST      0x01aa
+
+#define I8042_CMD_KBD_TEST      0x01ab
+#define I8042_CMD_KBD_DISABLE   0x00ad
+#define I8042_CMD_KBD_ENABLE    0x00ae
+
+#define I8042_CMD_AUX_DISABLE   0x00a7
+#define I8042_CMD_AUX_ENABLE    0x00a8
+#define I8042_CMD_AUX_SEND      0x10d4
+
+// Keyboard commands
+#define ATKBD_CMD_SETLEDS       0x10ed
+#define ATKBD_CMD_SSCANSET      0x10f0
+#define ATKBD_CMD_GETID         0x02f2
+#define ATKBD_CMD_ENABLE        0x00f4
+#define ATKBD_CMD_RESET_DIS     0x00f5
+#define ATKBD_CMD_RESET_BAT     0x02ff
+
+// Mouse commands
+#define PSMOUSE_CMD_SETSCALE11  0x00e6
+#define PSMOUSE_CMD_SETSCALE21  0x00e7
+#define PSMOUSE_CMD_SETRES      0x10e8
+#define PSMOUSE_CMD_GETINFO     0x03e9
+#define PSMOUSE_CMD_GETID       0x02f2
+#define PSMOUSE_CMD_SETRATE     0x10f3
+#define PSMOUSE_CMD_ENABLE      0x00f4
+#define PSMOUSE_CMD_DISABLE     0x00f5
+#define PSMOUSE_CMD_RESET_BAT   0x02ff
+
+// Status register bits.
+#define I8042_STR_PARITY        0x80
+#define I8042_STR_TIMEOUT       0x40
+#define I8042_STR_AUXDATA       0x20
+#define I8042_STR_KEYLOCK       0x10
+#define I8042_STR_CMDDAT        0x08
+#define I8042_STR_MUXERR        0x04
+#define I8042_STR_IBF           0x02
+#define I8042_STR_OBF           0x01
+
+// Control register bits.
+#define I8042_CTR_KBDINT        0x01
+#define I8042_CTR_AUXINT        0x02
+#define I8042_CTR_IGNKEYLOCK    0x08
+#define I8042_CTR_KBDDIS        0x10
+#define I8042_CTR_AUXDIS        0x20
+#define I8042_CTR_XLATE         0x40
+
+// functions
+void i8042_reboot(void);
+int ps2_kbd_command(int command, u8 *param);
+int ps2_mouse_command(int command, u8 *param);
+void ps2port_setup(void);
+
+#endif // ps2port.h
diff --git a/src/hw/ramdisk.c b/src/hw/ramdisk.c
new file mode 100644 (file)
index 0000000..b9da2ad
--- /dev/null
@@ -0,0 +1,107 @@
+// Code for emulating a drive via high-memory accesses.
+//
+// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "disk.h" // process_ramdisk_op
+#include "util.h" // dprintf
+#include "memmap.h" // add_e820
+#include "biosvar.h" // GET_GLOBAL
+#include "bregs.h" // struct bregs
+#include "boot.h" // boot_add_floppy
+
+void
+ramdisk_setup(void)
+{
+    if (!CONFIG_FLASH_FLOPPY)
+        return;
+
+    // Find image.
+    struct romfile_s *file = romfile_findprefix("floppyimg/", NULL);
+    if (!file)
+        return;
+    const char *filename = file->name;
+    u32 size = file->size;
+    dprintf(3, "Found floppy file %s of size %d\n", filename, size);
+    int ftype = find_floppy_type(size);
+    if (ftype < 0) {
+        dprintf(3, "No floppy type found for ramdisk size\n");
+        return;
+    }
+
+    // Allocate ram for image.
+    void *pos = memalign_tmphigh(PAGE_SIZE, size);
+    if (!pos) {
+        warn_noalloc();
+        return;
+    }
+    add_e820((u32)pos, size, E820_RESERVED);
+
+    // Copy image into ram.
+    int ret = file->copy(file, pos, size);
+    if (ret < 0)
+        return;
+
+    // Setup driver.
+    struct drive_s *drive_g = init_floppy((u32)pos, ftype);
+    if (!drive_g)
+        return;
+    drive_g->type = DTYPE_RAMDISK;
+    dprintf(1, "Mapping CBFS floppy %s to addr %p\n", filename, pos);
+    char *desc = znprintf(MAXDESCSIZE, "Ramdisk [%s]", &filename[10]);
+    boot_add_floppy(drive_g, desc, bootprio_find_named_rom(filename, 0));
+}
+
+static int
+ramdisk_copy(struct disk_op_s *op, int iswrite)
+{
+    u32 offset = GET_GLOBAL(op->drive_g->cntl_id);
+    offset += (u32)op->lba * DISK_SECTOR_SIZE;
+    u64 opd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)op->buf_fl);
+    u64 ramd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE(offset);
+
+    u64 gdt[6];
+    if (iswrite) {
+        gdt[2] = opd;
+        gdt[3] = ramd;
+    } else {
+        gdt[2] = ramd;
+        gdt[3] = opd;
+    }
+
+    // Call int 1587 to copy data.
+    struct bregs br;
+    memset(&br, 0, sizeof(br));
+    br.flags = F_CF|F_IF;
+    br.ah = 0x87;
+    br.es = GET_SEG(SS);
+    br.si = (u32)gdt;
+    br.cx = op->count * DISK_SECTOR_SIZE / 2;
+    call16_int(0x15, &br);
+
+    if (br.flags & F_CF)
+        return DISK_RET_EBADTRACK;
+    return DISK_RET_SUCCESS;
+}
+
+int
+process_ramdisk_op(struct disk_op_s *op)
+{
+    if (!CONFIG_FLASH_FLOPPY)
+        return 0;
+
+    switch (op->command) {
+    case CMD_READ:
+        return ramdisk_copy(op, 0);
+    case CMD_WRITE:
+        return ramdisk_copy(op, 1);
+    case CMD_VERIFY:
+    case CMD_FORMAT:
+    case CMD_RESET:
+        return DISK_RET_SUCCESS;
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
diff --git a/src/hw/timer.c b/src/hw/timer.c
new file mode 100644 (file)
index 0000000..b368362
--- /dev/null
@@ -0,0 +1,241 @@
+// Internal timer support.
+//
+// Copyright (C) 2008-2013  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pit.h" // PM_SEL_TIMER0
+#include "ioport.h" // PORT_PIT_MODE
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_LOW
+
+// Bits for PORT_PS2_CTRLB
+#define PPCB_T2GATE (1<<0)
+#define PPCB_SPKR   (1<<1)
+#define PPCB_T2OUT  (1<<5)
+
+#define PMTIMER_HZ 3579545      // Underlying Hz of the PM Timer
+#define PMTIMER_TO_PIT 3        // Ratio of pmtimer rate to pit rate
+
+u32 TimerKHz VARFSEG;
+u16 TimerPort VARFSEG;
+u8 ShiftTSC VARFSEG;
+
+
+/****************************************************************
+ * Timer setup
+ ****************************************************************/
+
+#define CALIBRATE_COUNT 0x800   // Approx 1.7ms
+
+// Calibrate the CPU time-stamp-counter
+static void
+tsctimer_setup(void)
+{
+    // Setup "timer2"
+    u8 orig = inb(PORT_PS2_CTRLB);
+    outb((orig & ~PPCB_SPKR) | PPCB_T2GATE, PORT_PS2_CTRLB);
+    /* binary, mode 0, LSB/MSB, Ch 2 */
+    outb(PM_SEL_TIMER2|PM_ACCESS_WORD|PM_MODE0|PM_CNT_BINARY, PORT_PIT_MODE);
+    /* LSB of ticks */
+    outb(CALIBRATE_COUNT & 0xFF, PORT_PIT_COUNTER2);
+    /* MSB of ticks */
+    outb(CALIBRATE_COUNT >> 8, PORT_PIT_COUNTER2);
+
+    u64 start = rdtscll();
+    while ((inb(PORT_PS2_CTRLB) & PPCB_T2OUT) == 0)
+        ;
+    u64 end = rdtscll();
+
+    // Restore PORT_PS2_CTRLB
+    outb(orig, PORT_PS2_CTRLB);
+
+    // Store calibrated cpu khz.
+    u64 diff = end - start;
+    dprintf(6, "tsc calibrate start=%u end=%u diff=%u\n"
+            , (u32)start, (u32)end, (u32)diff);
+    u64 t = DIV_ROUND_UP(diff * PMTIMER_HZ, CALIBRATE_COUNT);
+    while (t >= (1<<24)) {
+        ShiftTSC++;
+        t = (t + 1) >> 1;
+    }
+    TimerKHz = DIV_ROUND_UP((u32)t, 1000 * PMTIMER_TO_PIT);
+
+    dprintf(1, "CPU Mhz=%u\n", (TimerKHz << ShiftTSC) / 1000);
+}
+
+// Setup internal timers.
+void
+timer_setup(void)
+{
+    if (CONFIG_PMTIMER && TimerPort) {
+        dprintf(3, "pmtimer already configured; will not calibrate TSC\n");
+        return;
+    }
+
+    u32 eax, ebx, ecx, edx, cpuid_features = 0;
+    cpuid(0, &eax, &ebx, &ecx, &edx);
+    if (eax > 0)
+        cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
+
+    if (!(cpuid_features & CPUID_TSC)) {
+        TimerPort = PORT_PIT_COUNTER0;
+        TimerKHz = DIV_ROUND_UP(PMTIMER_HZ, 1000 * PMTIMER_TO_PIT);
+        dprintf(3, "386/486 class CPU. Using TSC emulation\n");
+        return;
+    }
+
+    tsctimer_setup();
+}
+
+void
+pmtimer_setup(u16 ioport)
+{
+    if (!CONFIG_PMTIMER)
+        return;
+    dprintf(1, "Using pmtimer, ioport 0x%x\n", ioport);
+    TimerPort = ioport;
+    TimerKHz = DIV_ROUND_UP(PMTIMER_HZ, 1000);
+}
+
+
+/****************************************************************
+ * Internal timer reading
+ ****************************************************************/
+
+u32 TimerLast VARLOW;
+
+// Add extra high bits to timers that have less than 32bits of precision.
+static u32
+timer_adjust_bits(u32 value, u32 validbits)
+{
+    u32 last = GET_LOW(TimerLast);
+    value = (last & ~validbits) | (value & validbits);
+    if (value < last)
+        value += validbits + 1;
+    SET_LOW(TimerLast, value);
+    return value;
+}
+
+// Sample the current timer value.
+static u32
+timer_read(void)
+{
+    u16 port = GET_GLOBAL(TimerPort);
+    if (!port)
+        // Read from CPU TSC
+        return rdtscll() >> GET_GLOBAL(ShiftTSC);
+    if (CONFIG_PMTIMER && port != PORT_PIT_COUNTER0)
+        // Read from PMTIMER
+        return timer_adjust_bits(inl(port), 0xffffff);
+    // Read from PIT.
+    outb(PM_SEL_READBACK | PM_READ_VALUE | PM_READ_COUNTER0, PORT_PIT_MODE);
+    u16 v = inb(PORT_PIT_COUNTER0) | (inb(PORT_PIT_COUNTER0) << 8);
+    return timer_adjust_bits(v, 0xffff);
+}
+
+// Check if the current time is past a previously calculated end time.
+int
+timer_check(u32 end)
+{
+    return (s32)(timer_read() - end) > 0;
+}
+
+static void
+timer_delay(u32 diff)
+{
+    u32 start = timer_read();
+    u32 end = start + diff;
+    while (!timer_check(end))
+        cpu_relax();
+}
+
+static void
+timer_sleep(u32 diff)
+{
+    u32 start = timer_read();
+    u32 end = start + diff;
+    while (!timer_check(end))
+        yield();
+}
+
+void ndelay(u32 count) {
+    timer_delay(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000000));
+}
+void udelay(u32 count) {
+    timer_delay(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000));
+}
+void mdelay(u32 count) {
+    timer_delay(count * GET_GLOBAL(TimerKHz));
+}
+
+void nsleep(u32 count) {
+    timer_sleep(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000000));
+}
+void usleep(u32 count) {
+    timer_sleep(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000));
+}
+void msleep(u32 count) {
+    timer_sleep(count * GET_GLOBAL(TimerKHz));
+}
+
+// Return the TSC value that is 'msecs' time in the future.
+u32
+timer_calc(u32 msecs)
+{
+    return timer_read() + (GET_GLOBAL(TimerKHz) * msecs);
+}
+u32
+timer_calc_usec(u32 usecs)
+{
+    return timer_read() + DIV_ROUND_UP(GET_GLOBAL(TimerKHz) * usecs, 1000);
+}
+
+
+/****************************************************************
+ * IRQ based timer
+ ****************************************************************/
+
+#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer
+
+// Return the number of milliseconds in 'ticks' number of timer irqs.
+u32
+ticks_to_ms(u32 ticks)
+{
+    u32 t = PIT_TICK_INTERVAL * 1000 * PMTIMER_TO_PIT * ticks;
+    return DIV_ROUND_UP(t, PMTIMER_HZ);
+}
+
+// Return the number of timer irqs in 'ms' number of milliseconds.
+u32
+ticks_from_ms(u32 ms)
+{
+    u32 t = DIV_ROUND_UP((u64)ms * PMTIMER_HZ, PIT_TICK_INTERVAL);
+    return DIV_ROUND_UP(t, 1000 * PMTIMER_TO_PIT);
+}
+
+// Calculate the timer value at 'count' number of full timer ticks in
+// the future.
+u32
+irqtimer_calc_ticks(u32 count)
+{
+    return (GET_BDA(timer_counter) + count + 1) % TICKS_PER_DAY;
+}
+
+// Return the timer value that is 'msecs' time in the future.
+u32
+irqtimer_calc(u32 msecs)
+{
+    if (!msecs)
+        return GET_BDA(timer_counter);
+    return irqtimer_calc_ticks(ticks_from_ms(msecs));
+}
+
+// Check if the given timer value has passed.
+int
+irqtimer_check(u32 end)
+{
+    return (((GET_BDA(timer_counter) + TICKS_PER_DAY - end) % TICKS_PER_DAY)
+            < (TICKS_PER_DAY/2));
+}
diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c
new file mode 100644 (file)
index 0000000..978ca68
--- /dev/null
@@ -0,0 +1,723 @@
+// Code for handling EHCI USB controllers.
+//
+// Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // pci_bdf_to_bus
+#include "config.h" // CONFIG_*
+#include "ioport.h" // outw
+#include "usb-ehci.h" // struct ehci_qh
+#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI
+#include "pci_regs.h" // PCI_BASE_ADDRESS_0
+#include "usb.h" // struct usb_s
+#include "biosvar.h" // GET_LOWFLAT
+#include "usb-uhci.h" // uhci_setup
+#include "usb-ohci.h" // ohci_setup
+
+struct usb_ehci_s {
+    struct usb_s usb;
+    struct ehci_caps *caps;
+    struct ehci_regs *regs;
+    struct ehci_qh *async_qh;
+    struct pci_device *companion[8];
+    int checkports;
+    int legacycount;
+};
+
+struct ehci_pipe {
+    struct ehci_qh qh;
+    struct ehci_qtd *next_td, *tds;
+    void *data;
+    struct usb_pipe pipe;
+};
+
+
+/****************************************************************
+ * Root hub
+ ****************************************************************/
+
+#define EHCI_TIME_POSTPOWER 20
+#define EHCI_TIME_POSTRESET 2
+
+// Check if need companion controllers for full/low speed devices
+static void
+ehci_note_port(struct usb_ehci_s *cntl)
+{
+    if (--cntl->checkports)
+        // Ports still being detected.
+        return;
+    if (! cntl->legacycount)
+        // No full/low speed devices found.
+        return;
+    // Start companion controllers.
+    int i;
+    for (i=0; i<ARRAY_SIZE(cntl->companion); i++) {
+        struct pci_device *pci = cntl->companion[i];
+        if (!pci)
+            break;
+
+        // ohci/uhci_setup call pci_config_X - don't run from irq handler.
+        wait_preempt();
+
+        if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI)
+            uhci_setup(pci, cntl->usb.busid + i);
+        else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI)
+            ohci_setup(pci, cntl->usb.busid + i);
+    }
+}
+
+// Check if device attached to port
+static int
+ehci_hub_detect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
+    u32 *portreg = &cntl->regs->portsc[port];
+    u32 portsc = readl(portreg);
+
+    // Power up port.
+    if (!(portsc & PORT_POWER)) {
+        portsc |= PORT_POWER;
+        writel(portreg, portsc);
+        msleep(EHCI_TIME_POSTPOWER);
+    } else {
+        // Port is already powered up, but we don't know how long it
+        // has been powered up, so wait the 20ms.
+        msleep(EHCI_TIME_POSTPOWER);
+    }
+    portsc = readl(portreg);
+
+    if (!(portsc & PORT_CONNECT))
+        // No device present
+        goto doneearly;
+
+    if ((portsc & PORT_LINESTATUS_MASK) == PORT_LINESTATUS_KSTATE) {
+        // low speed device
+        cntl->legacycount++;
+        writel(portreg, portsc | PORT_OWNER);
+        goto doneearly;
+    }
+
+    // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
+
+    // Begin reset on port
+    portsc = (portsc & ~PORT_PE) | PORT_RESET;
+    writel(portreg, portsc);
+    msleep(USB_TIME_DRSTR);
+    return 0;
+
+doneearly:
+    ehci_note_port(cntl);
+    return -1;
+}
+
+// Reset device on port
+static int
+ehci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
+    u32 *portreg = &cntl->regs->portsc[port];
+    u32 portsc = readl(portreg);
+
+    // Finish reset on port
+    portsc &= ~PORT_RESET;
+    writel(portreg, portsc);
+    msleep(EHCI_TIME_POSTRESET);
+
+    int rv = -1;
+    portsc = readl(portreg);
+    if (!(portsc & PORT_CONNECT))
+        // No longer connected
+        goto resetfail;
+    if (!(portsc & PORT_PE)) {
+        // full speed device
+        cntl->legacycount++;
+        writel(portreg, portsc | PORT_OWNER);
+        goto resetfail;
+    }
+
+    rv = USB_HIGHSPEED;
+resetfail:
+    ehci_note_port(cntl);
+    return rv;
+}
+
+// Disable port
+static void
+ehci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
+    u32 *portreg = &cntl->regs->portsc[port];
+    u32 portsc = readl(portreg);
+    writel(portreg, portsc & ~PORT_PE);
+}
+
+static struct usbhub_op_s ehci_HubOp = {
+    .detect = ehci_hub_detect,
+    .reset = ehci_hub_reset,
+    .disconnect = ehci_hub_disconnect,
+};
+
+// 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;
+}
+
+
+/****************************************************************
+ * Setup
+ ****************************************************************/
+
+// Wait for next USB async frame to start - for ensuring safe memory release.
+static void
+ehci_waittick(struct usb_ehci_s *cntl)
+{
+    if (MODE16) {
+        msleep(10);
+        return;
+    }
+    // Wait for access to "doorbell"
+    barrier();
+    u32 cmd, sts;
+    u32 end = timer_calc(100);
+    for (;;) {
+        sts = readl(&cntl->regs->usbsts);
+        if (!(sts & STS_IAA)) {
+            cmd = readl(&cntl->regs->usbcmd);
+            if (!(cmd & CMD_IAAD))
+                break;
+        }
+        if (timer_check(end)) {
+            warn_timeout();
+            return;
+        }
+        yield();
+    }
+    // Ring "doorbell"
+    writel(&cntl->regs->usbcmd, cmd | CMD_IAAD);
+    // Wait for completion
+    for (;;) {
+        sts = readl(&cntl->regs->usbsts);
+        if (sts & STS_IAA)
+            break;
+        if (timer_check(end)) {
+            warn_timeout();
+            return;
+        }
+        yield();
+    }
+    // Ack completion
+    writel(&cntl->regs->usbsts, STS_IAA);
+}
+
+static void
+ehci_free_pipes(struct usb_ehci_s *cntl)
+{
+    dprintf(7, "ehci_free_pipes %p\n", cntl);
+
+    struct ehci_qh *start = cntl->async_qh;
+    struct ehci_qh *pos = start;
+    for (;;) {
+        struct ehci_qh *next = (void*)(pos->next & ~EHCI_PTR_BITS);
+        if (next == start)
+            break;
+        struct ehci_pipe *pipe = container_of(next, struct ehci_pipe, qh);
+        if (pipe->pipe.cntl != &cntl->usb)
+            pos->next = next->next;
+        else
+            pos = next;
+    }
+    ehci_waittick(cntl);
+    for (;;) {
+        struct usb_pipe *usbpipe = cntl->usb.freelist;
+        if (!usbpipe)
+            break;
+        cntl->usb.freelist = usbpipe->freenext;
+        struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe);
+        free(pipe);
+    }
+}
+
+static void
+configure_ehci(void *data)
+{
+    struct usb_ehci_s *cntl = data;
+
+    // Allocate ram for schedule storage
+    struct ehci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl));
+    struct ehci_qh *intr_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*intr_qh));
+    struct ehci_qh *async_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*async_qh));
+    if (!fl || !intr_qh || !async_qh) {
+        warn_noalloc();
+        goto fail;
+    }
+
+    // XXX - check for halted?
+
+    // Reset the HC
+    u32 cmd = readl(&cntl->regs->usbcmd);
+    writel(&cntl->regs->usbcmd, (cmd & ~(CMD_ASE | CMD_PSE)) | CMD_HCRESET);
+    u32 end = timer_calc(250);
+    for (;;) {
+        cmd = readl(&cntl->regs->usbcmd);
+        if (!(cmd & CMD_HCRESET))
+            break;
+        if (timer_check(end)) {
+            warn_timeout();
+            goto fail;
+        }
+        yield();
+    }
+
+    // Disable interrupts (just to be safe).
+    writel(&cntl->regs->usbintr, 0);
+
+    // Set schedule to point to primary intr queue head
+    memset(intr_qh, 0, sizeof(*intr_qh));
+    intr_qh->next = EHCI_PTR_TERM;
+    intr_qh->info2 = (0x01 << QH_SMASK_SHIFT);
+    intr_qh->token = QTD_STS_HALT;
+    intr_qh->qtd_next = intr_qh->alt_next = EHCI_PTR_TERM;
+    int i;
+    for (i=0; i<ARRAY_SIZE(fl->links); i++)
+        fl->links[i] = (u32)intr_qh | EHCI_PTR_QH;
+    writel(&cntl->regs->periodiclistbase, (u32)fl);
+
+    // Set async list to point to primary async queue head
+    memset(async_qh, 0, sizeof(*async_qh));
+    async_qh->next = (u32)async_qh | EHCI_PTR_QH;
+    async_qh->info1 = QH_HEAD;
+    async_qh->token = QTD_STS_HALT;
+    async_qh->qtd_next = async_qh->alt_next = EHCI_PTR_TERM;
+    cntl->async_qh = async_qh;
+    writel(&cntl->regs->asynclistbase, (u32)async_qh);
+
+    // Enable queues
+    writel(&cntl->regs->usbcmd, cmd | CMD_ASE | CMD_PSE | CMD_RUN);
+
+    // Set default of high speed for root hub.
+    writel(&cntl->regs->configflag, 1);
+    cntl->checkports = readl(&cntl->caps->hcsparams) & HCS_N_PORTS_MASK;
+
+    // Find devices
+    int count = check_ehci_ports(cntl);
+    ehci_free_pipes(cntl);
+    if (count)
+        // Success
+        return;
+
+    // No devices found - shutdown and free controller.
+    writel(&cntl->regs->usbcmd, cmd & ~CMD_RUN);
+    msleep(4);  // 2ms to stop reading memory - XXX
+fail:
+    free(fl);
+    free(intr_qh);
+    free(async_qh);
+    free(cntl);
+}
+
+int
+ehci_setup(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);
+
+    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);
+    if (hcc_params & HCC_64BIT_ADDR)
+        cntl->regs->ctrldssegment = 0;
+
+    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 = container_of(comppci->node.next, struct pci_device, node);
+    }
+
+    run_thread(configure_ehci, cntl);
+    return 0;
+}
+
+
+/****************************************************************
+ * End point communication
+ ****************************************************************/
+
+// Setup fields in qh
+static void
+ehci_desc2pipe(struct ehci_pipe *pipe, struct usbdevice_s *usbdev
+               , struct usb_endpoint_descriptor *epdesc)
+{
+    usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
+
+    pipe->qh.info1 = ((pipe->pipe.maxpacket << QH_MAXPACKET_SHIFT)
+                      | (pipe->pipe.speed << QH_SPEED_SHIFT)
+                      | (pipe->pipe.ep << QH_EP_SHIFT)
+                      | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT));
+
+    pipe->qh.info2 = (1 << QH_MULT_SHIFT);
+    struct usbdevice_s *hubdev = usbdev->hub->usbdev;
+    if (hubdev) {
+        struct ehci_pipe *hpipe = container_of(
+            hubdev->defpipe, struct ehci_pipe, pipe);
+        if (hpipe->pipe.speed == USB_HIGHSPEED)
+            pipe->qh.info2 |= ((usbdev->port << QH_HUBPORT_SHIFT)
+                               | (hpipe->pipe.devaddr << QH_HUBADDR_SHIFT));
+        else
+            pipe->qh.info2 = hpipe->qh.info2;
+    }
+
+    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+    if (eptype == USB_ENDPOINT_XFER_CONTROL)
+        pipe->qh.info1 |= ((pipe->pipe.speed != USB_HIGHSPEED ? QH_CONTROL : 0)
+                           | QH_TOGGLECONTROL);
+    else if (eptype == USB_ENDPOINT_XFER_INT)
+        pipe->qh.info2 |= (0x01 << QH_SMASK_SHIFT) | (0x1c << QH_CMASK_SHIFT);
+}
+
+static struct usb_pipe *
+ehci_alloc_intr_pipe(struct usbdevice_s *usbdev
+                     , struct usb_endpoint_descriptor *epdesc)
+{
+    struct usb_ehci_s *cntl = container_of(
+        usbdev->hub->cntl, struct usb_ehci_s, usb);
+    int frameexp = usb_getFrameExp(usbdev, epdesc);
+    dprintf(7, "ehci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
+
+    if (frameexp > 10)
+        frameexp = 10;
+    int maxpacket = epdesc->wMaxPacketSize;
+    // Determine number of entries needed for 2 timer ticks.
+    int ms = 1<<frameexp;
+    int count = DIV_ROUND_UP(ticks_to_ms(2), ms);
+    struct ehci_pipe *pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe));
+    struct ehci_qtd *tds = memalign_low(EHCI_QTD_ALIGN, sizeof(*tds) * count);
+    void *data = malloc_low(maxpacket * count);
+    if (!pipe || !tds || !data) {
+        warn_noalloc();
+        goto fail;
+    }
+    memset(pipe, 0, sizeof(*pipe));
+    ehci_desc2pipe(pipe, usbdev, epdesc);
+    pipe->next_td = pipe->tds = tds;
+    pipe->data = data;
+    pipe->qh.qtd_next = (u32)tds;
+
+    int i;
+    for (i=0; i<count; i++) {
+        struct ehci_qtd *td = &tds[i];
+        td->qtd_next = (i==count-1 ? (u32)tds : (u32)&td[1]);
+        td->alt_next = EHCI_PTR_TERM;
+        td->token = (ehci_explen(maxpacket) | QTD_STS_ACTIVE
+                     | QTD_PID_IN | ehci_maxerr(3));
+        td->buf[0] = (u32)data + maxpacket * i;
+    }
+
+    // Add to interrupt schedule.
+    struct ehci_framelist *fl = (void*)readl(&cntl->regs->periodiclistbase);
+    if (frameexp == 0) {
+        // Add to existing interrupt entry.
+        struct ehci_qh *intr_qh = (void*)(fl->links[0] & ~EHCI_PTR_BITS);
+        pipe->qh.next = intr_qh->next;
+        barrier();
+        intr_qh->next = (u32)&pipe->qh | EHCI_PTR_QH;
+    } else {
+        int startpos = 1<<(frameexp-1);
+        pipe->qh.next = fl->links[startpos];
+        barrier();
+        for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms)
+            fl->links[i] = (u32)&pipe->qh | EHCI_PTR_QH;
+    }
+
+    return &pipe->pipe;
+fail:
+    free(pipe);
+    free(tds);
+    free(data);
+    return NULL;
+}
+
+struct usb_pipe *
+ehci_alloc_pipe(struct usbdevice_s *usbdev
+                , struct usb_endpoint_descriptor *epdesc)
+{
+    if (! CONFIG_USB_EHCI)
+        return NULL;
+    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+    if (eptype == USB_ENDPOINT_XFER_INT)
+        return ehci_alloc_intr_pipe(usbdev, epdesc);
+    struct usb_ehci_s *cntl = container_of(
+        usbdev->hub->cntl, struct usb_ehci_s, usb);
+    dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);
+
+    struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
+    if (usbpipe) {
+        // Use previously allocated pipe.
+        struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe);
+        ehci_desc2pipe(pipe, usbdev, epdesc);
+        return usbpipe;
+    }
+
+    // Allocate a new queue head.
+    struct ehci_pipe *pipe;
+    if (eptype == USB_ENDPOINT_XFER_CONTROL)
+        pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe));
+    else
+        pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe));
+    if (!pipe) {
+        warn_noalloc();
+        return NULL;
+    }
+    memset(pipe, 0, sizeof(*pipe));
+    ehci_desc2pipe(pipe, usbdev, epdesc);
+    pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;
+
+    // Add queue head to controller list.
+    struct ehci_qh *async_qh = cntl->async_qh;
+    pipe->qh.next = async_qh->next;
+    barrier();
+    async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH;
+    return &pipe->pipe;
+}
+
+static void
+ehci_reset_pipe(struct ehci_pipe *pipe)
+{
+    SET_LOWFLAT(pipe->qh.qtd_next, EHCI_PTR_TERM);
+    SET_LOWFLAT(pipe->qh.alt_next, EHCI_PTR_TERM);
+    barrier();
+    SET_LOWFLAT(pipe->qh.token, GET_LOWFLAT(pipe->qh.token) & QTD_TOGGLE);
+}
+
+static int
+ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout)
+{
+    u32 end = timer_calc(timeout);
+    u32 status;
+    for (;;) {
+        status = td->token;
+        if (!(status & QTD_STS_ACTIVE))
+            break;
+        if (timer_check(end)) {
+            u32 cur = GET_LOWFLAT(pipe->qh.current);
+            u32 tok = GET_LOWFLAT(pipe->qh.token);
+            u32 next = GET_LOWFLAT(pipe->qh.qtd_next);
+            warn_timeout();
+            dprintf(1, "ehci pipe=%p cur=%08x tok=%08x next=%x td=%p status=%x\n"
+                    , pipe, cur, tok, next, td, status);
+            ehci_reset_pipe(pipe);
+            struct usb_ehci_s *cntl = container_of(
+                GET_LOWFLAT(pipe->pipe.cntl), struct usb_ehci_s, usb);
+            ehci_waittick(cntl);
+            return -1;
+        }
+        yield();
+    }
+    if (status & QTD_STS_HALT) {
+        dprintf(1, "ehci_wait_td error - status=%x\n", status);
+        ehci_reset_pipe(pipe);
+        return -2;
+    }
+    return 0;
+}
+
+static int
+fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes)
+{
+    u32 dest = (u32)buf;
+    u32 *pos = td->buf;
+    while (bytes) {
+        if (pos >= &td->buf[ARRAY_SIZE(td->buf)])
+            // More data than can transfer in a single qtd - only use
+            // full packets to prevent a babble error.
+            return ALIGN_DOWN(dest - (u32)buf, maxpacket);
+        u32 count = bytes;
+        u32 max = 0x1000 - (dest & 0xfff);
+        if (count > max)
+            count = max;
+        *pos = dest;
+        bytes -= count;
+        dest += count;
+        pos++;
+    }
+    return dest - (u32)buf;
+}
+
+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;
+}
+
+#define STACKQTDS 4
+
+int
+ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
+{
+    if (! CONFIG_USB_EHCI)
+        return -1;
+    struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);
+    dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n"
+            , &pipe->qh, dir, data, datasize);
+
+    // Allocate 4 tds on stack (with required alignment)
+    u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1];
+    struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN);
+    memset(tds, 0, sizeof(*tds) * STACKQTDS);
+    barrier();
+    SET_LOWFLAT(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
+
+    u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
+    int tdpos = 0;
+    while (datasize) {
+        struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS];
+        int ret = ehci_wait_td(pipe, td, 5000);
+        if (ret)
+            return -1;
+
+        struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
+                                                 , &tds[tdpos % STACKQTDS]);
+
+        int transfer = fillTDbuffer(td, maxpacket, data, datasize);
+        td->qtd_next = (transfer==datasize ? EHCI_PTR_TERM : (u32)nexttd_fl);
+        td->alt_next = EHCI_PTR_TERM;
+        barrier();
+        td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE
+                     | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3));
+
+        data += transfer;
+        datasize -= transfer;
+    }
+    int i;
+    for (i=0; i<STACKQTDS; i++) {
+        struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS];
+        int ret = ehci_wait_td(pipe, td, 5000);
+        if (ret)
+            return -1;
+    }
+
+    return 0;
+}
+
+int
+ehci_poll_intr(struct usb_pipe *p, void *data)
+{
+    ASSERT16();
+    if (! CONFIG_USB_EHCI)
+        return -1;
+    struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);
+    struct ehci_qtd *td = GET_LOWFLAT(pipe->next_td);
+    u32 token = GET_LOWFLAT(td->token);
+    if (token & QTD_STS_ACTIVE)
+        // No intrs found.
+        return -1;
+    // XXX - check for errors.
+
+    // Copy data.
+    int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
+    int pos = td - GET_LOWFLAT(pipe->tds);
+    void *tddata = GET_LOWFLAT(pipe->data) + maxpacket * pos;
+    memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata), maxpacket);
+
+    // Reenable this td.
+    struct ehci_qtd *next = (void*)(GET_LOWFLAT(td->qtd_next) & ~EHCI_PTR_BITS);
+    SET_LOWFLAT(pipe->next_td, next);
+    SET_LOWFLAT(td->buf[0], (u32)tddata);
+    barrier();
+    SET_LOWFLAT(td->token, (ehci_explen(maxpacket) | QTD_STS_ACTIVE
+                            | QTD_PID_IN | ehci_maxerr(3)));
+
+    return 0;
+}
diff --git a/src/hw/usb-ehci.h b/src/hw/usb-ehci.h
new file mode 100644 (file)
index 0000000..5672033
--- /dev/null
@@ -0,0 +1,176 @@
+#ifndef __USB_EHCI_H
+#define __USB_EHCI_H
+
+// usb-ehci.c
+int ehci_setup(struct pci_device *pci, int busid, struct pci_device *comppci);
+struct usbdevice_s;
+struct usb_endpoint_descriptor;
+struct usb_pipe *ehci_alloc_pipe(struct usbdevice_s *usbdev
+                                 , struct usb_endpoint_descriptor *epdesc);
+struct usb_pipe;
+int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+                 , void *data, int datasize);
+int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
+int ehci_poll_intr(struct usb_pipe *p, void *data);
+
+
+/****************************************************************
+ * ehci structs and flags
+ ****************************************************************/
+
+struct ehci_caps {
+    u8 caplength;
+    u8 reserved_01;
+    u16 hciversion;
+    u32 hcsparams;
+    u32 hccparams;
+    u64 portroute;
+} PACKED;
+
+#define HCC_64BIT_ADDR 1
+
+#define HCS_N_PORTS_MASK 0xf
+
+struct ehci_regs {
+    u32 usbcmd;
+    u32 usbsts;
+    u32 usbintr;
+    u32 frindex;
+    u32 ctrldssegment;
+    u32 periodiclistbase;
+    u32 asynclistbase;
+    u32 reserved[9];
+    u32 configflag;
+    u32 portsc[0];
+} PACKED;
+
+#define CMD_PARK        (1<<11)
+#define CMD_PARK_CNT(c) (((c)>>8)&3)
+#define CMD_LRESET      (1<<7)
+#define CMD_IAAD        (1<<6)
+#define CMD_ASE         (1<<5)
+#define CMD_PSE         (1<<4)
+#define CMD_HCRESET     (1<<1)
+#define CMD_RUN         (1<<0)
+
+#define STS_ASS         (1<<15)
+#define STS_PSS         (1<<14)
+#define STS_RECL        (1<<13)
+#define STS_HALT        (1<<12)
+#define STS_IAA         (1<<5)
+#define STS_FATAL       (1<<4)
+#define STS_FLR         (1<<3)
+#define STS_PCD         (1<<2)
+#define STS_ERR         (1<<1)
+#define STS_INT         (1<<0)
+
+#define FLAG_CF         (1<<0)
+
+#define PORT_WKOC_E     (1<<22)
+#define PORT_WKDISC_E   (1<<21)
+#define PORT_WKCONN_E   (1<<20)
+#define PORT_TEST_PKT   (0x4<<16)
+#define PORT_LED_OFF    (0<<14)
+#define PORT_LED_AMBER  (1<<14)
+#define PORT_LED_GREEN  (2<<14)
+#define PORT_LED_MASK   (3<<14)
+#define PORT_OWNER      (1<<13)
+#define PORT_POWER      (1<<12)
+#define PORT_LINESTATUS_MASK   (3<<10)
+#define PORT_LINESTATUS_KSTATE (1<<10)
+#define PORT_RESET      (1<<8)
+#define PORT_SUSPEND    (1<<7)
+#define PORT_RESUME     (1<<6)
+#define PORT_OCC        (1<<5)
+#define PORT_OC         (1<<4)
+#define PORT_PEC        (1<<3)
+#define PORT_PE         (1<<2)
+#define PORT_CSC        (1<<1)
+#define PORT_CONNECT    (1<<0)
+#define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
+
+
+#define EHCI_QH_ALIGN 128 // Can't span a 4K boundary, so increase from 32
+
+struct ehci_qh {
+    u32 next;
+    u32 info1;
+    u32 info2;
+    u32 current;
+
+    u32 qtd_next;
+    u32 alt_next;
+    u32 token;
+    u32 buf[5];
+    u32 buf_hi[5];
+} PACKED;
+
+#define QH_CONTROL       (1 << 27)
+#define QH_MAXPACKET_SHIFT 16
+#define QH_MAXPACKET_MASK  (0x7ff << QH_MAXPACKET_SHIFT)
+#define QH_HEAD          (1 << 15)
+#define QH_TOGGLECONTROL (1 << 14)
+#define QH_SPEED_SHIFT   12
+#define QH_SPEED_MASK    (0x3 << QH_SPEED_SHIFT)
+#define QH_EP_SHIFT      8
+#define QH_EP_MASK       (0xf << QH_EP_SHIFT)
+#define QH_DEVADDR_SHIFT 0
+#define QH_DEVADDR_MASK  (0x7f << QH_DEVADDR_SHIFT)
+
+#define QH_SMASK_SHIFT   0
+#define QH_SMASK_MASK    (0xff << QH_SMASK_SHIFT)
+#define QH_CMASK_SHIFT   8
+#define QH_CMASK_MASK    (0xff << QH_CMASK_SHIFT)
+#define QH_HUBADDR_SHIFT 16
+#define QH_HUBADDR_MASK  (0x7f << QH_HUBADDR_SHIFT)
+#define QH_HUBPORT_SHIFT 23
+#define QH_HUBPORT_MASK  (0x7f << QH_HUBPORT_SHIFT)
+#define QH_MULT_SHIFT    30
+#define QH_MULT_MASK     (0x3 << QH_MULT_SHIFT)
+
+#define EHCI_PTR_BITS           0x001F
+#define EHCI_PTR_TERM           0x0001
+#define EHCI_PTR_QH             0x0002
+
+
+#define EHCI_QTD_ALIGN 64 // Can't span a 4K boundary, so increase from 32
+
+struct ehci_qtd {
+    u32 qtd_next;
+    u32 alt_next;
+    u32 token;
+    u32 buf[5];
+    u32 buf_hi[5];
+    /* keep struct size a multiple of 64 bytes, as we're allocating
+       arrays. Without this padding, the second qtd could have the
+       wrong alignment. */
+} PACKED __aligned(EHCI_QTD_ALIGN);
+
+#define QTD_TOGGLE      (1 << 31)
+#define QTD_LENGTH_SHIFT 16
+#define QTD_LENGTH_MASK (0x7fff << QTD_LENGTH_SHIFT)
+#define QTD_CERR_SHIFT  10
+#define QTD_CERR_MASK   (0x3 << QTD_CERR_SHIFT)
+#define QTD_IOC         (1 << 15)
+#define QTD_PID_OUT     (0x0 << 8)
+#define QTD_PID_IN      (0x1 << 8)
+#define QTD_PID_SETUP   (0x2 << 8)
+#define QTD_STS_ACTIVE  (1 << 7)
+#define QTD_STS_HALT    (1 << 6)
+#define QTD_STS_DBE     (1 << 5)
+#define QTD_STS_BABBLE  (1 << 4)
+#define QTD_STS_XACT    (1 << 3)
+#define QTD_STS_MMF     (1 << 2)
+#define QTD_STS_STS     (1 << 1)
+#define QTD_STS_PING    (1 << 0)
+
+#define ehci_explen(len) (((len) << QTD_LENGTH_SHIFT) & QTD_LENGTH_MASK)
+
+#define ehci_maxerr(err) (((err) << QTD_CERR_SHIFT) & QTD_CERR_MASK)
+
+
+struct ehci_framelist {
+    u32 links[1024];
+} PACKED;
+
+#endif // usb-ehci.h
diff --git a/src/hw/usb-hid.c b/src/hw/usb-hid.c
new file mode 100644 (file)
index 0000000..deb3ea5
--- /dev/null
@@ -0,0 +1,431 @@
+// Code for handling USB Human Interface Devices (HID).
+//
+// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "usb-hid.h" // usb_keyboard_setup
+#include "config.h" // CONFIG_*
+#include "usb.h" // usb_ctrlrequest
+#include "biosvar.h" // GET_GLOBAL
+#include "ps2port.h" // ATKBD_CMD_GETID
+
+struct usb_pipe *keyboard_pipe VARFSEG;
+struct usb_pipe *mouse_pipe VARFSEG;
+
+
+/****************************************************************
+ * Setup
+ ****************************************************************/
+
+// Send USB HID protocol message.
+static int
+set_protocol(struct usb_pipe *pipe, u16 val)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+    req.bRequest = HID_REQ_SET_PROTOCOL;
+    req.wValue = val;
+    req.wIndex = 0;
+    req.wLength = 0;
+    return send_default_control(pipe, &req, NULL);
+}
+
+// Send USB HID SetIdle request.
+static int
+set_idle(struct usb_pipe *pipe, int ms)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+    req.bRequest = HID_REQ_SET_IDLE;
+    req.wValue = (ms/4)<<8;
+    req.wIndex = 0;
+    req.wLength = 0;
+    return send_default_control(pipe, &req, NULL);
+}
+
+#define KEYREPEATWAITMS 500
+#define KEYREPEATMS 33
+
+static int
+usb_kbd_setup(struct usbdevice_s *usbdev
+              , struct usb_endpoint_descriptor *epdesc)
+{
+    if (! CONFIG_USB_KEYBOARD)
+        return -1;
+    if (keyboard_pipe)
+        // XXX - this enables the first found keyboard (could be random)
+        return -1;
+
+    if (epdesc->wMaxPacketSize != 8)
+        return -1;
+
+    // Enable "boot" protocol.
+    int ret = set_protocol(usbdev->defpipe, 0);
+    if (ret)
+        return -1;
+    // Periodically send reports to enable key repeat.
+    ret = set_idle(usbdev->defpipe, KEYREPEATMS);
+    if (ret)
+        return -1;
+
+    keyboard_pipe = usb_alloc_pipe(usbdev, epdesc);
+    if (!keyboard_pipe)
+        return -1;
+
+    dprintf(1, "USB keyboard initialized\n");
+    return 0;
+}
+
+static int
+usb_mouse_setup(struct usbdevice_s *usbdev
+                , struct usb_endpoint_descriptor *epdesc)
+{
+    if (! CONFIG_USB_MOUSE)
+        return -1;
+    if (mouse_pipe)
+        // XXX - this enables the first found mouse (could be random)
+        return -1;
+
+    if (epdesc->wMaxPacketSize < 3 || epdesc->wMaxPacketSize > 8)
+        return -1;
+
+    // Enable "boot" protocol.
+    int ret = set_protocol(usbdev->defpipe, 0);
+    if (ret)
+        return -1;
+
+    mouse_pipe = usb_alloc_pipe(usbdev, epdesc);
+    if (!mouse_pipe)
+        return -1;
+
+    dprintf(1, "USB mouse initialized\n");
+    return 0;
+}
+
+// Initialize a found USB HID device (if applicable).
+int
+usb_hid_setup(struct usbdevice_s *usbdev)
+{
+    if (! CONFIG_USB_KEYBOARD || ! CONFIG_USB_MOUSE)
+        return -1;
+    dprintf(2, "usb_hid_setup %p\n", usbdev->defpipe);
+
+    struct usb_interface_descriptor *iface = usbdev->iface;
+    if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT)
+        // Doesn't support boot protocol.
+        return -1;
+
+    // Find intr in endpoint.
+    struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
+        usbdev, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
+    if (!epdesc) {
+        dprintf(1, "No usb hid intr in?\n");
+        return -1;
+    }
+
+    if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD)
+        return usb_kbd_setup(usbdev, epdesc);
+    if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
+        return usb_mouse_setup(usbdev, epdesc);
+    return -1;
+}
+
+
+/****************************************************************
+ * Keyboard events
+ ****************************************************************/
+
+// Mapping from USB key id to ps2 key sequence.
+static u16 KeyToScanCode[] VAR16 = {
+    0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
+    0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
+    0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
+    0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
+    0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
+    0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
+    0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
+    0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+    0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
+    0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
+    0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
+    0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
+    0x0048, 0x0049, 0x0052, 0x0053
+};
+
+// Mapping from USB modifier id to ps2 key sequence.
+static u16 ModifierToScanCode[] VAR16 = {
+    //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
+    0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
+};
+
+#define RELEASEBIT 0x80
+
+// Format of USB keyboard event data
+struct keyevent {
+    u8 modifiers;
+    u8 reserved;
+    u8 keys[6];
+};
+
+// Translate data from KeyToScanCode[] to calls to process_key().
+static void
+prockeys(u16 keys)
+{
+    if (keys > 0xff) {
+        u8 key = keys>>8;
+        if (key == 0xe1) {
+            // Pause key
+            process_key(0xe1);
+            process_key(0x1d | (keys & RELEASEBIT));
+            process_key(0x45 | (keys & RELEASEBIT));
+            return;
+        }
+        process_key(key);
+    }
+    process_key(keys);
+}
+
+// Handle a USB key press/release event.
+static void
+procscankey(u8 key, u8 flags)
+{
+    if (key >= ARRAY_SIZE(KeyToScanCode))
+        return;
+    u16 keys = GET_GLOBAL(KeyToScanCode[key]);
+    if (keys)
+        prockeys(keys | flags);
+}
+
+// Handle a USB modifier press/release event.
+static void
+procmodkey(u8 mods, u8 flags)
+{
+    int i;
+    for (i=0; mods; i++)
+        if (mods & (1<<i)) {
+            // Modifier key change.
+            prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
+            mods &= ~(1<<i);
+        }
+}
+
+struct usbkeyinfo {
+    union {
+        struct {
+            u8 modifiers;
+            u8 repeatcount;
+            u8 keys[6];
+        };
+        u64 data;
+    };
+};
+struct usbkeyinfo LastUSBkey VARLOW;
+
+// Process USB keyboard data.
+static void
+handle_key(struct keyevent *data)
+{
+    dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
+
+    // Load old keys.
+    struct usbkeyinfo old;
+    old.data = GET_LOW(LastUSBkey.data);
+
+    // Check for keys no longer pressed.
+    int addpos = 0;
+    int i;
+    for (i=0; i<ARRAY_SIZE(old.keys); i++) {
+        u8 key = old.keys[i];
+        if (!key)
+            break;
+        int j;
+        for (j=0;; j++) {
+            if (j>=ARRAY_SIZE(data->keys)) {
+                // Key released.
+                procscankey(key, RELEASEBIT);
+                if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
+                    // Last pressed key released - disable repeat.
+                    old.repeatcount = 0xff;
+                break;
+            }
+            if (data->keys[j] == key) {
+                // Key still pressed.
+                data->keys[j] = 0;
+                old.keys[addpos++] = key;
+                break;
+            }
+        }
+    }
+    procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
+
+    // Process new keys
+    procmodkey(data->modifiers & ~old.modifiers, 0);
+    old.modifiers = data->modifiers;
+    for (i=0; i<ARRAY_SIZE(data->keys); i++) {
+        u8 key = data->keys[i];
+        if (!key)
+            continue;
+        // New key pressed.
+        procscankey(key, 0);
+        old.keys[addpos++] = key;
+        old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
+    }
+    if (addpos < ARRAY_SIZE(old.keys))
+        old.keys[addpos] = 0;
+
+    // Check for key repeat event.
+    if (addpos) {
+        if (!old.repeatcount)
+            procscankey(old.keys[addpos-1], 0);
+        else if (old.repeatcount != 0xff)
+            old.repeatcount--;
+    }
+
+    // Update old keys
+    SET_LOW(LastUSBkey.data, old.data);
+}
+
+// Check if a USB keyboard event is pending and process it if so.
+static void
+usb_check_key(void)
+{
+    if (! CONFIG_USB_KEYBOARD)
+        return;
+    struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
+    if (!pipe)
+        return;
+
+    for (;;) {
+        struct keyevent data;
+        int ret = usb_poll_intr(pipe, &data);
+        if (ret)
+            break;
+        handle_key(&data);
+    }
+}
+
+// Test if USB keyboard is active.
+inline int
+usb_kbd_active(void)
+{
+    if (! CONFIG_USB_KEYBOARD)
+        return 0;
+    return GET_GLOBAL(keyboard_pipe) != NULL;
+}
+
+// Handle a ps2 style keyboard command.
+inline int
+usb_kbd_command(int command, u8 *param)
+{
+    if (! CONFIG_USB_KEYBOARD)
+        return -1;
+    dprintf(9, "usb keyboard cmd=%x\n", command);
+    switch (command) {
+    case ATKBD_CMD_GETID:
+        // Return the id of a standard AT keyboard.
+        param[0] = 0xab;
+        param[1] = 0x83;
+        return 0;
+    default:
+        return -1;
+    }
+}
+
+
+/****************************************************************
+ * Mouse events
+ ****************************************************************/
+
+// Format of USB mouse event data
+struct mouseevent {
+    u8 buttons;
+    u8 x, y;
+    u8 reserved[5];
+};
+
+// Process USB mouse data.
+static void
+handle_mouse(struct mouseevent *data)
+{
+    dprintf(9, "Got mouse b=%x x=%x y=%x\n", data->buttons, data->x, data->y);
+
+    s8 x = data->x, y = -data->y;
+    u8 flag = ((data->buttons & 0x7) | (1<<3)
+               | (x & 0x80 ? (1<<4) : 0) | (y & 0x80 ? (1<<5) : 0));
+    process_mouse(flag);
+    process_mouse(x);
+    process_mouse(y);
+}
+
+// Check if a USB mouse event is pending and process it if so.
+static void
+usb_check_mouse(void)
+{
+    if (! CONFIG_USB_MOUSE)
+        return;
+    struct usb_pipe *pipe = GET_GLOBAL(mouse_pipe);
+    if (!pipe)
+        return;
+
+    for (;;) {
+        struct mouseevent data;
+        int ret = usb_poll_intr(pipe, &data);
+        if (ret)
+            break;
+        handle_mouse(&data);
+    }
+}
+
+// Test if USB mouse is active.
+inline int
+usb_mouse_active(void)
+{
+    if (! CONFIG_USB_MOUSE)
+        return 0;
+    return GET_GLOBAL(mouse_pipe) != NULL;
+}
+
+// Handle a ps2 style mouse command.
+inline int
+usb_mouse_command(int command, u8 *param)
+{
+    if (! CONFIG_USB_MOUSE)
+        return -1;
+    dprintf(9, "usb mouse cmd=%x\n", command);
+    switch (command) {
+    case PSMOUSE_CMD_ENABLE:
+    case PSMOUSE_CMD_DISABLE:
+    case PSMOUSE_CMD_SETSCALE11:
+        return 0;
+    case PSMOUSE_CMD_SETSCALE21:
+    case PSMOUSE_CMD_SETRATE:
+    case PSMOUSE_CMD_SETRES:
+        // XXX
+        return 0;
+    case PSMOUSE_CMD_RESET_BAT:
+    case PSMOUSE_CMD_GETID:
+        // Return the id of a standard AT mouse.
+        param[0] = 0xaa;
+        param[1] = 0x00;
+        return 0;
+
+    case PSMOUSE_CMD_GETINFO:
+        param[0] = 0x00;
+        param[1] = 4;
+        param[2] = 100;
+        return 0;
+
+    default:
+        return -1;
+    }
+}
+
+// Check for USB events pending - called periodically from timer interrupt.
+void
+usb_check_event(void)
+{
+    usb_check_key();
+    usb_check_mouse();
+}
diff --git a/src/hw/usb-hid.h b/src/hw/usb-hid.h
new file mode 100644 (file)
index 0000000..ef34e79
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __USB_HID_H
+#define __USB_HID_H
+
+// usb-hid.c
+struct usbdevice_s;
+int usb_hid_setup(struct usbdevice_s *usbdev);
+inline int usb_kbd_active(void);
+inline int usb_kbd_command(int command, u8 *param);
+inline int usb_mouse_active(void);
+inline int usb_mouse_command(int command, u8 *param);
+void usb_check_event(void);
+
+
+/****************************************************************
+ * hid flags
+ ****************************************************************/
+
+#define USB_INTERFACE_SUBCLASS_BOOT     1
+#define USB_INTERFACE_PROTOCOL_KEYBOARD 1
+#define USB_INTERFACE_PROTOCOL_MOUSE    2
+
+#define HID_REQ_GET_REPORT              0x01
+#define HID_REQ_GET_IDLE                0x02
+#define HID_REQ_GET_PROTOCOL            0x03
+#define HID_REQ_SET_REPORT              0x09
+#define HID_REQ_SET_IDLE                0x0A
+#define HID_REQ_SET_PROTOCOL            0x0B
+
+#endif // ush-hid.h
diff --git a/src/hw/usb-hub.c b/src/hw/usb-hub.c
new file mode 100644 (file)
index 0000000..0b55d15
--- /dev/null
@@ -0,0 +1,185 @@
+// Code for handling standard USB hubs.
+//
+// Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_USB_HUB
+#include "usb-hub.h" // struct usb_hub_descriptor
+#include "usb.h" // struct usb_s
+
+static int
+get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE;
+    req.bRequest = USB_REQ_GET_DESCRIPTOR;
+    req.wValue = USB_DT_HUB<<8;
+    req.wIndex = 0;
+    req.wLength = sizeof(*desc);
+    return send_default_control(pipe, &req, desc);
+}
+
+static int
+set_port_feature(struct usbhub_s *hub, int port, int feature)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
+    req.bRequest = USB_REQ_SET_FEATURE;
+    req.wValue = feature;
+    req.wIndex = port + 1;
+    req.wLength = 0;
+    mutex_lock(&hub->lock);
+    int ret = send_default_control(hub->usbdev->defpipe, &req, NULL);
+    mutex_unlock(&hub->lock);
+    return ret;
+}
+
+static int
+clear_port_feature(struct usbhub_s *hub, int port, int feature)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
+    req.bRequest = USB_REQ_CLEAR_FEATURE;
+    req.wValue = feature;
+    req.wIndex = port + 1;
+    req.wLength = 0;
+    mutex_lock(&hub->lock);
+    int ret = send_default_control(hub->usbdev->defpipe, &req, NULL);
+    mutex_unlock(&hub->lock);
+    return ret;
+}
+
+static int
+get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER;
+    req.bRequest = USB_REQ_GET_STATUS;
+    req.wValue = 0;
+    req.wIndex = port + 1;
+    req.wLength = sizeof(*sts);
+    mutex_lock(&hub->lock);
+    int ret = send_default_control(hub->usbdev->defpipe, &req, sts);
+    mutex_unlock(&hub->lock);
+    return ret;
+}
+
+// Check if device attached to port
+static int
+usb_hub_detect(struct usbhub_s *hub, u32 port)
+{
+    // Turn on power to port.
+    int ret = set_port_feature(hub, port, USB_PORT_FEAT_POWER);
+    if (ret)
+        goto fail;
+
+    // Wait for port power to stabilize.
+    msleep(hub->powerwait);
+
+    // Check periodically for a device connect.
+    struct usb_port_status sts;
+    u32 end = timer_calc(USB_TIME_SIGATT);
+    for (;;) {
+        ret = get_port_status(hub, port, &sts);
+        if (ret)
+            goto fail;
+        if (sts.wPortStatus & USB_PORT_STAT_CONNECTION)
+            // Device connected.
+            break;
+        if (timer_check(end))
+            // No device found.
+            return -1;
+        msleep(5);
+    }
+
+    // XXX - wait USB_TIME_ATTDB time?
+
+    return 0;
+
+fail:
+    dprintf(1, "Failure on hub port %d detect\n", port);
+    return -1;
+}
+
+// Disable port
+static void
+usb_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+    int ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
+    if (ret)
+        dprintf(1, "Failure on hub port %d disconnect\n", port);
+}
+
+// Reset device on port
+static int
+usb_hub_reset(struct usbhub_s *hub, u32 port)
+{
+    int ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET);
+    if (ret)
+        goto fail;
+
+    // Wait for reset to complete.
+    struct usb_port_status sts;
+    u32 end = timer_calc(USB_TIME_DRST * 2);
+    for (;;) {
+        ret = get_port_status(hub, port, &sts);
+        if (ret)
+            goto fail;
+        if (!(sts.wPortStatus & USB_PORT_STAT_RESET))
+            break;
+        if (timer_check(end)) {
+            warn_timeout();
+            goto fail;
+        }
+        msleep(5);
+    }
+
+    // Reset complete.
+    if (!(sts.wPortStatus & USB_PORT_STAT_CONNECTION))
+        // Device no longer present
+        return -1;
+
+    return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK)
+            >> USB_PORT_STAT_SPEED_SHIFT);
+
+fail:
+    dprintf(1, "Failure on hub port %d reset\n", port);
+    usb_hub_disconnect(hub, port);
+    return -1;
+}
+
+static struct usbhub_op_s HubOp = {
+    .detect = usb_hub_detect,
+    .reset = usb_hub_reset,
+    .disconnect = usb_hub_disconnect,
+};
+
+// 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;
+}
diff --git a/src/hw/usb-hub.h b/src/hw/usb-hub.h
new file mode 100644 (file)
index 0000000..5b09947
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __USB_HUB_H
+#define __USB_HUB_H
+
+// usb-hub.c
+struct usbdevice_s;
+int usb_hub_setup(struct usbdevice_s *usbdev);
+
+
+/****************************************************************
+ * hub flags
+ ****************************************************************/
+
+#define USB_DT_HUB                      (USB_TYPE_CLASS | 0x09)
+
+struct usb_hub_descriptor {
+    u8  bDescLength;
+    u8  bDescriptorType;
+    u8  bNbrPorts;
+    u16 wHubCharacteristics;
+    u8  bPwrOn2PwrGood;
+    u8  bHubContrCurrent;
+    // Variable length fields for DeviceRemovable[], PortPwrCtrlMask[] follow.
+} PACKED;
+
+#define USB_PORT_FEAT_CONNECTION        0
+#define USB_PORT_FEAT_ENABLE            1
+#define USB_PORT_FEAT_SUSPEND           2
+#define USB_PORT_FEAT_OVER_CURRENT      3
+#define USB_PORT_FEAT_RESET             4
+#define USB_PORT_FEAT_POWER             8
+#define USB_PORT_FEAT_LOWSPEED          9
+#define USB_PORT_FEAT_C_CONNECTION      16
+#define USB_PORT_FEAT_C_ENABLE          17
+#define USB_PORT_FEAT_C_SUSPEND         18
+#define USB_PORT_FEAT_C_OVER_CURRENT    19
+#define USB_PORT_FEAT_C_RESET           20
+#define USB_PORT_FEAT_TEST              21
+#define USB_PORT_FEAT_INDICATOR         22
+#define USB_PORT_FEAT_C_PORT_L1         23
+
+struct usb_port_status {
+    u16 wPortStatus;
+    u16 wPortChange;
+} PACKED;
+
+#define USB_PORT_STAT_CONNECTION        0x0001
+#define USB_PORT_STAT_ENABLE            0x0002
+#define USB_PORT_STAT_SUSPEND           0x0004
+#define USB_PORT_STAT_OVERCURRENT       0x0008
+#define USB_PORT_STAT_RESET             0x0010
+#define USB_PORT_STAT_L1                0x0020
+#define USB_PORT_STAT_POWER             0x0100
+#define USB_PORT_STAT_SPEED_SHIFT       9
+#define USB_PORT_STAT_SPEED_MASK        (0x3 << USB_PORT_STAT_SPEED_SHIFT)
+#define USB_PORT_STAT_LOW_SPEED         0x0200
+#define USB_PORT_STAT_HIGH_SPEED        0x0400
+#define USB_PORT_STAT_TEST              0x0800
+#define USB_PORT_STAT_INDICATOR         0x1000
+
+#endif // ush-hid.h
diff --git a/src/hw/usb-msc.c b/src/hw/usb-msc.c
new file mode 100644 (file)
index 0000000..7b2524d
--- /dev/null
@@ -0,0 +1,215 @@
+// Code for handling USB Mass Storage Controller devices.
+//
+// Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_USB_MSC
+#include "usb-msc.h" // usb_msc_setup
+#include "usb.h" // struct usb_s
+#include "biosvar.h" // GET_GLOBAL
+#include "blockcmd.h" // cdb_read
+#include "disk.h" // DTYPE_USB
+#include "boot.h" // bootprio_find_usb
+
+struct usbdrive_s {
+    struct drive_s drive;
+    struct usb_pipe *bulkin, *bulkout;
+    int lun;
+};
+
+
+/****************************************************************
+ * Bulk-only drive command processing
+ ****************************************************************/
+
+#define USB_CDB_SIZE 12
+
+#define CBW_SIGNATURE 0x43425355 // USBC
+
+struct cbw_s {
+    u32 dCBWSignature;
+    u32 dCBWTag;
+    u32 dCBWDataTransferLength;
+    u8 bmCBWFlags;
+    u8 bCBWLUN;
+    u8 bCBWCBLength;
+    u8 CBWCB[16];
+} PACKED;
+
+#define CSW_SIGNATURE 0x53425355 // USBS
+
+struct csw_s {
+    u32 dCSWSignature;
+    u32 dCSWTag;
+    u32 dCSWDataResidue;
+    u8 bCSWStatus;
+} PACKED;
+
+static int
+usb_msc_send(struct usbdrive_s *udrive_g, int dir, void *buf, u32 bytes)
+{
+    struct usb_pipe *pipe;
+    if (dir == USB_DIR_OUT)
+        pipe = GET_GLOBAL(udrive_g->bulkout);
+    else
+        pipe = GET_GLOBAL(udrive_g->bulkin);
+    return usb_send_bulk(pipe, dir, buf, bytes);
+}
+
+// Low-level usb command transmit function.
+int
+usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    if (!CONFIG_USB_MSC)
+        return 0;
+
+    dprintf(16, "usb_cmd_data id=%p write=%d count=%d bs=%d buf=%p\n"
+            , op->drive_g, 0, op->count, blocksize, op->buf_fl);
+    struct usbdrive_s *udrive_g = container_of(
+        op->drive_g, struct usbdrive_s, drive);
+
+    // Setup command block wrapper.
+    u32 bytes = blocksize * op->count;
+    struct cbw_s cbw;
+    memset(&cbw, 0, sizeof(cbw));
+    memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE);
+    cbw.dCBWSignature = CBW_SIGNATURE;
+    cbw.dCBWTag = 999; // XXX
+    cbw.dCBWDataTransferLength = bytes;
+    cbw.bmCBWFlags = cdb_is_read(cdbcmd, blocksize) ? USB_DIR_IN : USB_DIR_OUT;
+    cbw.bCBWLUN = GET_GLOBAL(udrive_g->lun);
+    cbw.bCBWCBLength = USB_CDB_SIZE;
+
+    // Transfer cbw to device.
+    int ret = usb_msc_send(udrive_g, USB_DIR_OUT
+                           , MAKE_FLATPTR(GET_SEG(SS), &cbw), sizeof(cbw));
+    if (ret)
+        goto fail;
+
+    // Transfer data to/from device.
+    if (bytes) {
+        ret = usb_msc_send(udrive_g, cbw.bmCBWFlags, op->buf_fl, bytes);
+        if (ret)
+            goto fail;
+    }
+
+    // Transfer csw info.
+    struct csw_s csw;
+    ret = usb_msc_send(udrive_g, USB_DIR_IN
+                        , MAKE_FLATPTR(GET_SEG(SS), &csw), sizeof(csw));
+    if (ret)
+        goto fail;
+
+    if (!csw.bCSWStatus)
+        return DISK_RET_SUCCESS;
+    if (csw.bCSWStatus == 2)
+        goto fail;
+
+    if (blocksize)
+        op->count -= csw.dCSWDataResidue / blocksize;
+    return DISK_RET_EBADTRACK;
+
+fail:
+    // XXX - reset connection
+    dprintf(1, "USB transmission failed\n");
+    op->count = 0;
+    return DISK_RET_EBADTRACK;
+}
+
+static int
+usb_msc_maxlun(struct usb_pipe *pipe)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+    req.bRequest = 0xfe;
+    req.wValue = 0;
+    req.wIndex = 0;
+    req.wLength = 1;
+    unsigned char maxlun;
+    int ret = send_default_control(pipe, &req, &maxlun);
+    if (ret)
+        return 0;
+    return maxlun;
+}
+
+static int
+usb_msc_lun_setup(struct usb_pipe *inpipe, struct usb_pipe *outpipe,
+                  struct usbdevice_s *usbdev, int lun)
+{
+    // Allocate drive structure.
+    struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g));
+    if (!udrive_g) {
+        warn_noalloc();
+        return -1;
+    }
+    memset(udrive_g, 0, sizeof(*udrive_g));
+    udrive_g->drive.type = DTYPE_USB;
+    udrive_g->bulkin = inpipe;
+    udrive_g->bulkout = outpipe;
+    udrive_g->lun = lun;
+
+    int prio = bootprio_find_usb(usbdev, lun);
+    int ret = scsi_drive_setup(&udrive_g->drive, "USB MSC", prio);
+    if (ret) {
+        dprintf(1, "Unable to configure USB MSC drive.\n");
+        free(udrive_g);
+        return -1;
+    }
+    return 0;
+}
+
+/****************************************************************
+ * Setup
+ ****************************************************************/
+
+// Configure a usb msc device.
+int
+usb_msc_setup(struct usbdevice_s *usbdev)
+{
+    if (!CONFIG_USB_MSC)
+        return -1;
+
+    // Verify right kind of device
+    struct usb_interface_descriptor *iface = usbdev->iface;
+    if ((iface->bInterfaceSubClass != US_SC_SCSI &&
+         iface->bInterfaceSubClass != US_SC_ATAPI_8070 &&
+         iface->bInterfaceSubClass != US_SC_ATAPI_8020)
+        || iface->bInterfaceProtocol != US_PR_BULK) {
+        dprintf(1, "Unsupported MSC USB device (subclass=%02x proto=%02x)\n"
+                , iface->bInterfaceSubClass, iface->bInterfaceProtocol);
+        return -1;
+    }
+
+    // Find bulk in and bulk out endpoints.
+    struct usb_pipe *inpipe = NULL, *outpipe = NULL;
+    struct usb_endpoint_descriptor *indesc = findEndPointDesc(
+        usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
+    struct usb_endpoint_descriptor *outdesc = findEndPointDesc(
+        usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
+    if (!indesc || !outdesc)
+        goto fail;
+    inpipe = usb_alloc_pipe(usbdev, indesc);
+    outpipe = usb_alloc_pipe(usbdev, outdesc);
+    if (!inpipe || !outpipe)
+        goto fail;
+
+    int maxlun = usb_msc_maxlun(usbdev->defpipe);
+    int lun, pipesused = 0;
+    for (lun = 0; lun < maxlun + 1; lun++) {
+        int ret = usb_msc_lun_setup(inpipe, outpipe, usbdev, lun);
+        if (!ret)
+            pipesused = 1;
+    }
+
+    if (!pipesused)
+        goto fail;
+
+    return 0;
+fail:
+    dprintf(1, "Unable to configure USB MSC device.\n");
+    free_pipe(inpipe);
+    free_pipe(outpipe);
+    return -1;
+}
diff --git a/src/hw/usb-msc.h b/src/hw/usb-msc.h
new file mode 100644 (file)
index 0000000..c40d755
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __USB_MSC_H
+#define __USB_MSC_H
+
+// usb-msc.c
+struct disk_op_s;
+int usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+struct usbdevice_s;
+int usb_msc_setup(struct usbdevice_s *usbdev);
+
+#endif // ush-msc.h
diff --git a/src/hw/usb-ohci.c b/src/hw/usb-ohci.c
new file mode 100644 (file)
index 0000000..e5c9fa5
--- /dev/null
@@ -0,0 +1,534 @@
+// Code for handling OHCI USB controllers.
+//
+// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // pci_bdf_to_bus
+#include "config.h" // CONFIG_*
+#include "usb-ohci.h" // struct ohci_hcca
+#include "pci_regs.h" // PCI_BASE_ADDRESS_0
+#include "usb.h" // struct usb_s
+#include "biosvar.h" // GET_LOWFLAT
+
+#define FIT                     (1 << 31)
+
+struct usb_ohci_s {
+    struct usb_s usb;
+    struct ohci_regs *regs;
+};
+
+struct ohci_pipe {
+    struct ohci_ed ed;
+    struct usb_pipe pipe;
+    void *data;
+    int count;
+    struct ohci_td *tds;
+};
+
+
+/****************************************************************
+ * Root hub
+ ****************************************************************/
+
+// Check if device attached to port
+static int
+ohci_hub_detect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
+    u32 sts = readl(&cntl->regs->roothub_portstatus[port]);
+    if (!(sts & RH_PS_CCS))
+        // No device.
+        return -1;
+
+    // XXX - need to wait for USB_TIME_ATTDB if just powered up?
+
+    return 0;
+}
+
+// Disable port
+static void
+ohci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
+    writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
+}
+
+// Reset device on port
+static int
+ohci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
+    writel(&cntl->regs->roothub_portstatus[port], RH_PS_PRS);
+    u32 sts;
+    u32 end = timer_calc(USB_TIME_DRSTR * 2);
+    for (;;) {
+        sts = readl(&cntl->regs->roothub_portstatus[port]);
+        if (!(sts & RH_PS_PRS))
+            // XXX - need to ensure USB_TIME_DRSTR time in reset?
+            break;
+        if (timer_check(end)) {
+            // Timeout.
+            warn_timeout();
+            ohci_hub_disconnect(hub, port);
+            return -1;
+        }
+        yield();
+    }
+
+    if ((sts & (RH_PS_CCS|RH_PS_PES)) != (RH_PS_CCS|RH_PS_PES))
+        // Device no longer present
+        return -1;
+
+    return !!(sts & RH_PS_LSDA);
+}
+
+static struct usbhub_op_s ohci_HubOp = {
+    .detect = ohci_hub_detect,
+    .reset = ohci_hub_reset,
+    .disconnect = ohci_hub_disconnect,
+};
+
+// Find any devices connected to the root hub.
+static int
+check_ohci_ports(struct usb_ohci_s *cntl)
+{
+    ASSERT32FLAT();
+    // Turn on power for all devices on roothub.
+    u32 rha = readl(&cntl->regs->roothub_a);
+    rha &= ~(RH_A_PSM | RH_A_OCPM);
+    writel(&cntl->regs->roothub_status, RH_HS_LPSC);
+    writel(&cntl->regs->roothub_b, RH_B_PPCM);
+    msleep((rha >> 24) * 2);
+    // XXX - need to sleep for USB_TIME_SIGATT if just powered up?
+
+    struct usbhub_s hub;
+    memset(&hub, 0, sizeof(hub));
+    hub.cntl = &cntl->usb;
+    hub.portcount = rha & RH_A_NDP;
+    hub.op = &ohci_HubOp;
+    usb_enumerate(&hub);
+    return hub.devcount;
+}
+
+
+/****************************************************************
+ * Setup
+ ****************************************************************/
+
+// Wait for next USB frame to start - for ensuring safe memory release.
+static void
+ohci_waittick(struct usb_ohci_s *cntl)
+{
+    barrier();
+    struct ohci_hcca *hcca = (void*)cntl->regs->hcca;
+    u32 startframe = hcca->frame_no;
+    u32 end = timer_calc(1000 * 5);
+    for (;;) {
+        if (hcca->frame_no != startframe)
+            break;
+        if (timer_check(end)) {
+            warn_timeout();
+            return;
+        }
+        yield();
+    }
+}
+
+static void
+ohci_free_pipes(struct usb_ohci_s *cntl)
+{
+    dprintf(7, "ohci_free_pipes %p\n", cntl);
+
+    u32 creg = readl(&cntl->regs->control);
+    if (creg & (OHCI_CTRL_CLE|OHCI_CTRL_BLE)) {
+        writel(&cntl->regs->control, creg & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE));
+        ohci_waittick(cntl);
+    }
+
+    u32 *pos = &cntl->regs->ed_controlhead;
+    for (;;) {
+        struct ohci_ed *next = (void*)*pos;
+        if (!next)
+            break;
+        struct ohci_pipe *pipe = container_of(next, struct ohci_pipe, ed);
+        if (pipe->pipe.cntl != &cntl->usb) {
+            *pos = next->hwNextED;
+            free(pipe);
+        } else {
+            pos = &next->hwNextED;
+        }
+    }
+
+    writel(&cntl->regs->ed_controlcurrent, 0);
+    writel(&cntl->regs->ed_bulkcurrent, 0);
+    writel(&cntl->regs->control, creg);
+    cntl->usb.freelist = NULL;
+}
+
+static int
+start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca)
+{
+    u32 oldfminterval = readl(&cntl->regs->fminterval);
+    u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC;
+
+    // XXX - check if already running?
+
+    // Do reset
+    writel(&cntl->regs->control, OHCI_USB_RESET | oldrwc);
+    readl(&cntl->regs->control); // flush writes
+    msleep(USB_TIME_DRSTR);
+
+    // Do software init (min 10us, max 2ms)
+    u32 end = timer_calc_usec(10);
+    writel(&cntl->regs->cmdstatus, OHCI_HCR);
+    for (;;) {
+        u32 status = readl(&cntl->regs->cmdstatus);
+        if (! status & OHCI_HCR)
+            break;
+        if (timer_check(end)) {
+            warn_timeout();
+            return -1;
+        }
+    }
+
+    // Init memory
+    writel(&cntl->regs->ed_controlhead, 0);
+    writel(&cntl->regs->ed_bulkhead, 0);
+    writel(&cntl->regs->hcca, (u32)hcca);
+
+    // Init fminterval
+    u32 fi = oldfminterval & 0x3fff;
+    writel(&cntl->regs->fminterval
+           , (((oldfminterval & FIT) ^ FIT)
+              | fi | (((6 * (fi - 210)) / 7) << 16)));
+    writel(&cntl->regs->periodicstart, ((9 * fi) / 10) & 0x3fff);
+    readl(&cntl->regs->control); // flush writes
+
+    // XXX - verify that fminterval was setup correctly.
+
+    // Go into operational state
+    writel(&cntl->regs->control
+           , (OHCI_CTRL_CBSR | OHCI_CTRL_CLE | OHCI_CTRL_PLE
+              | OHCI_USB_OPER | oldrwc));
+    readl(&cntl->regs->control); // flush writes
+
+    return 0;
+}
+
+static void
+stop_ohci(struct usb_ohci_s *cntl)
+{
+    u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC;
+    writel(&cntl->regs->control, oldrwc);
+    readl(&cntl->regs->control); // flush writes
+}
+
+static void
+configure_ohci(void *data)
+{
+    struct usb_ohci_s *cntl = data;
+
+    // Allocate memory
+    struct ohci_hcca *hcca = memalign_high(256, sizeof(*hcca));
+    struct ohci_ed *intr_ed = malloc_high(sizeof(*intr_ed));
+    if (!hcca || !intr_ed) {
+        warn_noalloc();
+        goto free;
+    }
+    memset(hcca, 0, sizeof(*hcca));
+    memset(intr_ed, 0, sizeof(*intr_ed));
+    intr_ed->hwINFO = ED_SKIP;
+    int i;
+    for (i=0; i<ARRAY_SIZE(hcca->int_table); i++)
+        hcca->int_table[i] = (u32)intr_ed;
+
+    int ret = start_ohci(cntl, hcca);
+    if (ret)
+        goto err;
+
+    int count = check_ohci_ports(cntl);
+    ohci_free_pipes(cntl);
+    if (! count)
+        goto err;
+    return;
+
+err:
+    stop_ohci(cntl);
+free:
+    free(hcca);
+    free(intr_ed);
+}
+
+void
+ohci_setup(struct pci_device *pci, int busid)
+{
+    if (! CONFIG_USB_OHCI)
+        return;
+    struct usb_ohci_s *cntl = malloc_tmphigh(sizeof(*cntl));
+    if (!cntl) {
+        warn_noalloc();
+        return;
+    }
+    memset(cntl, 0, sizeof(*cntl));
+    cntl->usb.busid = busid;
+    cntl->usb.pci = pci;
+    cntl->usb.type = USB_TYPE_OHCI;
+
+    u16 bdf = pci->bdf;
+    u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0);
+    cntl->regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK);
+
+    dprintf(1, "OHCI 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);
+
+    // Enable bus mastering and memory access.
+    pci_config_maskw(bdf, PCI_COMMAND
+                     , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY);
+
+    // XXX - check for and disable SMM control?
+
+    // Disable interrupts
+    writel(&cntl->regs->intrdisable, ~0);
+    writel(&cntl->regs->intrstatus, ~0);
+
+    run_thread(configure_ohci, cntl);
+}
+
+
+/****************************************************************
+ * End point communication
+ ****************************************************************/
+
+// Setup fields in ed
+static void
+ohci_desc2pipe(struct ohci_pipe *pipe, struct usbdevice_s *usbdev
+               , struct usb_endpoint_descriptor *epdesc)
+{
+    usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
+    pipe->ed.hwINFO = (ED_SKIP | usbdev->devaddr | (pipe->pipe.ep << 7)
+                       | (epdesc->wMaxPacketSize << 16)
+                       | (usbdev->speed ? ED_LOWSPEED : 0));
+}
+
+static struct usb_pipe *
+ohci_alloc_intr_pipe(struct usbdevice_s *usbdev
+                     , struct usb_endpoint_descriptor *epdesc)
+{
+    struct usb_ohci_s *cntl = container_of(
+        usbdev->hub->cntl, struct usb_ohci_s, usb);
+    int frameexp = usb_getFrameExp(usbdev, epdesc);
+    dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
+
+    if (frameexp > 5)
+        frameexp = 5;
+    int maxpacket = epdesc->wMaxPacketSize;
+    // Determine number of entries needed for 2 timer ticks.
+    int ms = 1<<frameexp;
+    int count = DIV_ROUND_UP(ticks_to_ms(2), ms) + 1;
+    struct ohci_pipe *pipe = malloc_low(sizeof(*pipe));
+    struct ohci_td *tds = malloc_low(sizeof(*tds) * count);
+    void *data = malloc_low(maxpacket * count);
+    if (!pipe || !tds || !data)
+        goto err;
+    memset(pipe, 0, sizeof(*pipe));
+    ohci_desc2pipe(pipe, usbdev, epdesc);
+    pipe->ed.hwINFO &= ~ED_SKIP;
+    pipe->data = data;
+    pipe->count = count;
+    pipe->tds = tds;
+
+    struct ohci_ed *ed = &pipe->ed;
+    ed->hwHeadP = (u32)&tds[0];
+    ed->hwTailP = (u32)&tds[count-1];
+
+    int i;
+    for (i=0; i<count-1; i++) {
+        tds[i].hwINFO = TD_DP_IN | TD_T_TOGGLE | TD_CC;
+        tds[i].hwCBP = (u32)data + maxpacket * i;
+        tds[i].hwNextTD = (u32)&tds[i+1];
+        tds[i].hwBE = tds[i].hwCBP + maxpacket - 1;
+    }
+
+    // Add to interrupt schedule.
+    struct ohci_hcca *hcca = (void*)cntl->regs->hcca;
+    if (frameexp == 0) {
+        // Add to existing interrupt entry.
+        struct ohci_ed *intr_ed = (void*)hcca->int_table[0];
+        ed->hwNextED = intr_ed->hwNextED;
+        barrier();
+        intr_ed->hwNextED = (u32)ed;
+    } else {
+        int startpos = 1<<(frameexp-1);
+        ed->hwNextED = hcca->int_table[startpos];
+        barrier();
+        for (i=startpos; i<ARRAY_SIZE(hcca->int_table); i+=ms)
+            hcca->int_table[i] = (u32)ed;
+    }
+
+    return &pipe->pipe;
+
+err:
+    free(pipe);
+    free(tds);
+    free(data);
+    return NULL;
+}
+
+struct usb_pipe *
+ohci_alloc_pipe(struct usbdevice_s *usbdev
+                , struct usb_endpoint_descriptor *epdesc)
+{
+    if (! CONFIG_USB_OHCI)
+        return NULL;
+    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+    if (eptype == USB_ENDPOINT_XFER_INT)
+        return ohci_alloc_intr_pipe(usbdev, epdesc);
+    if (eptype != USB_ENDPOINT_XFER_CONTROL) {
+        dprintf(1, "OHCI Bulk transfers not supported.\n");
+        return NULL;
+    }
+    struct usb_ohci_s *cntl = container_of(
+        usbdev->hub->cntl, struct usb_ohci_s, usb);
+    dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb);
+
+    struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
+    if (usbpipe) {
+        // Use previously allocated pipe.
+        struct ohci_pipe *pipe = container_of(usbpipe, struct ohci_pipe, pipe);
+        ohci_desc2pipe(pipe, usbdev, epdesc);
+        return usbpipe;
+    }
+
+    // Allocate a new queue head.
+    struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
+    if (!pipe) {
+        warn_noalloc();
+        return NULL;
+    }
+    memset(pipe, 0, sizeof(*pipe));
+    ohci_desc2pipe(pipe, usbdev, epdesc);
+
+    // Add queue head to controller list.
+    pipe->ed.hwNextED = cntl->regs->ed_controlhead;
+    barrier();
+    cntl->regs->ed_controlhead = (u32)&pipe->ed;
+    return &pipe->pipe;
+}
+
+static int
+wait_ed(struct ohci_ed *ed)
+{
+    // XXX - 500ms just a guess
+    u32 end = timer_calc(500);
+    for (;;) {
+        if (ed->hwHeadP == ed->hwTailP)
+            return 0;
+        if (timer_check(end)) {
+            warn_timeout();
+            return -1;
+        }
+        yield();
+    }
+}
+
+int
+ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+             , void *data, int datasize)
+{
+    if (! CONFIG_USB_OHCI)
+        return -1;
+    dprintf(5, "ohci_control %p\n", p);
+    if (datasize > 4096) {
+        // XXX - should support larger sizes.
+        warn_noalloc();
+        return -1;
+    }
+    struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
+    struct usb_ohci_s *cntl = container_of(
+        pipe->pipe.cntl, struct usb_ohci_s, usb);
+
+    // Setup transfer descriptors
+    struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3);
+    if (!tds) {
+        warn_noalloc();
+        return -1;
+    }
+    struct ohci_td *td = tds;
+    td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC;
+    td->hwCBP = (u32)cmd;
+    td->hwNextTD = (u32)&td[1];
+    td->hwBE = (u32)cmd + cmdsize - 1;
+    td++;
+    if (datasize) {
+        td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC;
+        td->hwCBP = (u32)data;
+        td->hwNextTD = (u32)&td[1];
+        td->hwBE = (u32)data + datasize - 1;
+        td++;
+    }
+    td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC;
+    td->hwCBP = 0;
+    td->hwNextTD = (u32)&td[1];
+    td->hwBE = 0;
+    td++;
+
+    // Transfer data
+    pipe->ed.hwHeadP = (u32)tds;
+    pipe->ed.hwTailP = (u32)td;
+    barrier();
+    pipe->ed.hwINFO &= ~ED_SKIP;
+    writel(&cntl->regs->cmdstatus, OHCI_CLF);
+
+    int ret = wait_ed(&pipe->ed);
+    pipe->ed.hwINFO |= ED_SKIP;
+    if (ret)
+        ohci_waittick(cntl);
+    free(tds);
+    return ret;
+}
+
+int
+ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
+{
+    return -1;
+}
+
+int
+ohci_poll_intr(struct usb_pipe *p, void *data)
+{
+    ASSERT16();
+    if (! CONFIG_USB_OHCI)
+        return -1;
+
+    struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
+    struct ohci_td *tds = GET_LOWFLAT(pipe->tds);
+    struct ohci_td *head = (void*)(GET_LOWFLAT(pipe->ed.hwHeadP) & ~(ED_C|ED_H));
+    struct ohci_td *tail = (void*)GET_LOWFLAT(pipe->ed.hwTailP);
+    int count = GET_LOWFLAT(pipe->count);
+    int pos = (tail - tds + 1) % count;
+    struct ohci_td *next = &tds[pos];
+    if (head == next)
+        // No intrs found.
+        return -1;
+    // XXX - check for errors.
+
+    // Copy data.
+    int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
+    void *pipedata = GET_LOWFLAT((pipe->data));
+    void *intrdata = pipedata + maxpacket * pos;
+    memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(intrdata), maxpacket);
+
+    // Reenable this td.
+    SET_LOWFLAT(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC);
+    intrdata = pipedata + maxpacket * (tail-tds);
+    SET_LOWFLAT(tail->hwCBP, (u32)intrdata);
+    SET_LOWFLAT(tail->hwNextTD, (u32)next);
+    SET_LOWFLAT(tail->hwBE, (u32)intrdata + maxpacket - 1);
+    barrier();
+    SET_LOWFLAT(pipe->ed.hwTailP, (u32)next);
+
+    return 0;
+}
diff --git a/src/hw/usb-ohci.h b/src/hw/usb-ohci.h
new file mode 100644 (file)
index 0000000..ad0ffec
--- /dev/null
@@ -0,0 +1,143 @@
+#ifndef __USB_OHCI_H
+#define __USB_OHCI_H
+
+// usb-ohci.c
+void ohci_setup(struct pci_device *pci, int busid);
+struct usbdevice_s;
+struct usb_endpoint_descriptor;
+struct usb_pipe *ohci_alloc_pipe(struct usbdevice_s *usbdev
+                                 , struct usb_endpoint_descriptor *epdesc);
+struct usb_pipe;
+int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+                 , void *data, int datasize);
+int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
+int ohci_poll_intr(struct usb_pipe *p, void *data);
+
+
+/****************************************************************
+ * ohci structs and flags
+ ****************************************************************/
+
+struct ohci_ed {
+    u32 hwINFO;
+    u32 hwTailP;
+    u32 hwHeadP;
+    u32 hwNextED;
+} PACKED;
+
+#define ED_ISO          (1 << 15)
+#define ED_SKIP         (1 << 14)
+#define ED_LOWSPEED     (1 << 13)
+#define ED_OUT          (0x01 << 11)
+#define ED_IN           (0x02 << 11)
+
+#define ED_C            (0x02)
+#define ED_H            (0x01)
+
+struct ohci_td {
+    u32 hwINFO;
+    u32 hwCBP;
+    u32 hwNextTD;
+    u32 hwBE;
+} PACKED;
+
+#define TD_CC       0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_DI       0x00E00000
+
+#define TD_DONE     0x00020000
+#define TD_ISO      0x00010000
+
+#define TD_EC       0x0C000000
+#define TD_T        0x03000000
+#define TD_T_DATA0  0x02000000
+#define TD_T_DATA1  0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_DP       0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN    0x00100000
+#define TD_DP_OUT   0x00080000
+
+#define TD_R        0x00040000
+
+struct ohci_hcca {
+    u32  int_table[32];
+    u32  frame_no;
+    u32  done_head;
+    u8   reserved[120];
+} PACKED;
+
+struct ohci_regs {
+    u32  revision;
+    u32  control;
+    u32  cmdstatus;
+    u32  intrstatus;
+    u32  intrenable;
+    u32  intrdisable;
+
+    u32  hcca;
+    u32  ed_periodcurrent;
+    u32  ed_controlhead;
+    u32  ed_controlcurrent;
+    u32  ed_bulkhead;
+    u32  ed_bulkcurrent;
+    u32  donehead;
+
+    u32  fminterval;
+    u32  fmremaining;
+    u32  fmnumber;
+    u32  periodicstart;
+    u32  lsthresh;
+
+    u32  roothub_a;
+    u32  roothub_b;
+    u32  roothub_status;
+    u32  roothub_portstatus[15];
+} PACKED;
+
+#define OHCI_CTRL_CBSR  (3 << 0)
+#define OHCI_CTRL_PLE   (1 << 2)
+#define OHCI_CTRL_CLE   (1 << 4)
+#define OHCI_CTRL_BLE   (1 << 5)
+#define OHCI_CTRL_HCFS  (3 << 6)
+#       define OHCI_USB_RESET   (0 << 6)
+#       define OHCI_USB_OPER    (2 << 6)
+#define OHCI_CTRL_RWC   (1 << 9)
+
+#define OHCI_HCR        (1 << 0)
+#define OHCI_CLF        (1 << 1)
+
+#define OHCI_INTR_MIE   (1 << 31)
+
+#define RH_PS_CCS            0x00000001
+#define RH_PS_PES            0x00000002
+#define RH_PS_PSS            0x00000004
+#define RH_PS_POCI           0x00000008
+#define RH_PS_PRS            0x00000010
+#define RH_PS_PPS            0x00000100
+#define RH_PS_LSDA           0x00000200
+#define RH_PS_CSC            0x00010000
+#define RH_PS_PESC           0x00020000
+#define RH_PS_PSSC           0x00040000
+#define RH_PS_OCIC           0x00080000
+#define RH_PS_PRSC           0x00100000
+
+#define RH_HS_LPS            0x00000001
+#define RH_HS_OCI            0x00000002
+#define RH_HS_DRWE           0x00008000
+#define RH_HS_LPSC           0x00010000
+#define RH_HS_OCIC           0x00020000
+#define RH_HS_CRWE           0x80000000
+
+#define RH_B_DR         0x0000ffff
+#define RH_B_PPCM       0xffff0000
+
+#define RH_A_NDP        (0xff << 0)
+#define RH_A_PSM        (1 << 8)
+#define RH_A_NPS        (1 << 9)
+#define RH_A_DT         (1 << 10)
+#define RH_A_OCPM       (1 << 11)
+#define RH_A_NOCP       (1 << 12)
+#define RH_A_POTPGT     (0xff << 24)
+
+#endif // usb-ohci.h
diff --git a/src/hw/usb-uas.c b/src/hw/usb-uas.c
new file mode 100644 (file)
index 0000000..3169389
--- /dev/null
@@ -0,0 +1,264 @@
+// Code for handling usb attached scsi devices.
+//
+// only usb 2.0 for now.
+//
+// once we have xhci driver with usb 3.0 support this must
+// be updated to use usb3 streams so booting from usb3
+// devices actually works.
+//
+// Authors:
+//  Gerd Hoffmann <kraxel@redhat.com>
+//
+// based on usb-msc.c which is written by:
+//  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_USB_UAS
+#include "usb.h" // struct usb_s
+#include "biosvar.h" // GET_GLOBAL
+#include "blockcmd.h" // cdb_read
+#include "disk.h" // DTYPE_UAS
+#include "boot.h" // bootprio_find_usb
+#include "usb-uas.h" // usb_uas_init
+
+#define UAS_UI_COMMAND              0x01
+#define UAS_UI_SENSE                0x03
+#define UAS_UI_RESPONSE             0x04
+#define UAS_UI_TASK_MGMT            0x05
+#define UAS_UI_READ_READY           0x06
+#define UAS_UI_WRITE_READY          0x07
+
+#define UAS_PIPE_ID_COMMAND         0x01
+#define UAS_PIPE_ID_STATUS          0x02
+#define UAS_PIPE_ID_DATA_IN         0x03
+#define UAS_PIPE_ID_DATA_OUT        0x04
+
+typedef struct {
+    u8    id;
+    u8    reserved;
+    u16   tag;
+} PACKED  uas_ui_header;
+
+typedef struct {
+    u8    prio_taskattr;   /* 6:3 priority, 2:0 task attribute   */
+    u8    reserved_1;
+    u8    add_cdb_length;  /* 7:2 additional adb length (dwords) */
+    u8    reserved_2;
+    u8    lun[8];
+    u8    cdb[16];
+    u8    add_cdb[];
+} PACKED  uas_ui_command;
+
+typedef struct {
+    u16   status_qualifier;
+    u8    status;
+    u8    reserved[7];
+    u16   sense_length;
+    u8    sense_data[18];
+} PACKED  uas_ui_sense;
+
+typedef struct {
+    u16   add_response_info;
+    u8    response_code;
+} PACKED  uas_ui_response;
+
+typedef struct {
+    u8    function;
+    u8    reserved;
+    u16   task_tag;
+    u8    lun[8];
+} PACKED  uas_ui_task_mgmt;
+
+typedef struct {
+    uas_ui_header  hdr;
+    union {
+        uas_ui_command   command;
+        uas_ui_sense     sense;
+        uas_ui_task_mgmt task;
+        uas_ui_response  response;
+    };
+} PACKED  uas_ui;
+
+struct uasdrive_s {
+    struct drive_s drive;
+    struct usb_pipe *command, *status, *data_in, *data_out;
+    int lun;
+};
+
+int
+uas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    if (!CONFIG_USB_UAS)
+        return DISK_RET_EBADTRACK;
+
+    struct uasdrive_s *drive = container_of(
+        op->drive_g, struct uasdrive_s, drive);
+
+    uas_ui ui;
+    memset(&ui, 0, sizeof(ui));
+    ui.hdr.id = UAS_UI_COMMAND;
+    ui.hdr.tag = 0xdead;
+    ui.command.lun[1] = drive->lun;
+    memcpy(ui.command.cdb, cdbcmd, sizeof(ui.command.cdb));
+    int ret = usb_send_bulk(GET_GLOBAL(drive->command),
+                            USB_DIR_OUT, MAKE_FLATPTR(GET_SEG(SS), &ui),
+                            sizeof(ui.hdr) + sizeof(ui.command));
+    if (ret) {
+        dprintf(1, "uas: command send fail");
+        goto fail;
+    }
+
+    memset(&ui, 0xff, sizeof(ui));
+    ret = usb_send_bulk(GET_GLOBAL(drive->status),
+                        USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui));
+    if (ret) {
+        dprintf(1, "uas: status recv fail");
+        goto fail;
+    }
+
+    switch (ui.hdr.id) {
+    case UAS_UI_SENSE:
+        goto have_sense;
+    case UAS_UI_READ_READY:
+        ret = usb_send_bulk(GET_GLOBAL(drive->data_in),
+                            USB_DIR_IN, op->buf_fl, op->count * blocksize);
+        if (ret) {
+            dprintf(1, "uas: data read fail");
+            goto fail;
+        }
+        break;
+    case UAS_UI_WRITE_READY:
+        ret = usb_send_bulk(GET_GLOBAL(drive->data_out),
+                            USB_DIR_OUT, op->buf_fl, op->count * blocksize);
+        if (ret) {
+            dprintf(1, "uas: data write fail");
+            goto fail;
+        }
+        break;
+    default:
+        dprintf(1, "uas: unknown status ui id %d", ui.hdr.id);
+        goto fail;
+    }
+
+    memset(&ui, 0xff, sizeof(ui));
+    ret = usb_send_bulk(GET_GLOBAL(drive->status),
+                        USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui));
+    if (ret) {
+        dprintf(1, "uas: status recv fail");
+        goto fail;
+    }
+    if (ui.hdr.id != UAS_UI_SENSE) {
+        dprintf(1, "uas: expected sense ui, got ui id %d", ui.hdr.id);
+        goto fail;
+    }
+
+have_sense:
+    if (ui.sense.status == 0) {
+        return DISK_RET_SUCCESS;
+    }
+
+fail:
+    return DISK_RET_EBADTRACK;
+}
+
+static int
+uas_lun_setup(struct usbdevice_s *usbdev,
+              struct usb_pipe *command, struct usb_pipe *status,
+              struct usb_pipe *data_in, struct usb_pipe *data_out,
+              int lun)
+{
+    // Allocate drive structure.
+    struct uasdrive_s *drive = malloc_fseg(sizeof(*drive));
+    if (!drive) {
+        warn_noalloc();
+        return -1;
+    }
+    memset(drive, 0, sizeof(*drive));
+    drive->drive.type = DTYPE_UAS;
+    drive->command = command;
+    drive->status = status;
+    drive->data_in = data_in;
+    drive->data_out = data_out;
+    drive->lun = lun;
+
+    int prio = bootprio_find_usb(usbdev, lun);
+    int ret = scsi_drive_setup(&drive->drive, "USB UAS", prio);
+    if (ret) {
+        free(drive);
+        return -1;
+    }
+    return 0;
+}
+
+int
+usb_uas_setup(struct usbdevice_s *usbdev)
+{
+    if (!CONFIG_USB_UAS)
+        return -1;
+
+    // Verify right kind of device
+    struct usb_interface_descriptor *iface = usbdev->iface;
+    if (iface->bInterfaceSubClass != US_SC_SCSI ||
+        iface->bInterfaceProtocol != US_PR_UAS) {
+        dprintf(1, "Unsupported UAS device (subclass=%02x proto=%02x)\n"
+                , iface->bInterfaceSubClass, iface->bInterfaceProtocol);
+        return -1;
+    }
+
+    /* find & allocate pipes */
+    struct usb_endpoint_descriptor *ep = NULL;
+    struct usb_pipe *command = NULL;
+    struct usb_pipe *status = NULL;
+    struct usb_pipe *data_in = NULL;
+    struct usb_pipe *data_out = NULL;
+    u8 *desc = (u8*)iface;
+    while (desc) {
+        desc += desc[0];
+        switch (desc[1]) {
+        case USB_DT_ENDPOINT:
+            ep = (void*)desc;
+            break;
+        case 0x24:
+            switch (desc[2]) {
+            case UAS_PIPE_ID_COMMAND:
+                command = usb_alloc_pipe(usbdev, ep);
+                break;
+            case UAS_PIPE_ID_STATUS:
+                status = usb_alloc_pipe(usbdev, ep);
+                break;
+            case UAS_PIPE_ID_DATA_IN:
+                data_in = usb_alloc_pipe(usbdev, ep);
+                break;
+            case UAS_PIPE_ID_DATA_OUT:
+                data_out = usb_alloc_pipe(usbdev, ep);
+                break;
+            default:
+                goto fail;
+            }
+            break;
+        default:
+            desc = NULL;
+            break;
+        }
+    }
+    if (!command || !status || !data_in || !data_out)
+        goto fail;
+
+    /* TODO: send REPORT LUNS.  For now, only LUN 0 is recognized.  */
+    int ret = uas_lun_setup(usbdev, command, status, data_in, data_out, 0);
+    if (ret < 0) {
+        dprintf(1, "Unable to configure UAS drive.\n");
+        goto fail;
+    }
+
+    return 0;
+
+fail:
+    free_pipe(command);
+    free_pipe(status);
+    free_pipe(data_in);
+    free_pipe(data_out);
+    return -1;
+}
diff --git a/src/hw/usb-uas.h b/src/hw/usb-uas.h
new file mode 100644 (file)
index 0000000..ad91c5f
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __USB_UAS_H
+#define __USB_UAS_H
+
+struct disk_op_s;
+int uas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+struct usbdevice_s;
+int usb_uas_setup(struct usbdevice_s *usbdev);
+
+#endif /* __USB_UAS_H */
diff --git a/src/hw/usb-uhci.c b/src/hw/usb-uhci.c
new file mode 100644 (file)
index 0000000..d8f9b1e
--- /dev/null
@@ -0,0 +1,578 @@
+// Code for handling UHCI USB controllers.
+//
+// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // pci_bdf_to_bus
+#include "config.h" // CONFIG_*
+#include "ioport.h" // outw
+#include "usb-uhci.h" // USBLEGSUP
+#include "pci_regs.h" // PCI_BASE_ADDRESS_4
+#include "usb.h" // struct usb_s
+#include "biosvar.h" // GET_LOWFLAT
+
+struct usb_uhci_s {
+    struct usb_s usb;
+    u16 iobase;
+    struct uhci_qh *control_qh;
+    struct uhci_framelist *framelist;
+};
+
+struct uhci_pipe {
+    struct uhci_qh qh;
+    struct uhci_td *next_td;
+    struct usb_pipe pipe;
+    u16 iobase;
+    u8 toggle;
+};
+
+
+/****************************************************************
+ * Root hub
+ ****************************************************************/
+
+// Check if device attached to a given port
+static int
+uhci_hub_detect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
+    u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
+
+    u16 status = inw(ioport);
+    if (!(status & USBPORTSC_CCS))
+        // No device
+        return -1;
+
+    // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
+
+    // Begin reset on port
+    outw(USBPORTSC_PR, ioport);
+    msleep(USB_TIME_DRSTR);
+    return 0;
+}
+
+// Reset device on port
+static int
+uhci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+    struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
+    u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
+
+    // Finish reset on port
+    outw(0, ioport);
+    udelay(6); // 64 high-speed bit times
+    u16 status = inw(ioport);
+    if (!(status & USBPORTSC_CCS))
+        // No longer connected
+        return -1;
+    outw(USBPORTSC_PE, ioport);
+    return !!(status & USBPORTSC_LSDA);
+}
+
+// Disable port
+static void
+uhci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
+    u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
+    outw(0, ioport);
+}
+
+static struct usbhub_op_s uhci_HubOp = {
+    .detect = uhci_hub_detect,
+    .reset = uhci_hub_reset,
+    .disconnect = uhci_hub_disconnect,
+};
+
+// Find any devices connected to the root hub.
+static int
+check_uhci_ports(struct usb_uhci_s *cntl)
+{
+    ASSERT32FLAT();
+    struct usbhub_s hub;
+    memset(&hub, 0, sizeof(hub));
+    hub.cntl = &cntl->usb;
+    hub.portcount = 2;
+    hub.op = &uhci_HubOp;
+    usb_enumerate(&hub);
+    return hub.devcount;
+}
+
+
+/****************************************************************
+ * Setup
+ ****************************************************************/
+
+// Wait for next USB frame to start - for ensuring safe memory release.
+static void
+uhci_waittick(u16 iobase)
+{
+    barrier();
+    u16 startframe = inw(iobase + USBFRNUM);
+    u32 end = timer_calc(1000 * 5);
+    for (;;) {
+        if (inw(iobase + USBFRNUM) != startframe)
+            break;
+        if (timer_check(end)) {
+            warn_timeout();
+            return;
+        }
+        yield();
+    }
+}
+
+static void
+uhci_free_pipes(struct usb_uhci_s *cntl)
+{
+    dprintf(7, "uhci_free_pipes %p\n", cntl);
+
+    struct uhci_qh *pos = (void*)(cntl->framelist->links[0] & ~UHCI_PTR_BITS);
+    for (;;) {
+        u32 link = pos->link;
+        if (link == UHCI_PTR_TERM)
+            break;
+        struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS);
+        struct uhci_pipe *pipe = container_of(next, struct uhci_pipe, qh);
+        if (pipe->pipe.cntl != &cntl->usb)
+            pos->link = next->link;
+        else
+            pos = next;
+    }
+    uhci_waittick(cntl->iobase);
+    for (;;) {
+        struct usb_pipe *usbpipe = cntl->usb.freelist;
+        if (!usbpipe)
+            break;
+        cntl->usb.freelist = usbpipe->freenext;
+        struct uhci_pipe *pipe = container_of(usbpipe, struct uhci_pipe, pipe);
+        free(pipe);
+    }
+}
+
+static void
+reset_uhci(struct usb_uhci_s *cntl, u16 bdf)
+{
+    // XXX - don't reset if not needed.
+
+    // Reset PIRQ and SMI
+    pci_config_writew(bdf, USBLEGSUP, USBLEGSUP_RWC);
+
+    // Reset the HC
+    outw(USBCMD_HCRESET, cntl->iobase + USBCMD);
+    udelay(5);
+
+    // Disable interrupts and commands (just to be safe).
+    outw(0, cntl->iobase + USBINTR);
+    outw(0, cntl->iobase + USBCMD);
+}
+
+static void
+configure_uhci(void *data)
+{
+    struct usb_uhci_s *cntl = data;
+
+    // Allocate ram for schedule storage
+    struct uhci_td *term_td = malloc_high(sizeof(*term_td));
+    struct uhci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl));
+    struct uhci_pipe *intr_pipe = malloc_high(sizeof(*intr_pipe));
+    struct uhci_pipe *term_pipe = malloc_high(sizeof(*term_pipe));
+    if (!term_td || !fl || !intr_pipe || !term_pipe) {
+        warn_noalloc();
+        goto fail;
+    }
+
+    // Work around for PIIX errata
+    memset(term_td, 0, sizeof(*term_td));
+    term_td->link = UHCI_PTR_TERM;
+    term_td->token = (uhci_explen(0) | (0x7f << TD_TOKEN_DEVADDR_SHIFT)
+                      | USB_PID_IN);
+    memset(term_pipe, 0, sizeof(*term_pipe));
+    term_pipe->qh.element = (u32)term_td;
+    term_pipe->qh.link = UHCI_PTR_TERM;
+    term_pipe->pipe.cntl = &cntl->usb;
+
+    // Set schedule to point to primary intr queue head
+    memset(intr_pipe, 0, sizeof(*intr_pipe));
+    intr_pipe->qh.element = UHCI_PTR_TERM;
+    intr_pipe->qh.link = (u32)&term_pipe->qh | UHCI_PTR_QH;
+    intr_pipe->pipe.cntl = &cntl->usb;
+    int i;
+    for (i=0; i<ARRAY_SIZE(fl->links); i++)
+        fl->links[i] = (u32)&intr_pipe->qh | UHCI_PTR_QH;
+    cntl->framelist = fl;
+    cntl->control_qh = &intr_pipe->qh;
+    barrier();
+
+    // Set the frame length to the default: 1 ms exactly
+    outb(USBSOF_DEFAULT, cntl->iobase + USBSOF);
+
+    // Store the frame list base address
+    outl((u32)fl->links, cntl->iobase + USBFLBASEADD);
+
+    // Set the current frame number
+    outw(0, cntl->iobase + USBFRNUM);
+
+    // Mark as configured and running with a 64-byte max packet.
+    outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->iobase + USBCMD);
+
+    // Find devices
+    int count = check_uhci_ports(cntl);
+    uhci_free_pipes(cntl);
+    if (count)
+        // Success
+        return;
+
+    // No devices found - shutdown and free controller.
+    outw(0, cntl->iobase + USBCMD);
+fail:
+    free(term_td);
+    free(fl);
+    free(intr_pipe);
+    free(term_pipe);
+    free(cntl);
+}
+
+void
+uhci_setup(struct pci_device *pci, int busid)
+{
+    if (! CONFIG_USB_UHCI)
+        return;
+    u16 bdf = pci->bdf;
+    struct usb_uhci_s *cntl = malloc_tmphigh(sizeof(*cntl));
+    if (!cntl) {
+        warn_noalloc();
+        return;
+    }
+    memset(cntl, 0, sizeof(*cntl));
+    cntl->usb.busid = busid;
+    cntl->usb.pci = pci;
+    cntl->usb.type = USB_TYPE_UHCI;
+    cntl->iobase = (pci_config_readl(bdf, PCI_BASE_ADDRESS_4)
+                    & PCI_BASE_ADDRESS_IO_MASK);
+
+    dprintf(1, "UHCI init on dev %02x:%02x.%x (io=%x)\n"
+            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)
+            , pci_bdf_to_fn(bdf), cntl->iobase);
+
+    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
+
+    reset_uhci(cntl, bdf);
+
+    run_thread(configure_uhci, cntl);
+}
+
+
+/****************************************************************
+ * End point communication
+ ****************************************************************/
+
+static struct usb_pipe *
+uhci_alloc_intr_pipe(struct usbdevice_s *usbdev
+                     , struct usb_endpoint_descriptor *epdesc)
+{
+    struct usb_uhci_s *cntl = container_of(
+        usbdev->hub->cntl, struct usb_uhci_s, usb);
+    int frameexp = usb_getFrameExp(usbdev, epdesc);
+    dprintf(7, "uhci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
+
+    if (frameexp > 10)
+        frameexp = 10;
+    int maxpacket = epdesc->wMaxPacketSize;
+    // Determine number of entries needed for 2 timer ticks.
+    int ms = 1<<frameexp;
+    int count = DIV_ROUND_UP(ticks_to_ms(2), ms);
+    count = ALIGN(count, 2);
+    struct uhci_pipe *pipe = malloc_low(sizeof(*pipe));
+    struct uhci_td *tds = malloc_low(sizeof(*tds) * count);
+    void *data = malloc_low(maxpacket * count);
+    if (!pipe || !tds || !data) {
+        warn_noalloc();
+        goto fail;
+    }
+    memset(pipe, 0, sizeof(*pipe));
+    usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
+    int lowspeed = pipe->pipe.speed;
+    int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7);
+    pipe->qh.element = (u32)tds;
+    pipe->next_td = &tds[0];
+    pipe->iobase = cntl->iobase;
+
+    int toggle = 0;
+    int i;
+    for (i=0; i<count; i++) {
+        tds[i].link = (i==count-1 ? (u32)&tds[0] : (u32)&tds[i+1]);
+        tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
+                         | TD_CTRL_ACTIVE);
+        tds[i].token = (uhci_explen(maxpacket) | toggle
+                        | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
+                        | USB_PID_IN);
+        tds[i].buffer = data + maxpacket * i;
+        toggle ^= TD_TOKEN_TOGGLE;
+    }
+
+    // Add to interrupt schedule.
+    struct uhci_framelist *fl = cntl->framelist;
+    if (frameexp == 0) {
+        // Add to existing interrupt entry.
+        struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS);
+        pipe->qh.link = intr_qh->link;
+        barrier();
+        intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
+        if (cntl->control_qh == intr_qh)
+            cntl->control_qh = &pipe->qh;
+    } else {
+        int startpos = 1<<(frameexp-1);
+        pipe->qh.link = fl->links[startpos];
+        barrier();
+        for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms)
+            fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH;
+    }
+
+    return &pipe->pipe;
+fail:
+    free(pipe);
+    free(tds);
+    free(data);
+    return NULL;
+}
+
+struct usb_pipe *
+uhci_alloc_pipe(struct usbdevice_s *usbdev
+                , struct usb_endpoint_descriptor *epdesc)
+{
+    if (! CONFIG_USB_UHCI)
+        return NULL;
+    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+    if (eptype == USB_ENDPOINT_XFER_INT)
+        return uhci_alloc_intr_pipe(usbdev, epdesc);
+    struct usb_uhci_s *cntl = container_of(
+        usbdev->hub->cntl, struct usb_uhci_s, usb);
+    dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);
+
+    struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
+    if (usbpipe) {
+        // Use previously allocated pipe.
+        usb_desc2pipe(usbpipe, usbdev, epdesc);
+        return usbpipe;
+    }
+
+    // Allocate a new queue head.
+    struct uhci_pipe *pipe;
+    if (eptype == USB_ENDPOINT_XFER_CONTROL)
+        pipe = malloc_tmphigh(sizeof(*pipe));
+    else
+        pipe = malloc_low(sizeof(*pipe));
+    if (!pipe) {
+        warn_noalloc();
+        return NULL;
+    }
+    memset(pipe, 0, sizeof(*pipe));
+    usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
+    pipe->qh.element = UHCI_PTR_TERM;
+    pipe->iobase = cntl->iobase;
+
+    // Add queue head to controller list.
+    struct uhci_qh *control_qh = cntl->control_qh;
+    pipe->qh.link = control_qh->link;
+    barrier();
+    control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
+    if (eptype == USB_ENDPOINT_XFER_CONTROL)
+        cntl->control_qh = &pipe->qh;
+    return &pipe->pipe;
+}
+
+static int
+wait_pipe(struct uhci_pipe *pipe, int timeout)
+{
+    u32 end = timer_calc(timeout);
+    for (;;) {
+        u32 el_link = GET_LOWFLAT(pipe->qh.element);
+        if (el_link & UHCI_PTR_TERM)
+            return 0;
+        if (timer_check(end)) {
+            warn_timeout();
+            u16 iobase = GET_LOWFLAT(pipe->iobase);
+            struct uhci_td *td = (void*)(el_link & ~UHCI_PTR_BITS);
+            dprintf(1, "Timeout on wait_pipe %p (td=%p s=%x c=%x/%x)\n"
+                    , pipe, (void*)el_link, GET_LOWFLAT(td->status)
+                    , inw(iobase + USBCMD)
+                    , inw(iobase + USBSTS));
+            SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM);
+            uhci_waittick(iobase);
+            return -1;
+        }
+        yield();
+    }
+}
+
+static int
+wait_td(struct uhci_td *td)
+{
+    u32 end = timer_calc(5000); // XXX - lookup real time.
+    u32 status;
+    for (;;) {
+        status = td->status;
+        if (!(status & TD_CTRL_ACTIVE))
+            break;
+        if (timer_check(end)) {
+            warn_timeout();
+            return -1;
+        }
+        yield();
+    }
+    if (status & TD_CTRL_ANY_ERROR) {
+        dprintf(1, "wait_td error - status=%x\n", status);
+        return -2;
+    }
+    return 0;
+}
+
+int
+uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+             , void *data, int datasize)
+{
+    ASSERT32FLAT();
+    if (! CONFIG_USB_UHCI)
+        return -1;
+    dprintf(5, "uhci_control %p\n", p);
+    struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
+
+    int maxpacket = pipe->pipe.maxpacket;
+    int lowspeed = pipe->pipe.speed;
+    int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7);
+
+    // Setup transfer descriptors
+    int count = 2 + DIV_ROUND_UP(datasize, maxpacket);
+    struct uhci_td *tds = malloc_tmphigh(sizeof(*tds) * count);
+    if (!tds) {
+        warn_noalloc();
+        return -1;
+    }
+
+    tds[0].link = (u32)&tds[1] | UHCI_PTR_DEPTH;
+    tds[0].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
+                     | TD_CTRL_ACTIVE);
+    tds[0].token = (uhci_explen(cmdsize) | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
+                    | USB_PID_SETUP);
+    tds[0].buffer = (void*)cmd;
+    int toggle = TD_TOKEN_TOGGLE;
+    int i;
+    for (i=1; i<count-1; i++) {
+        tds[i].link = (u32)&tds[i+1] | UHCI_PTR_DEPTH;
+        tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
+                         | TD_CTRL_ACTIVE);
+        int len = (i == count-2 ? (datasize - (i-1)*maxpacket) : maxpacket);
+        tds[i].token = (uhci_explen(len) | toggle
+                        | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
+                        | (dir ? USB_PID_IN : USB_PID_OUT));
+        tds[i].buffer = data + (i-1) * maxpacket;
+        toggle ^= TD_TOKEN_TOGGLE;
+    }
+    tds[i].link = UHCI_PTR_TERM;
+    tds[i].status = (uhci_maxerr(0) | (lowspeed ? TD_CTRL_LS : 0)
+                     | TD_CTRL_ACTIVE);
+    tds[i].token = (uhci_explen(0) | TD_TOKEN_TOGGLE
+                    | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
+                    | (dir ? USB_PID_OUT : USB_PID_IN));
+    tds[i].buffer = 0;
+
+    // Transfer data
+    barrier();
+    pipe->qh.element = (u32)&tds[0];
+    int ret = wait_pipe(pipe, 500);
+    free(tds);
+    return ret;
+}
+
+#define STACKTDS 4
+#define TDALIGN 16
+
+int
+uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
+{
+    if (! CONFIG_USB_UHCI)
+        return -1;
+    struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
+    dprintf(7, "uhci_send_bulk qh=%p dir=%d data=%p size=%d\n"
+            , &pipe->qh, dir, data, datasize);
+    int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
+    int lowspeed = GET_LOWFLAT(pipe->pipe.speed);
+    int devaddr = (GET_LOWFLAT(pipe->pipe.devaddr)
+                   | (GET_LOWFLAT(pipe->pipe.ep) << 7));
+    int toggle = GET_LOWFLAT(pipe->toggle) ? TD_TOKEN_TOGGLE : 0;
+
+    // Allocate 4 tds on stack (16byte aligned)
+    u8 tdsbuf[sizeof(struct uhci_td) * STACKTDS + TDALIGN - 1];
+    struct uhci_td *tds = (void*)ALIGN((u32)tdsbuf, TDALIGN);
+    memset(tds, 0, sizeof(*tds) * STACKTDS);
+
+    // Enable tds
+    barrier();
+    SET_LOWFLAT(pipe->qh.element, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
+
+    int tdpos = 0;
+    while (datasize) {
+        struct uhci_td *td = &tds[tdpos++ % STACKTDS];
+        int ret = wait_td(td);
+        if (ret)
+            goto fail;
+
+        int transfer = datasize;
+        if (transfer > maxpacket)
+            transfer = maxpacket;
+        struct uhci_td *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
+                                                 , &tds[tdpos % STACKTDS]);
+        td->link = (transfer==datasize ? UHCI_PTR_TERM : (u32)nexttd_fl);
+        td->token = (uhci_explen(transfer) | toggle
+                     | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
+                     | (dir ? USB_PID_IN : USB_PID_OUT));
+        td->buffer = data;
+        barrier();
+        td->status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
+                      | TD_CTRL_ACTIVE);
+        toggle ^= TD_TOKEN_TOGGLE;
+
+        data += transfer;
+        datasize -= transfer;
+    }
+    SET_LOWFLAT(pipe->toggle, !!toggle);
+    return wait_pipe(pipe, 5000);
+fail:
+    dprintf(1, "uhci_send_bulk failed\n");
+    SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM);
+    uhci_waittick(GET_LOWFLAT(pipe->iobase));
+    return -1;
+}
+
+int
+uhci_poll_intr(struct usb_pipe *p, void *data)
+{
+    ASSERT16();
+    if (! CONFIG_USB_UHCI)
+        return -1;
+
+    struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
+    struct uhci_td *td = GET_LOWFLAT(pipe->next_td);
+    u32 status = GET_LOWFLAT(td->status);
+    u32 token = GET_LOWFLAT(td->token);
+    if (status & TD_CTRL_ACTIVE)
+        // No intrs found.
+        return -1;
+    // XXX - check for errors.
+
+    // Copy data.
+    void *tddata = GET_LOWFLAT(td->buffer);
+    memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata)
+               , uhci_expected_length(token));
+
+    // Reenable this td.
+    struct uhci_td *next = (void*)(GET_LOWFLAT(td->link) & ~UHCI_PTR_BITS);
+    SET_LOWFLAT(pipe->next_td, next);
+    barrier();
+    SET_LOWFLAT(td->status, (uhci_maxerr(0) | (status & TD_CTRL_LS)
+                             | TD_CTRL_ACTIVE));
+
+    return 0;
+}
diff --git a/src/hw/usb-uhci.h b/src/hw/usb-uhci.h
new file mode 100644 (file)
index 0000000..b83c487
--- /dev/null
@@ -0,0 +1,128 @@
+#ifndef __USB_UHCI_H
+#define __USB_UHCI_H
+
+// usb-uhci.c
+void uhci_setup(struct pci_device *pci, int busid);
+struct usbdevice_s;
+struct usb_endpoint_descriptor;
+struct usb_pipe *uhci_alloc_pipe(struct usbdevice_s *usbdev
+                                 , struct usb_endpoint_descriptor *epdesc);
+struct usb_pipe;
+int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+                 , void *data, int datasize);
+int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
+int uhci_poll_intr(struct usb_pipe *p, void *data);
+
+
+/****************************************************************
+ * uhci structs and flags
+ ****************************************************************/
+
+/* USB port status and control registers */
+#define USBPORTSC1      16
+#define USBPORTSC2      18
+#define   USBPORTSC_CCS         0x0001  /* Current Connect Status
+                                         * ("device present") */
+#define   USBPORTSC_CSC         0x0002  /* Connect Status Change */
+#define   USBPORTSC_PE          0x0004  /* Port Enable */
+#define   USBPORTSC_PEC         0x0008  /* Port Enable Change */
+#define   USBPORTSC_DPLUS       0x0010  /* D+ high (line status) */
+#define   USBPORTSC_DMINUS      0x0020  /* D- high (line status) */
+#define   USBPORTSC_RD          0x0040  /* Resume Detect */
+#define   USBPORTSC_RES1        0x0080  /* reserved, always 1 */
+#define   USBPORTSC_LSDA        0x0100  /* Low Speed Device Attached */
+#define   USBPORTSC_PR          0x0200  /* Port Reset */
+
+/* Legacy support register */
+#define USBLEGSUP               0xc0
+#define   USBLEGSUP_RWC         0x8f00  /* the R/WC bits */
+
+/* Command register */
+#define USBCMD          0
+#define   USBCMD_RS             0x0001  /* Run/Stop */
+#define   USBCMD_HCRESET        0x0002  /* Host reset */
+#define   USBCMD_GRESET         0x0004  /* Global reset */
+#define   USBCMD_EGSM           0x0008  /* Global Suspend Mode */
+#define   USBCMD_FGR            0x0010  /* Force Global Resume */
+#define   USBCMD_SWDBG          0x0020  /* SW Debug mode */
+#define   USBCMD_CF             0x0040  /* Config Flag (sw only) */
+#define   USBCMD_MAXP           0x0080  /* Max Packet (0 = 32, 1 = 64) */
+
+/* Status register */
+#define USBSTS          2
+#define   USBSTS_USBINT         0x0001  /* Interrupt due to IOC */
+#define   USBSTS_ERROR          0x0002  /* Interrupt due to error */
+#define   USBSTS_RD             0x0004  /* Resume Detect */
+#define   USBSTS_HSE            0x0008  /* Host System Error: PCI problems */
+#define   USBSTS_HCPE           0x0010  /* Host Controller Process Error:
+                                         * the schedule is buggy */
+#define   USBSTS_HCH            0x0020  /* HC Halted */
+
+/* Interrupt enable register */
+#define USBINTR         4
+#define   USBINTR_TIMEOUT       0x0001  /* Timeout/CRC error enable */
+#define   USBINTR_RESUME        0x0002  /* Resume interrupt enable */
+#define   USBINTR_IOC           0x0004  /* Interrupt On Complete enable */
+#define   USBINTR_SP            0x0008  /* Short packet interrupt enable */
+
+#define USBFRNUM        6
+#define USBFLBASEADD    8
+#define USBSOF          12
+#define   USBSOF_DEFAULT        64      /* Frame length is exactly 1 ms */
+
+struct uhci_framelist {
+    u32 links[1024];
+} PACKED;
+
+#define TD_CTRL_SPD             (1 << 29)       /* Short Packet Detect */
+#define TD_CTRL_C_ERR_MASK      (3 << 27)       /* Error Counter bits */
+#define TD_CTRL_C_ERR_SHIFT     27
+#define TD_CTRL_LS              (1 << 26)       /* Low Speed Device */
+#define TD_CTRL_IOS             (1 << 25)       /* Isochronous Select */
+#define TD_CTRL_IOC             (1 << 24)       /* Interrupt on Complete */
+#define TD_CTRL_ACTIVE          (1 << 23)       /* TD Active */
+#define TD_CTRL_STALLED         (1 << 22)       /* TD Stalled */
+#define TD_CTRL_DBUFERR         (1 << 21)       /* Data Buffer Error */
+#define TD_CTRL_BABBLE          (1 << 20)       /* Babble Detected */
+#define TD_CTRL_NAK             (1 << 19)       /* NAK Received */
+#define TD_CTRL_CRCTIMEO        (1 << 18)       /* CRC/Time Out Error */
+#define TD_CTRL_BITSTUFF        (1 << 17)       /* Bit Stuff Error */
+#define TD_CTRL_ACTLEN_MASK     0x7FF   /* actual length, encoded as n - 1 */
+
+#define TD_CTRL_ANY_ERROR       (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
+                                 TD_CTRL_BABBLE | TD_CTRL_CRCTIMEO | \
+                                 TD_CTRL_BITSTUFF)
+#define uhci_maxerr(err)                ((err) << TD_CTRL_C_ERR_SHIFT)
+
+#define TD_TOKEN_DEVADDR_SHIFT  8
+#define TD_TOKEN_TOGGLE_SHIFT   19
+#define TD_TOKEN_TOGGLE         (1 << 19)
+#define TD_TOKEN_EXPLEN_SHIFT   21
+#define TD_TOKEN_EXPLEN_MASK    0x7FF   /* expected length, encoded as n-1 */
+#define TD_TOKEN_PID_MASK       0xFF
+
+#define uhci_explen(len)        ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
+                                        TD_TOKEN_EXPLEN_SHIFT)
+
+#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
+                                        1) & TD_TOKEN_EXPLEN_MASK)
+
+struct uhci_td {
+    u32 link;
+    u32 status;
+    u32 token;
+    void *buffer;
+} PACKED;
+
+struct uhci_qh {
+    u32 link;
+    u32 element;
+} PACKED;
+
+#define UHCI_PTR_BITS           0x000F
+#define UHCI_PTR_TERM           0x0001
+#define UHCI_PTR_QH             0x0002
+#define UHCI_PTR_DEPTH          0x0004
+#define UHCI_PTR_BREADTH        0x0000
+
+#endif // usb-uhci.h
diff --git a/src/hw/usb.c b/src/hw/usb.c
new file mode 100644 (file)
index 0000000..42541ff
--- /dev/null
@@ -0,0 +1,461 @@
+// Main code for handling USB controllers and devices.
+//
+// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "pci_regs.h" // PCI_CLASS_REVISION
+#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI
+#include "usb-uhci.h" // uhci_setup
+#include "usb-ohci.h" // ohci_setup
+#include "usb-ehci.h" // ehci_setup
+#include "usb-hid.h" // usb_keyboard_setup
+#include "usb-hub.h" // usb_hub_setup
+#include "usb-msc.h" // usb_msc_setup
+#include "usb-uas.h" // usb_uas_setup
+#include "usb.h" // struct usb_s
+#include "biosvar.h" // GET_GLOBAL
+
+
+/****************************************************************
+ * Controller function wrappers
+ ****************************************************************/
+
+// Allocate an async pipe (control or bulk).
+struct usb_pipe *
+usb_alloc_pipe(struct usbdevice_s *usbdev
+               , struct usb_endpoint_descriptor *epdesc)
+{
+    switch (usbdev->hub->cntl->type) {
+    default:
+    case USB_TYPE_UHCI:
+        return uhci_alloc_pipe(usbdev, epdesc);
+    case USB_TYPE_OHCI:
+        return ohci_alloc_pipe(usbdev, epdesc);
+    case USB_TYPE_EHCI:
+        return ehci_alloc_pipe(usbdev, epdesc);
+    }
+}
+
+// Send a message on a control pipe using the default control descriptor.
+static int
+send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize
+             , void *data, int datasize)
+{
+    ASSERT32FLAT();
+    switch (pipe->type) {
+    default:
+    case USB_TYPE_UHCI:
+        return uhci_control(pipe, dir, cmd, cmdsize, data, datasize);
+    case USB_TYPE_OHCI:
+        return ohci_control(pipe, dir, cmd, cmdsize, data, datasize);
+    case USB_TYPE_EHCI:
+        return ehci_control(pipe, dir, cmd, cmdsize, data, datasize);
+    }
+}
+
+int
+usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize)
+{
+    switch (GET_LOWFLAT(pipe_fl->type)) {
+    default:
+    case USB_TYPE_UHCI:
+        return uhci_send_bulk(pipe_fl, dir, data, datasize);
+    case USB_TYPE_OHCI:
+        return ohci_send_bulk(pipe_fl, dir, data, datasize);
+    case USB_TYPE_EHCI:
+        return ehci_send_bulk(pipe_fl, dir, data, datasize);
+    }
+}
+
+int
+usb_poll_intr(struct usb_pipe *pipe_fl, void *data)
+{
+    switch (GET_LOWFLAT(pipe_fl->type)) {
+    default:
+    case USB_TYPE_UHCI:
+        return uhci_poll_intr(pipe_fl, data);
+    case USB_TYPE_OHCI:
+        return ohci_poll_intr(pipe_fl, data);
+    case USB_TYPE_EHCI:
+        return ehci_poll_intr(pipe_fl, data);
+    }
+}
+
+
+/****************************************************************
+ * Helper functions
+ ****************************************************************/
+
+// Send a message to the default control pipe of a device.
+int
+send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req
+                     , void *data)
+{
+    return send_control(pipe, req->bRequestType & USB_DIR_IN
+                        , req, sizeof(*req), data, req->wLength);
+}
+
+// Free an allocated control or bulk pipe.
+void
+free_pipe(struct usb_pipe *pipe)
+{
+    ASSERT32FLAT();
+    if (!pipe)
+        return;
+    // Add to controller's free list.
+    struct usb_s *cntl = pipe->cntl;
+    pipe->freenext = cntl->freelist;
+    cntl->freelist = pipe;
+}
+
+// Check for an available pipe on the freelist.
+struct usb_pipe *
+usb_getFreePipe(struct usb_s *cntl, u8 eptype)
+{
+    struct usb_pipe **pfree = &cntl->freelist;
+    for (;;) {
+        struct usb_pipe *pipe = *pfree;
+        if (!pipe)
+            return NULL;
+        if (pipe->eptype == eptype) {
+            *pfree = pipe->freenext;
+            return pipe;
+        }
+        pfree = &pipe->freenext;
+    }
+}
+
+// Fill "pipe" endpoint info from an endpoint descriptor.
+void
+usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev
+              , struct usb_endpoint_descriptor *epdesc)
+{
+    pipe->cntl = usbdev->hub->cntl;
+    pipe->type = usbdev->hub->cntl->type;
+    pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+    pipe->devaddr = usbdev->devaddr;
+    pipe->speed = usbdev->speed;
+    pipe->maxpacket = epdesc->wMaxPacketSize;
+    pipe->eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+}
+
+// Find the exponential period of the requested interrupt end point.
+int
+usb_getFrameExp(struct usbdevice_s *usbdev
+                , struct usb_endpoint_descriptor *epdesc)
+{
+    int period = epdesc->bInterval;
+    if (usbdev->speed != USB_HIGHSPEED)
+        return (period <= 0) ? 0 : __fls(period);
+    return (period <= 4) ? 0 : period - 4;
+}
+
+// Find the first endpoing of a given type in an interface description.
+struct usb_endpoint_descriptor *
+findEndPointDesc(struct usbdevice_s *usbdev, int type, int dir)
+{
+    struct usb_endpoint_descriptor *epdesc = (void*)&usbdev->iface[1];
+    for (;;) {
+        if ((void*)epdesc >= (void*)usbdev->iface + usbdev->imax
+            || epdesc->bDescriptorType == USB_DT_INTERFACE) {
+            return NULL;
+        }
+        if (epdesc->bDescriptorType == USB_DT_ENDPOINT
+            && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir
+            && (epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == type)
+            return epdesc;
+        epdesc = (void*)epdesc + epdesc->bLength;
+    }
+}
+
+// Get the first 8 bytes of the device descriptor.
+static int
+get_device_info8(struct usb_pipe *pipe, struct usb_device_descriptor *dinfo)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+    req.bRequest = USB_REQ_GET_DESCRIPTOR;
+    req.wValue = USB_DT_DEVICE<<8;
+    req.wIndex = 0;
+    req.wLength = 8;
+    return send_default_control(pipe, &req, dinfo);
+}
+
+static struct usb_config_descriptor *
+get_device_config(struct usb_pipe *pipe)
+{
+    struct usb_config_descriptor cfg;
+
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+    req.bRequest = USB_REQ_GET_DESCRIPTOR;
+    req.wValue = USB_DT_CONFIG<<8;
+    req.wIndex = 0;
+    req.wLength = sizeof(cfg);
+    int ret = send_default_control(pipe, &req, &cfg);
+    if (ret)
+        return NULL;
+
+    void *config = malloc_tmphigh(cfg.wTotalLength);
+    if (!config)
+        return NULL;
+    req.wLength = cfg.wTotalLength;
+    ret = send_default_control(pipe, &req, config);
+    if (ret)
+        return NULL;
+    //hexdump(config, cfg.wTotalLength);
+    return config;
+}
+
+static int
+set_configuration(struct usb_pipe *pipe, u16 val)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+    req.bRequest = USB_REQ_SET_CONFIGURATION;
+    req.wValue = val;
+    req.wIndex = 0;
+    req.wLength = 0;
+    return send_default_control(pipe, &req, NULL);
+}
+
+
+/****************************************************************
+ * Initialization and enumeration
+ ****************************************************************/
+
+// 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;
+
+    // Create a pipe for the default address.
+    struct usb_endpoint_descriptor epdesc = {
+        .wMaxPacketSize = 8,
+        .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+    };
+    usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc);
+    if (!usbdev->defpipe)
+        return -1;
+
+    msleep(USB_TIME_RSTRCY);
+
+    // 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 = send_default_control(usbdev->defpipe, &req, NULL);
+    free_pipe(usbdev->defpipe);
+    if (ret)
+        return -1;
+
+    msleep(USB_TIME_SETADDR_RECOVERY);
+
+    cntl->maxaddr++;
+    usbdev->devaddr = cntl->maxaddr;
+    usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc);
+    if (!usbdev->defpipe)
+        return -1;
+    return 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;
+    dprintf(3, "device rev=%04x cls=%02x sub=%02x proto=%02x size=%02x\n"
+            , dinfo.bcdUSB, dinfo.bDeviceClass, dinfo.bDeviceSubClass
+            , dinfo.bDeviceProtocol, dinfo.bMaxPacketSize0);
+    if (dinfo.bMaxPacketSize0 < 8 || dinfo.bMaxPacketSize0 > 64)
+        return 0;
+    free_pipe(usbdev->defpipe);
+    struct usb_endpoint_descriptor epdesc = {
+        .wMaxPacketSize = dinfo.bMaxPacketSize0,
+        .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+    };
+    usbdev->defpipe = usb_alloc_pipe(usbdev, &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;
+}
+
+static void
+usb_hub_port_setup(void *data)
+{
+    struct usbdevice_s *usbdev = data;
+    struct usbhub_s *hub = usbdev->hub;
+    u32 port = usbdev->port;
+
+    // Detect if device present (and possibly start reset)
+    int ret = hub->op->detect(hub, port);
+    if (ret)
+        // No device present
+        goto done;
+
+    // Reset port and determine device speed
+    mutex_lock(&hub->cntl->resetlock);
+    ret = hub->op->reset(hub, port);
+    if (ret < 0)
+        // Reset failed
+        goto resetfail;
+    usbdev->speed = ret;
+
+    // Set address of port
+    ret = usb_set_address(usbdev);
+    if (ret) {
+        hub->op->disconnect(hub, port);
+        goto resetfail;
+    }
+    mutex_unlock(&hub->cntl->resetlock);
+
+    // Configure the device
+    int count = configure_usb_device(usbdev);
+    free_pipe(usbdev->defpipe);
+    if (!count)
+        hub->op->disconnect(hub, port);
+    hub->devcount += count;
+done:
+    hub->threads--;
+    free(usbdev);
+    return;
+
+resetfail:
+    mutex_unlock(&hub->cntl->resetlock);
+    goto done;
+}
+
+void
+usb_enumerate(struct usbhub_s *hub)
+{
+    u32 portcount = hub->portcount;
+    hub->threads = portcount;
+
+    // Launch a thread for every port.
+    int i;
+    for (i=0; i<portcount; i++) {
+        struct usbdevice_s *usbdev = malloc_tmphigh(sizeof(*usbdev));
+        if (!usbdev) {
+            warn_noalloc();
+            continue;
+        }
+        memset(usbdev, 0, sizeof(*usbdev));
+        usbdev->hub = hub;
+        usbdev->port = i;
+        run_thread(usb_hub_port_setup, usbdev);
+    }
+
+    // Wait for threads to complete.
+    while (hub->threads)
+        yield();
+}
+
+void
+usb_setup(void)
+{
+    ASSERT32FLAT();
+    if (! CONFIG_USB)
+        return;
+
+    dprintf(3, "init usb\n");
+
+    // Look for USB controllers
+    int count = 0;
+    struct pci_device *pci, *ehcipci = NULL;
+    foreachpci(pci) {
+        if (pci->class != PCI_CLASS_SERIAL_USB)
+            continue;
+
+        if (!ehcipci || pci->bdf >= ehcipci->bdf) {
+            // Check to see if this device has an ehci controller
+            int found = 0;
+            ehcipci = pci;
+            for (;;) {
+                if (pci_classprog(ehcipci) == PCI_CLASS_SERIAL_USB_EHCI) {
+                    // Found an ehci controller.
+                    int ret = ehci_setup(ehcipci, count++, pci);
+                    if (ret)
+                        // Error
+                        break;
+                    count += found;
+                    pci = ehcipci;
+                    break;
+                }
+                if (ehcipci->class == PCI_CLASS_SERIAL_USB)
+                    found++;
+                ehcipci = container_of_or_null(
+                    ehcipci->node.next, struct pci_device, node);
+                if (!ehcipci || (pci_bdf_to_busdev(ehcipci->bdf)
+                                 != pci_bdf_to_busdev(pci->bdf)))
+                    // No ehci controller found.
+                    break;
+            }
+        }
+
+        if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI)
+            uhci_setup(pci, count++);
+        else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI)
+            ohci_setup(pci, count++);
+    }
+}
diff --git a/src/hw/usb.h b/src/hw/usb.h
new file mode 100644 (file)
index 0000000..a43e829
--- /dev/null
@@ -0,0 +1,241 @@
+// USB functions and data.
+#ifndef __USB_H
+#define __USB_H
+
+#include "util.h" // struct mutex_s
+
+// Information on a USB end point.
+struct usb_pipe {
+    union {
+        struct usb_s *cntl;
+        struct usb_pipe *freenext;
+    };
+    u8 type;
+    u8 ep;
+    u8 devaddr;
+    u8 speed;
+    u16 maxpacket;
+    u8 eptype;
+};
+
+// Common information for usb devices.
+struct usbdevice_s {
+    struct usbhub_s *hub;
+    struct usb_pipe *defpipe;
+    u32 port;
+    struct usb_config_descriptor *config;
+    struct usb_interface_descriptor *iface;
+    int imax;
+    u8 speed;
+    u8 devaddr;
+};
+
+// Common information for usb controllers.
+struct usb_s {
+    struct usb_pipe *freelist;
+    struct mutex_s resetlock;
+    struct pci_device *pci;
+    int busid;
+    u8 type;
+    u8 maxaddr;
+};
+
+// Information for enumerating USB hubs
+struct usbhub_s {
+    struct usbhub_op_s *op;
+    struct usbdevice_s *usbdev;
+    struct usb_s *cntl;
+    struct mutex_s lock;
+    u32 powerwait;
+    u32 port;
+    u32 threads;
+    u32 portcount;
+    u32 devcount;
+};
+
+// Hub callback (32bit) info
+struct usbhub_op_s {
+    int (*detect)(struct usbhub_s *hub, u32 port);
+    int (*reset)(struct usbhub_s *hub, u32 port);
+    void (*disconnect)(struct usbhub_s *hub, u32 port);
+};
+
+#define USB_TYPE_UHCI 1
+#define USB_TYPE_OHCI 2
+#define USB_TYPE_EHCI 3
+
+#define USB_FULLSPEED 0
+#define USB_LOWSPEED  1
+#define USB_HIGHSPEED 2
+
+#define USB_MAXADDR 127
+
+
+/****************************************************************
+ * usb structs and flags
+ ****************************************************************/
+
+// USB mandated timings (in ms)
+#define USB_TIME_SIGATT 100
+#define USB_TIME_ATTDB  100
+#define USB_TIME_DRST   10
+#define USB_TIME_DRSTR  50
+#define USB_TIME_RSTRCY 10
+
+#define USB_TIME_SETADDR_RECOVERY 2
+
+#define USB_PID_OUT                     0xe1
+#define USB_PID_IN                      0x69
+#define USB_PID_SETUP                   0x2d
+
+#define USB_DIR_OUT                     0               /* to device */
+#define USB_DIR_IN                      0x80            /* to host */
+
+#define USB_TYPE_MASK                   (0x03 << 5)
+#define USB_TYPE_STANDARD               (0x00 << 5)
+#define USB_TYPE_CLASS                  (0x01 << 5)
+#define USB_TYPE_VENDOR                 (0x02 << 5)
+#define USB_TYPE_RESERVED               (0x03 << 5)
+
+#define USB_RECIP_MASK                  0x1f
+#define USB_RECIP_DEVICE                0x00
+#define USB_RECIP_INTERFACE             0x01
+#define USB_RECIP_ENDPOINT              0x02
+#define USB_RECIP_OTHER                 0x03
+
+#define USB_REQ_GET_STATUS              0x00
+#define USB_REQ_CLEAR_FEATURE           0x01
+#define USB_REQ_SET_FEATURE             0x03
+#define USB_REQ_SET_ADDRESS             0x05
+#define USB_REQ_GET_DESCRIPTOR          0x06
+#define USB_REQ_SET_DESCRIPTOR          0x07
+#define USB_REQ_GET_CONFIGURATION       0x08
+#define USB_REQ_SET_CONFIGURATION       0x09
+#define USB_REQ_GET_INTERFACE           0x0A
+#define USB_REQ_SET_INTERFACE           0x0B
+#define USB_REQ_SYNCH_FRAME             0x0C
+
+struct usb_ctrlrequest {
+    u8 bRequestType;
+    u8 bRequest;
+    u16 wValue;
+    u16 wIndex;
+    u16 wLength;
+} PACKED;
+
+#define USB_DT_DEVICE                   0x01
+#define USB_DT_CONFIG                   0x02
+#define USB_DT_STRING                   0x03
+#define USB_DT_INTERFACE                0x04
+#define USB_DT_ENDPOINT                 0x05
+#define USB_DT_DEVICE_QUALIFIER         0x06
+#define USB_DT_OTHER_SPEED_CONFIG       0x07
+
+struct usb_device_descriptor {
+    u8  bLength;
+    u8  bDescriptorType;
+
+    u16 bcdUSB;
+    u8  bDeviceClass;
+    u8  bDeviceSubClass;
+    u8  bDeviceProtocol;
+    u8  bMaxPacketSize0;
+    u16 idVendor;
+    u16 idProduct;
+    u16 bcdDevice;
+    u8  iManufacturer;
+    u8  iProduct;
+    u8  iSerialNumber;
+    u8  bNumConfigurations;
+} PACKED;
+
+#define USB_CLASS_PER_INTERFACE         0       /* for DeviceClass */
+#define USB_CLASS_AUDIO                 1
+#define USB_CLASS_COMM                  2
+#define USB_CLASS_HID                   3
+#define USB_CLASS_PHYSICAL              5
+#define USB_CLASS_STILL_IMAGE           6
+#define USB_CLASS_PRINTER               7
+#define USB_CLASS_MASS_STORAGE          8
+#define USB_CLASS_HUB                   9
+
+struct usb_config_descriptor {
+    u8  bLength;
+    u8  bDescriptorType;
+
+    u16 wTotalLength;
+    u8  bNumInterfaces;
+    u8  bConfigurationValue;
+    u8  iConfiguration;
+    u8  bmAttributes;
+    u8  bMaxPower;
+} PACKED;
+
+struct usb_interface_descriptor {
+    u8  bLength;
+    u8  bDescriptorType;
+
+    u8  bInterfaceNumber;
+    u8  bAlternateSetting;
+    u8  bNumEndpoints;
+    u8  bInterfaceClass;
+    u8  bInterfaceSubClass;
+    u8  bInterfaceProtocol;
+    u8  iInterface;
+} PACKED;
+
+struct usb_endpoint_descriptor {
+    u8  bLength;
+    u8  bDescriptorType;
+
+    u8  bEndpointAddress;
+    u8  bmAttributes;
+    u16 wMaxPacketSize;
+    u8  bInterval;
+} PACKED;
+
+#define USB_ENDPOINT_NUMBER_MASK        0x0f    /* in bEndpointAddress */
+#define USB_ENDPOINT_DIR_MASK           0x80
+
+#define USB_ENDPOINT_XFERTYPE_MASK      0x03    /* in bmAttributes */
+#define USB_ENDPOINT_XFER_CONTROL       0
+#define USB_ENDPOINT_XFER_ISOC          1
+#define USB_ENDPOINT_XFER_BULK          2
+#define USB_ENDPOINT_XFER_INT           3
+#define USB_ENDPOINT_MAX_ADJUSTABLE     0x80
+
+
+/****************************************************************
+ * usb mass storage flags
+ ****************************************************************/
+
+#define US_SC_ATAPI_8020   0x02
+#define US_SC_ATAPI_8070   0x05
+#define US_SC_SCSI         0x06
+
+#define US_PR_BULK         0x50  /* bulk-only transport */
+#define US_PR_UAS          0x62  /* usb attached scsi   */
+
+/****************************************************************
+ * function defs
+ ****************************************************************/
+
+// usb.c
+struct usb_pipe *usb_alloc_pipe(struct usbdevice_s *usbdev
+                                , struct usb_endpoint_descriptor *epdesc);
+int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize);
+int usb_poll_intr(struct usb_pipe *pipe, void *data);
+int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req
+                         , void *data);
+void free_pipe(struct usb_pipe *pipe);
+struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype);
+void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev
+                   , struct usb_endpoint_descriptor *epdesc);
+int usb_getFrameExp(struct usbdevice_s *usbdev
+                    , struct usb_endpoint_descriptor *epdesc);
+struct usb_endpoint_descriptor *findEndPointDesc(struct usbdevice_s *usbdev
+                                                 , int type, int dir);
+void usb_enumerate(struct usbhub_s *hub);
+void usb_setup(void);
+
+#endif // usb.h
diff --git a/src/hw/virtio-blk.c b/src/hw/virtio-blk.c
new file mode 100644 (file)
index 0000000..6c0cd74
--- /dev/null
@@ -0,0 +1,174 @@
+// Virtio block boot support.
+//
+// Copyright (C) 2010 Red Hat Inc.
+//
+// Authors:
+//  Gleb Natapov <gnatapov@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "boot.h" // boot_add_hd
+#include "virtio-pci.h"
+#include "virtio-ring.h"
+#include "virtio-blk.h"
+#include "disk.h"
+
+struct virtiodrive_s {
+    struct drive_s drive;
+    struct vring_virtqueue *vq;
+    u16 ioaddr;
+};
+
+static int
+virtio_blk_op(struct disk_op_s *op, int write)
+{
+    struct virtiodrive_s *vdrive_g =
+        container_of(op->drive_g, struct virtiodrive_s, drive);
+    struct vring_virtqueue *vq = GET_GLOBAL(vdrive_g->vq);
+    struct virtio_blk_outhdr hdr = {
+        .type = write ? VIRTIO_BLK_T_OUT : VIRTIO_BLK_T_IN,
+        .ioprio = 0,
+        .sector = op->lba,
+    };
+    u8 status = VIRTIO_BLK_S_UNSUPP;
+    struct vring_list sg[] = {
+        {
+            .addr       = MAKE_FLATPTR(GET_SEG(SS), &hdr),
+            .length     = sizeof(hdr),
+        },
+        {
+            .addr       = op->buf_fl,
+            .length     = GET_GLOBAL(vdrive_g->drive.blksize) * op->count,
+        },
+        {
+            .addr       = MAKE_FLATPTR(GET_SEG(SS), &status),
+            .length     = sizeof(status),
+        },
+    };
+
+    /* Add to virtqueue and kick host */
+    if (write)
+        vring_add_buf(vq, sg, 2, 1, 0, 0);
+    else
+        vring_add_buf(vq, sg, 1, 2, 0, 0);
+    vring_kick(GET_GLOBAL(vdrive_g->ioaddr), vq, 1);
+
+    /* Wait for reply */
+    while (!vring_more_used(vq))
+        usleep(5);
+
+    /* Reclaim virtqueue element */
+    vring_get_buf(vq, NULL);
+
+    /* Clear interrupt status register.  Avoid leaving interrupts stuck if
+     * VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised.
+     */
+    vp_get_isr(GET_GLOBAL(vdrive_g->ioaddr));
+
+    return status == VIRTIO_BLK_S_OK ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
+}
+
+int
+process_virtio_blk_op(struct disk_op_s *op)
+{
+    if (! CONFIG_VIRTIO_BLK)
+        return 0;
+    switch (op->command) {
+    case CMD_READ:
+        return virtio_blk_op(op, 0);
+    case CMD_WRITE:
+        return virtio_blk_op(op, 1);
+    case CMD_FORMAT:
+    case CMD_RESET:
+    case CMD_ISREADY:
+    case CMD_VERIFY:
+    case CMD_SEEK:
+        return DISK_RET_SUCCESS;
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
+
+static void
+init_virtio_blk(struct pci_device *pci)
+{
+    u16 bdf = pci->bdf;
+    dprintf(1, "found virtio-blk at %x:%x\n", pci_bdf_to_bus(bdf),
+            pci_bdf_to_dev(bdf));
+    struct virtiodrive_s *vdrive_g = malloc_fseg(sizeof(*vdrive_g));
+    if (!vdrive_g) {
+        warn_noalloc();
+        return;
+    }
+    memset(vdrive_g, 0, sizeof(*vdrive_g));
+    vdrive_g->drive.type = DTYPE_VIRTIO_BLK;
+    vdrive_g->drive.cntl_id = bdf;
+
+    u16 ioaddr = vp_init_simple(bdf);
+    vdrive_g->ioaddr = ioaddr;
+    if (vp_find_vq(ioaddr, 0, &vdrive_g->vq) < 0 ) {
+        dprintf(1, "fail to find vq for virtio-blk %x:%x\n",
+                pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
+        goto fail;
+    }
+
+    struct virtio_blk_config cfg;
+    vp_get(ioaddr, 0, &cfg, sizeof(cfg));
+
+    u32 f = vp_get_features(ioaddr);
+    vdrive_g->drive.blksize = (f & (1 << VIRTIO_BLK_F_BLK_SIZE)) ?
+        cfg.blk_size : DISK_SECTOR_SIZE;
+
+    vdrive_g->drive.sectors = cfg.capacity;
+    dprintf(3, "virtio-blk %x:%x blksize=%d sectors=%u\n",
+            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
+            vdrive_g->drive.blksize, (u32)vdrive_g->drive.sectors);
+
+    if (vdrive_g->drive.blksize != DISK_SECTOR_SIZE) {
+        dprintf(1, "virtio-blk %x:%x block size %d is unsupported\n",
+                pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
+                vdrive_g->drive.blksize);
+        goto fail;
+    }
+
+    vdrive_g->drive.pchs.cylinders = cfg.cylinders;
+    vdrive_g->drive.pchs.heads = cfg.heads;
+    vdrive_g->drive.pchs.spt = cfg.sectors;
+    char *desc = znprintf(MAXDESCSIZE, "Virtio disk PCI:%x:%x",
+                          pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
+
+    boot_add_hd(&vdrive_g->drive, desc, bootprio_find_pci_device(pci));
+
+    vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+                  VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
+    return;
+
+fail:
+    free(vdrive_g->vq);
+    free(vdrive_g);
+}
+
+void
+virtio_blk_setup(void)
+{
+    ASSERT32FLAT();
+    if (! CONFIG_VIRTIO_BLK)
+        return;
+
+    dprintf(3, "init virtio-blk\n");
+
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci->vendor != PCI_VENDOR_ID_REDHAT_QUMRANET
+            || pci->device != PCI_DEVICE_ID_VIRTIO_BLK)
+            continue;
+        init_virtio_blk(pci);
+    }
+}
diff --git a/src/hw/virtio-blk.h b/src/hw/virtio-blk.h
new file mode 100644 (file)
index 0000000..b233c74
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _VIRTIO_BLK_H
+#define _VIRTIO_BLK_H
+
+struct virtio_blk_config
+{
+    u64 capacity;
+    u32 size_max;
+    u32 seg_max;
+    u16 cylinders;
+    u8 heads;
+    u8 sectors;
+    u32 blk_size;
+    u8 physical_block_exp;
+    u8 alignment_offset;
+    u16 min_io_size;
+    u32 opt_io_size;
+} __attribute__((packed));
+
+#define VIRTIO_BLK_F_BLK_SIZE 6
+
+/* These two define direction. */
+#define VIRTIO_BLK_T_IN         0
+#define VIRTIO_BLK_T_OUT        1
+
+/* This is the first element of the read scatter-gather list. */
+struct virtio_blk_outhdr {
+    /* VIRTIO_BLK_T* */
+    u32 type;
+    /* io priority. */
+    u32 ioprio;
+    /* Sector (ie. 512 byte offset) */
+    u64 sector;
+};
+
+#define VIRTIO_BLK_S_OK         0
+#define VIRTIO_BLK_S_IOERR      1
+#define VIRTIO_BLK_S_UNSUPP     2
+
+struct disk_op_s;
+int process_virtio_blk_op(struct disk_op_s *op);
+void virtio_blk_setup(void);
+
+#endif /* _VIRTIO_BLK_H */
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
new file mode 100644 (file)
index 0000000..4b9ad0a
--- /dev/null
@@ -0,0 +1,94 @@
+/* virtio-pci.c - pci interface for virtio interface
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
+ *
+ * some parts from Linux Virtio PCI driver
+ *
+ *  Copyright IBM Corp. 2007
+ *  Authors: Anthony Liguori  <aliguori@us.ibm.com>
+ *
+ *  Adopted for Seabios: Gleb Natapov <gleb@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPLv3
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "virtio-ring.h"
+#include "virtio-pci.h"
+#include "config.h" // CONFIG_DEBUG_LEVEL
+#include "util.h" // dprintf
+#include "pci.h" // pci_config_readl
+#include "pci_regs.h" // PCI_BASE_ADDRESS_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;
+}
+
+u16 vp_init_simple(u16 bdf)
+{
+    u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) &
+        PCI_BASE_ADDRESS_IO_MASK;
+
+    vp_reset(ioaddr);
+    vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+                  VIRTIO_CONFIG_S_DRIVER );
+    return ioaddr;
+}
diff --git a/src/hw/virtio-pci.h b/src/hw/virtio-pci.h
new file mode 100644 (file)
index 0000000..e1d972d
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef _VIRTIO_PCI_H
+#define _VIRTIO_PCI_H
+
+#include "ioport.h" // inl
+
+/* A 32-bit r/o bitmask of the features supported by the host */
+#define VIRTIO_PCI_HOST_FEATURES        0
+
+/* A 32-bit r/w bitmask of features activated by the guest */
+#define VIRTIO_PCI_GUEST_FEATURES       4
+
+/* A 32-bit r/w PFN for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_PFN            8
+
+/* A 16-bit r/o queue size for the currently selected queue */
+#define VIRTIO_PCI_QUEUE_NUM            12
+
+/* A 16-bit r/w queue selector */
+#define VIRTIO_PCI_QUEUE_SEL            14
+
+/* A 16-bit r/w queue notifier */
+#define VIRTIO_PCI_QUEUE_NOTIFY         16
+
+/* An 8-bit device status register.  */
+#define VIRTIO_PCI_STATUS               18
+
+/* An 8-bit r/o interrupt status register.  Reading the value will return the
+ * current contents of the ISR and will also clear it.  This is effectively
+ * a read-and-acknowledge. */
+#define VIRTIO_PCI_ISR                  19
+
+/* The bit of the ISR which indicates a device configuration change. */
+#define VIRTIO_PCI_ISR_CONFIG           0x2
+
+/* The remaining space is defined by each driver as the per-driver
+ * configuration space */
+#define VIRTIO_PCI_CONFIG               20
+
+/* Virtio ABI version, this must match exactly */
+#define VIRTIO_PCI_ABI_VERSION          0
+
+static inline u32 vp_get_features(unsigned int ioaddr)
+{
+   return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES);
+}
+
+static inline void vp_set_features(unsigned int ioaddr, u32 features)
+{
+        outl(features, ioaddr + VIRTIO_PCI_GUEST_FEATURES);
+}
+
+static inline void vp_get(unsigned int ioaddr, unsigned offset,
+                     void *buf, unsigned len)
+{
+   u8 *ptr = buf;
+   unsigned i;
+
+   for (i = 0; i < len; i++)
+           ptr[i] = inb(ioaddr + VIRTIO_PCI_CONFIG + offset + i);
+}
+
+static inline u8 vp_get_status(unsigned int ioaddr)
+{
+   return inb(ioaddr + VIRTIO_PCI_STATUS);
+}
+
+static inline void vp_set_status(unsigned int ioaddr, u8 status)
+{
+   if (status == 0)        /* reset */
+           return;
+   outb(status, ioaddr + VIRTIO_PCI_STATUS);
+}
+
+static inline u8 vp_get_isr(unsigned int ioaddr)
+{
+   return inb(ioaddr + VIRTIO_PCI_ISR);
+}
+
+static inline void vp_reset(unsigned int ioaddr)
+{
+   outb(0, ioaddr + VIRTIO_PCI_STATUS);
+   (void)inb(ioaddr + VIRTIO_PCI_ISR);
+}
+
+static inline void vp_notify(unsigned int ioaddr, int queue_index)
+{
+   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
+}
+
+static inline void vp_del_vq(unsigned int ioaddr, int queue_index)
+{
+   /* select the queue */
+
+   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
+
+   /* deactivate the queue */
+
+   outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN);
+}
+
+struct vring_virtqueue;
+u16 vp_init_simple(u16 bdf);
+int vp_find_vq(unsigned int ioaddr, int queue_index,
+               struct vring_virtqueue **p_vq);
+#endif /* _VIRTIO_PCI_H_ */
diff --git a/src/hw/virtio-ring.c b/src/hw/virtio-ring.c
new file mode 100644 (file)
index 0000000..bddb090
--- /dev/null
@@ -0,0 +1,149 @@
+/* virtio-pci.c - virtio ring management
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
+ *
+ *  some parts from Linux Virtio Ring
+ *
+ *  Copyright Rusty Russell IBM Corporation 2007
+ *
+ *  Adopted for Seabios: Gleb Natapov <gleb@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPLv3
+ * See the COPYING file in the top-level directory.
+ *
+ *
+ */
+
+#include "virtio-ring.h"
+#include "virtio-pci.h"
+#include "biosvar.h" // GET_GLOBAL
+#include "util.h" // dprintf
+
+#define BUG() do {                                                      \
+            panic("BUG: failure at %d/%s()!\n", __LINE__, __func__);    \
+        } while (0)
+#define BUG_ON(condition) do { if (condition) BUG(); } while (0)
+
+/*
+ * vring_more_used
+ *
+ * is there some used buffers ?
+ *
+ */
+
+int vring_more_used(struct vring_virtqueue *vq)
+{
+    struct vring_used *used = GET_LOWFLAT(vq->vring.used);
+    int more = GET_LOWFLAT(vq->last_used_idx) != GET_LOWFLAT(used->idx);
+    /* Make sure ring reads are done after idx read above. */
+    smp_rmb();
+    return more;
+}
+
+/*
+ * vring_free
+ *
+ * put at the begin of the free list the current desc[head]
+ */
+
+void vring_detach(struct vring_virtqueue *vq, unsigned int head)
+{
+    struct vring *vr = &vq->vring;
+    struct vring_desc *desc = GET_LOWFLAT(vr->desc);
+    unsigned int i;
+
+    /* find end of given descriptor */
+
+    i = head;
+    while (GET_LOWFLAT(desc[i].flags) & VRING_DESC_F_NEXT)
+        i = GET_LOWFLAT(desc[i].next);
+
+    /* link it with free list and point to it */
+
+    SET_LOWFLAT(desc[i].next, GET_LOWFLAT(vq->free_head));
+    SET_LOWFLAT(vq->free_head, head);
+}
+
+/*
+ * vring_get_buf
+ *
+ * get a buffer from the used list
+ *
+ */
+
+int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
+{
+    struct vring *vr = &vq->vring;
+    struct vring_used_elem *elem;
+    struct vring_used *used = GET_LOWFLAT(vq->vring.used);
+    u32 id;
+    int ret;
+
+//    BUG_ON(!vring_more_used(vq));
+
+    elem = &used->ring[GET_LOWFLAT(vq->last_used_idx) % GET_LOWFLAT(vr->num)];
+    id = GET_LOWFLAT(elem->id);
+    if (len != NULL)
+        *len = GET_LOWFLAT(elem->len);
+
+    ret = GET_LOWFLAT(vq->vdata[id]);
+
+    vring_detach(vq, id);
+
+    SET_LOWFLAT(vq->last_used_idx, GET_LOWFLAT(vq->last_used_idx) + 1);
+
+    return ret;
+}
+
+void vring_add_buf(struct vring_virtqueue *vq,
+                   struct vring_list list[],
+                   unsigned int out, unsigned int in,
+                   int index, int num_added)
+{
+    struct vring *vr = &vq->vring;
+    int i, av, head, prev;
+    struct vring_desc *desc = GET_LOWFLAT(vr->desc);
+    struct vring_avail *avail = GET_LOWFLAT(vr->avail);
+
+    BUG_ON(out + in == 0);
+
+    prev = 0;
+    head = GET_LOWFLAT(vq->free_head);
+    for (i = head; out; i = GET_LOWFLAT(desc[i].next), out--) {
+        SET_LOWFLAT(desc[i].flags, VRING_DESC_F_NEXT);
+        SET_LOWFLAT(desc[i].addr, (u64)virt_to_phys(list->addr));
+        SET_LOWFLAT(desc[i].len, list->length);
+        prev = i;
+        list++;
+    }
+    for ( ; in; i = GET_LOWFLAT(desc[i].next), in--) {
+        SET_LOWFLAT(desc[i].flags, VRING_DESC_F_NEXT|VRING_DESC_F_WRITE);
+        SET_LOWFLAT(desc[i].addr, (u64)virt_to_phys(list->addr));
+        SET_LOWFLAT(desc[i].len, list->length);
+        prev = i;
+        list++;
+    }
+    SET_LOWFLAT(desc[prev].flags,
+                GET_LOWFLAT(desc[prev].flags) & ~VRING_DESC_F_NEXT);
+
+    SET_LOWFLAT(vq->free_head, i);
+
+    SET_LOWFLAT(vq->vdata[head], index);
+
+    av = (GET_LOWFLAT(avail->idx) + num_added) % GET_LOWFLAT(vr->num);
+    SET_LOWFLAT(avail->ring[av], head);
+}
+
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
+{
+    struct vring *vr = &vq->vring;
+    struct vring_avail *avail = GET_LOWFLAT(vr->avail);
+
+    /* Make sure idx update is done after ring write. */
+    smp_wmb();
+    SET_LOWFLAT(avail->idx, GET_LOWFLAT(avail->idx) + num_added);
+
+    vp_notify(ioaddr, GET_LOWFLAT(vq->queue_index));
+}
diff --git a/src/hw/virtio-ring.h b/src/hw/virtio-ring.h
new file mode 100644 (file)
index 0000000..b7a7aaf
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef _VIRTIO_RING_H
+#define _VIRTIO_RING_H
+
+#include "types.h" // u64
+#include "memmap.h" // PAGE_SIZE
+
+#define PAGE_SHIFT 12
+#define PAGE_MASK  (PAGE_SIZE-1)
+
+#define virt_to_phys(v) (unsigned long)(v)
+#define phys_to_virt(p) (void*)(p)
+/* Compiler barrier is enough as an x86 CPU does not reorder reads or writes */
+#define smp_rmb() barrier()
+#define smp_wmb() barrier()
+
+/* Status byte for guest to report progress, and synchronize features. */
+/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE     1
+/* We have found a driver for the device. */
+#define VIRTIO_CONFIG_S_DRIVER          2
+/* Driver has used its parts of the config, and is happy */
+#define VIRTIO_CONFIG_S_DRIVER_OK       4
+/* We've given up on this device. */
+#define VIRTIO_CONFIG_S_FAILED          0x80
+
+#define MAX_QUEUE_NUM      (128)
+
+#define VRING_DESC_F_NEXT  1
+#define VRING_DESC_F_WRITE 2
+
+#define VRING_AVAIL_F_NO_INTERRUPT 1
+
+#define VRING_USED_F_NO_NOTIFY     1
+
+struct vring_desc
+{
+   u64 addr;
+   u32 len;
+   u16 flags;
+   u16 next;
+};
+
+struct vring_avail
+{
+   u16 flags;
+   u16 idx;
+   u16 ring[0];
+};
+
+struct vring_used_elem
+{
+   u32 id;
+   u32 len;
+};
+
+struct vring_used
+{
+   u16 flags;
+   u16 idx;
+   struct vring_used_elem ring[];
+};
+
+struct vring {
+   unsigned int num;
+   struct vring_desc *desc;
+   struct vring_avail *avail;
+   struct vring_used *used;
+};
+
+#define vring_size(num) \
+   (((((sizeof(struct vring_desc) * num) + \
+      (sizeof(struct vring_avail) + sizeof(u16) * num)) \
+         + PAGE_MASK) & ~PAGE_MASK) + \
+         (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
+
+typedef unsigned char virtio_queue_t[vring_size(MAX_QUEUE_NUM)];
+
+struct vring_virtqueue {
+   virtio_queue_t queue;
+   struct vring vring;
+   u16 free_head;
+   u16 last_used_idx;
+   u16 vdata[MAX_QUEUE_NUM];
+   /* PCI */
+   int queue_index;
+};
+
+struct vring_list {
+  char *addr;
+  unsigned int length;
+};
+
+static inline void vring_init(struct vring *vr,
+                         unsigned int num, unsigned char *queue)
+{
+   unsigned int i;
+   unsigned long pa;
+
+   ASSERT32FLAT();
+   vr->num = num;
+
+   /* physical address of desc must be page aligned */
+
+   pa = virt_to_phys(queue);
+   pa = (pa + PAGE_MASK) & ~PAGE_MASK;
+   vr->desc = phys_to_virt(pa);
+
+   vr->avail = (struct vring_avail *)&vr->desc[num];
+   /* disable interrupts */
+   vr->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+
+   /* physical address of used must be page aligned */
+
+   pa = virt_to_phys(&vr->avail->ring[num]);
+   pa = (pa + PAGE_MASK) & ~PAGE_MASK;
+   vr->used = phys_to_virt(pa);
+
+   for (i = 0; i < num - 1; i++)
+           vr->desc[i].next = i + 1;
+   vr->desc[i].next = 0;
+}
+
+int vring_more_used(struct vring_virtqueue *vq);
+void vring_detach(struct vring_virtqueue *vq, unsigned int head);
+int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
+void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
+                   unsigned int out, unsigned int in,
+                   int index, int num_added);
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added);
+
+#endif /* _VIRTIO_RING_H_ */
diff --git a/src/hw/virtio-scsi.c b/src/hw/virtio-scsi.c
new file mode 100644 (file)
index 0000000..4de1255
--- /dev/null
@@ -0,0 +1,182 @@
+// Virtio SCSI boot support.
+//
+// Copyright (C) 2012 Red Hat Inc.
+//
+// Authors:
+//  Paolo Bonzini <pbonzini@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "boot.h" // bootprio_find_scsi_device
+#include "blockcmd.h" // scsi_drive_setup
+#include "virtio-pci.h"
+#include "virtio-ring.h"
+#include "virtio-scsi.h"
+#include "disk.h"
+
+struct virtio_lun_s {
+    struct drive_s drive;
+    struct pci_device *pci;
+    struct vring_virtqueue *vq;
+    u16 ioaddr;
+    u16 target;
+    u16 lun;
+};
+
+static int
+virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op,
+                void *cdbcmd, u16 target, u16 lun, u16 blocksize)
+{
+    struct virtio_scsi_req_cmd req;
+    struct virtio_scsi_resp_cmd resp;
+    struct vring_list sg[3];
+
+    memset(&req, 0, sizeof(req));
+    req.lun[0] = 1;
+    req.lun[1] = target;
+    req.lun[2] = (lun >> 8) | 0x40;
+    req.lun[3] = (lun & 0xff);
+    memcpy(req.cdb, cdbcmd, 16);
+
+    u32 len = op->count * blocksize;
+    int datain = cdb_is_read(cdbcmd, blocksize);
+    int in_num = (datain ? 2 : 1);
+    int out_num = (len ? 3 : 2) - in_num;
+
+    sg[0].addr   = MAKE_FLATPTR(GET_SEG(SS), &req);
+    sg[0].length = sizeof(req);
+
+    sg[out_num].addr   = MAKE_FLATPTR(GET_SEG(SS), &resp);
+    sg[out_num].length = sizeof(resp);
+
+    if (len) {
+        int data_idx = (datain ? 2 : 1);
+        sg[data_idx].addr   = op->buf_fl;
+        sg[data_idx].length = len;
+    }
+
+    /* Add to virtqueue and kick host */
+    vring_add_buf(vq, sg, out_num, in_num, 0, 0);
+    vring_kick(ioaddr, vq, 1);
+
+    /* Wait for reply */
+    while (!vring_more_used(vq))
+        usleep(5);
+
+    /* Reclaim virtqueue element */
+    vring_get_buf(vq, NULL);
+
+    /* Clear interrupt status register.  Avoid leaving interrupts stuck if
+     * VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised.
+     */
+    vp_get_isr(ioaddr);
+
+    if (resp.response == VIRTIO_SCSI_S_OK && resp.status == 0) {
+        return DISK_RET_SUCCESS;
+    }
+    return DISK_RET_EBADTRACK;
+}
+
+int
+virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+    struct virtio_lun_s *vlun =
+        container_of(op->drive_g, struct virtio_lun_s, drive);
+
+    return virtio_scsi_cmd(GET_GLOBAL(vlun->ioaddr),
+                           GET_GLOBAL(vlun->vq), op, cdbcmd,
+                           GET_GLOBAL(vlun->target), GET_GLOBAL(vlun->lun),
+                           blocksize);
+}
+
+static int
+virtio_scsi_add_lun(struct pci_device *pci, u16 ioaddr,
+                    struct vring_virtqueue *vq, u16 target, u16 lun)
+{
+    struct virtio_lun_s *vlun = malloc_fseg(sizeof(*vlun));
+    if (!vlun) {
+        warn_noalloc();
+        return -1;
+    }
+    memset(vlun, 0, sizeof(*vlun));
+    vlun->drive.type = DTYPE_VIRTIO_SCSI;
+    vlun->drive.cntl_id = pci->bdf;
+    vlun->pci = pci;
+    vlun->ioaddr = ioaddr;
+    vlun->vq = vq;
+    vlun->target = target;
+    vlun->lun = lun;
+
+    int prio = bootprio_find_scsi_device(pci, target, lun);
+    int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio);
+    if (ret)
+        goto fail;
+    return 0;
+
+fail:
+    free(vlun);
+    return -1;
+}
+
+static int
+virtio_scsi_scan_target(struct pci_device *pci, u16 ioaddr,
+                        struct vring_virtqueue *vq, u16 target)
+{
+    /* TODO: send REPORT LUNS.  For now, only LUN 0 is recognized.  */
+    int ret = virtio_scsi_add_lun(pci, ioaddr, vq, target, 0);
+    return ret < 0 ? 0 : 1;
+}
+
+static void
+init_virtio_scsi(struct pci_device *pci)
+{
+    u16 bdf = pci->bdf;
+    dprintf(1, "found virtio-scsi at %x:%x\n", pci_bdf_to_bus(bdf),
+            pci_bdf_to_dev(bdf));
+    struct vring_virtqueue *vq = NULL;
+    u16 ioaddr = vp_init_simple(bdf);
+    if (vp_find_vq(ioaddr, 2, &vq) < 0 ) {
+        dprintf(1, "fail to find vq for virtio-scsi %x:%x\n",
+                pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
+        goto fail;
+    }
+
+    vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
+                  VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
+
+    int i, tot;
+    for (tot = 0, i = 0; i < 256; i++)
+        tot += virtio_scsi_scan_target(pci, ioaddr, vq, i);
+
+    if (!tot)
+        goto fail;
+
+    return;
+
+fail:
+    free(vq);
+}
+
+void
+virtio_scsi_setup(void)
+{
+    ASSERT32FLAT();
+    if (! CONFIG_VIRTIO_SCSI)
+        return;
+
+    dprintf(3, "init virtio-scsi\n");
+
+    struct pci_device *pci;
+    foreachpci(pci) {
+        if (pci->vendor != PCI_VENDOR_ID_REDHAT_QUMRANET
+            || pci->device != PCI_DEVICE_ID_VIRTIO_SCSI)
+            continue;
+        init_virtio_scsi(pci);
+    }
+}
diff --git a/src/hw/virtio-scsi.h b/src/hw/virtio-scsi.h
new file mode 100644 (file)
index 0000000..96c3701
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _VIRTIO_SCSI_H
+#define _VIRTIO_SCSI_H
+
+#define VIRTIO_SCSI_CDB_SIZE      32
+#define VIRTIO_SCSI_SENSE_SIZE    96
+
+struct virtio_scsi_config
+{
+    u32 num_queues;
+    u32 seg_max;
+    u32 max_sectors;
+    u32 cmd_per_lun;
+    u32 event_info_size;
+    u32 sense_size;
+    u32 cdb_size;
+    u16 max_channel;
+    u16 max_target;
+    u32 max_lun;
+} __attribute__((packed));
+
+/* This is the first element of the "out" scatter-gather list. */
+struct virtio_scsi_req_cmd {
+    u8 lun[8];
+    u64 id;
+    u8 task_attr;
+    u8 prio;
+    u8 crn;
+    char cdb[VIRTIO_SCSI_CDB_SIZE];
+} __attribute__((packed));
+
+/* This is the first element of the "in" scatter-gather list. */
+struct virtio_scsi_resp_cmd {
+    u32 sense_len;
+    u32 residual;
+    u16 status_qualifier;
+    u8 status;
+    u8 response;
+    u8 sense[VIRTIO_SCSI_SENSE_SIZE];
+} __attribute__((packed));
+
+#define VIRTIO_SCSI_S_OK            0
+
+struct disk_op_s;
+int virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+void virtio_scsi_setup(void);
+
+#endif /* _VIRTIO_SCSI_H */
index 05845e5028f6450962b568389b0fd615d0ce8573..2e2ced7aa58305abc378772fda28062de143aa52 100644 (file)
--- a/src/kbd.c
+++ b/src/kbd.c
@@ -9,8 +9,8 @@
 #include "util.h" // debug_enter
 #include "config.h" // CONFIG_*
 #include "bregs.h" // struct bregs
-#include "ps2port.h" // ps2_kbd_command
-#include "usb-hid.h" // usb_kbd_command
+#include "hw/ps2port.h" // ps2_kbd_command
+#include "hw/usb-hid.h" // usb_kbd_command
 
 // Bit definitions for BDA kbd_flag[012]
 #define KF0_RSHIFT       (1<<0)
diff --git a/src/lsi-scsi.c b/src/lsi-scsi.c
deleted file mode 100644 (file)
index 305610a..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-// (qemu-emulated) lsi53c895a boot support.
-//
-// Copyright (C) 2012 Red Hat Inc.
-//
-// Authors:
-//  Gerd Hoffmann <kraxel@redhat.com>
-//
-// based on virtio-scsi.c which is written by:
-//  Paolo Bonzini <pbonzini@redhat.com>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // foreachpci
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // GET_GLOBAL
-#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK
-#include "pci_regs.h" // PCI_VENDOR_ID
-#include "boot.h" // bootprio_find_scsi_device
-#include "blockcmd.h" // scsi_drive_setup
-#include "paravirt.h" // runningOnQEMU
-#include "disk.h"
-
-#define LSI_REG_DSTAT     0x0c
-#define LSI_REG_ISTAT0    0x14
-#define LSI_REG_DSP0      0x2c
-#define LSI_REG_DSP1      0x2d
-#define LSI_REG_DSP2      0x2e
-#define LSI_REG_DSP3      0x2f
-#define LSI_REG_SIST0     0x42
-#define LSI_REG_SIST1     0x43
-
-#define LSI_ISTAT0_DIP    0x01
-#define LSI_ISTAT0_SIP    0x02
-#define LSI_ISTAT0_INTF   0x04
-#define LSI_ISTAT0_CON    0x08
-#define LSI_ISTAT0_SEM    0x10
-#define LSI_ISTAT0_SIGP   0x20
-#define LSI_ISTAT0_SRST   0x40
-#define LSI_ISTAT0_ABRT   0x80
-
-struct lsi_lun_s {
-    struct drive_s drive;
-    struct pci_device *pci;
-    u32 iobase;
-    u8 target;
-    u8 lun;
-};
-
-static int
-lsi_scsi_cmd(struct lsi_lun_s *llun, struct disk_op_s *op,
-             void *cdbcmd, u16 target, u16 lun, u16 blocksize)
-{
-    u32 iobase = GET_GLOBAL(llun->iobase);
-    u32 dma = ((cdb_is_read(cdbcmd, blocksize) ? 0x01000000 : 0x00000000) |
-               (op->count * blocksize));
-    u8 msgout[] = {
-        0x80 | lun,                 // select lun
-        0x08,
-    };
-    u8 status = 0xff;
-    u8 msgin_tmp[2];
-    u8 msgin = 0xff;
-
-    u32 script[] = {
-        /* select target, send scsi command */
-        0x40000000 | target << 16,  // select target
-        0x00000000,
-        0x06000001,                 // msgout
-        (u32)MAKE_FLATPTR(GET_SEG(SS), &msgout),
-        0x02000010,                 // scsi command
-        (u32)MAKE_FLATPTR(GET_SEG(SS), cdbcmd),
-
-        /* handle disconnect */
-        0x87820000,                 // phase == msgin ?
-        0x00000018,
-        0x07000002,                 // msgin
-        (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin_tmp),
-        0x50000000,                 // re-select
-        0x00000000,
-        0x07000002,                 // msgin
-        (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin_tmp),
-
-        /* dma data, get status, raise irq */
-        dma,                        // dma data
-        (u32)op->buf_fl,
-        0x03000001,                 // status
-        (u32)MAKE_FLATPTR(GET_SEG(SS), &status),
-        0x07000001,                 // msgin
-        (u32)MAKE_FLATPTR(GET_SEG(SS), &msgin),
-        0x98080000,                 // dma irq
-        0x00000000,
-    };
-    u32 dsp = (u32)MAKE_FLATPTR(GET_SEG(SS), &script);
-
-    outb(dsp         & 0xff, iobase + LSI_REG_DSP0);
-    outb((dsp >>  8) & 0xff, iobase + LSI_REG_DSP1);
-    outb((dsp >> 16) & 0xff, iobase + LSI_REG_DSP2);
-    outb((dsp >> 24) & 0xff, iobase + LSI_REG_DSP3);
-
-    for (;;) {
-        u8 dstat = inb(iobase + LSI_REG_DSTAT);
-        u8 sist0 = inb(iobase + LSI_REG_SIST0);
-        u8 sist1 = inb(iobase + LSI_REG_SIST1);
-        if (sist0 || sist1) {
-            goto fail;
-        }
-        if (dstat & 0x04) {
-            break;
-        }
-        usleep(5);
-    }
-
-    if (msgin == 0 && status == 0) {
-        return DISK_RET_SUCCESS;
-    }
-
-fail:
-    return DISK_RET_EBADTRACK;
-}
-
-int
-lsi_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    if (!CONFIG_LSI_SCSI)
-        return DISK_RET_EBADTRACK;
-
-    struct lsi_lun_s *llun =
-        container_of(op->drive_g, struct lsi_lun_s, drive);
-
-    return lsi_scsi_cmd(llun, op, cdbcmd,
-                        GET_GLOBAL(llun->target), GET_GLOBAL(llun->lun),
-                        blocksize);
-}
-
-static int
-lsi_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
-{
-    struct lsi_lun_s *llun = malloc_fseg(sizeof(*llun));
-    if (!llun) {
-        warn_noalloc();
-        return -1;
-    }
-    memset(llun, 0, sizeof(*llun));
-    llun->drive.type = DTYPE_LSI_SCSI;
-    llun->drive.cntl_id = pci->bdf;
-    llun->pci = pci;
-    llun->target = target;
-    llun->lun = lun;
-    llun->iobase = iobase;
-
-    char *name = znprintf(16, "lsi %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(&llun->drive, name, prio);
-    free(name);
-    if (ret)
-        goto fail;
-    return 0;
-
-fail:
-    free(llun);
-    return -1;
-}
-
-static void
-lsi_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target)
-{
-    /* TODO: send REPORT LUNS.  For now, only LUN 0 is recognized.  */
-    lsi_scsi_add_lun(pci, iobase, target, 0);
-}
-
-static void
-init_lsi_scsi(struct pci_device *pci)
-{
-    u16 bdf = pci->bdf;
-    u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
-        & PCI_BASE_ADDRESS_IO_MASK;
-
-    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
-
-    dprintf(1, "found lsi53c895a at %02x:%02x.%x, io @ %x\n",
-            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
-            pci_bdf_to_fn(bdf), iobase);
-
-    // reset
-    outb(LSI_ISTAT0_SRST, iobase + LSI_REG_ISTAT0);
-
-    int i;
-    for (i = 0; i < 7; i++)
-        lsi_scsi_scan_target(pci, iobase, i);
-
-    return;
-}
-
-void
-lsi_scsi_setup(void)
-{
-    ASSERT32FLAT();
-    if (!CONFIG_LSI_SCSI || !runningOnQEMU())
-        return;
-
-    dprintf(3, "init lsi53c895a\n");
-
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci->vendor != PCI_VENDOR_ID_LSI_LOGIC
-            || pci->device != PCI_DEVICE_ID_LSI_53C895A)
-            continue;
-        init_lsi_scsi(pci);
-    }
-}
diff --git a/src/lsi-scsi.h b/src/lsi-scsi.h
deleted file mode 100644 (file)
index 9c5a9b2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __LSI_SCSI_H
-#define __LSI_SCSI_H
-
-struct disk_op_s;
-int lsi_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
-void lsi_scsi_setup(void);
-
-#endif /* __LSI_SCSI_H */
diff --git a/src/megasas.c b/src/megasas.c
deleted file mode 100644 (file)
index f4eeba0..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-// MegaRAID SAS boot support.
-//
-// Copyright (C) 2012 Hannes Reinecke, SUSE Linux Products GmbH
-//
-// Authors:
-//  Hannes Reinecke <hare@suse.de>
-//
-// based on virtio-scsi.c which is written by:
-//  Paolo Bonzini <pbonzini@redhat.com>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // foreachpci
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // GET_GLOBAL
-#include "pci_ids.h" // PCI_DEVICE_ID_XXX
-#include "pci_regs.h" // PCI_VENDOR_ID
-#include "boot.h" // bootprio_find_scsi_device
-#include "blockcmd.h" // scsi_drive_setup
-#include "disk.h"
-
-#define MFI_DB 0x0 // Doorbell
-#define MFI_OMSG0 0x18 // Outbound message 0
-#define MFI_IDB 0x20 // Inbound doorbell
-#define MFI_ODB 0x2c // Outbound doorbell
-#define MFI_IQP 0x40 // Inbound queue port
-#define MFI_OSP0 0xb0 // Outbound scratch pad0
-#define MFI_IQPL 0xc0 // Inbound queue port (low bytes)
-#define MFI_IQPH 0xc4 // Inbound queue port (high bytes)
-
-#define MFI_STATE_MASK                0xf0000000
-#define MFI_STATE_WAIT_HANDSHAKE      0x60000000
-#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000
-#define MFI_STATE_READY               0xb0000000
-#define MFI_STATE_OPERATIONAL         0xc0000000
-#define MFI_STATE_FAULT               0xf0000000
-
-/* MFI Commands */
-typedef enum {
-    MFI_CMD_INIT = 0x00,
-    MFI_CMD_LD_READ,
-    MFI_CMD_LD_WRITE,
-    MFI_CMD_LD_SCSI_IO,
-    MFI_CMD_PD_SCSI_IO,
-    MFI_CMD_DCMD,
-    MFI_CMD_ABORT,
-    MFI_CMD_SMP,
-    MFI_CMD_STP
-} mfi_cmd_t;
-
-struct megasas_cmd_frame {
-    u8 cmd;             /*00h */
-    u8 sense_len;       /*01h */
-    u8 cmd_status;      /*02h */
-    u8 scsi_status;     /*03h */
-
-    u8 target_id;       /*04h */
-    u8 lun;             /*05h */
-    u8 cdb_len;         /*06h */
-    u8 sge_count;       /*07h */
-
-    u32 context;        /*08h */
-    u32 context_64;     /*0Ch */
-
-    u16 flags;          /*10h */
-    u16 timeout;        /*12h */
-    u32 data_xfer_len;   /*14h */
-
-    union {
-        struct {
-            u32 opcode;       /*18h */
-            u8 mbox[12];      /*1Ch */
-            u32 sgl_addr;     /*28h */
-            u32 sgl_len;      /*32h */
-            u32 pad;          /*34h */
-        } dcmd;
-        struct {
-            u32 sense_buf_lo; /*18h */
-            u32 sense_buf_hi; /*1Ch */
-            u8 cdb[16];       /*20h */
-            u32 sgl_addr;     /*30h */
-            u32 sgl_len;      /*34h */
-        } pthru;
-        struct {
-            u8 pad[22];       /*18h */
-        } gen;
-    };
-} __attribute__ ((packed));
-
-struct mfi_ld_list_s {
-    u32     count;
-    u32     reserved_0;
-    struct {
-        u8          target;
-        u8          lun;
-        u16         seq;
-        u8          state;
-        u8          reserved_1[3];
-        u64         size;
-    } lds[64];
-} __attribute__ ((packed));
-
-#define MEGASAS_POLL_TIMEOUT 60000 // 60 seconds polling timeout
-
-struct megasas_lun_s {
-    struct drive_s drive;
-    struct pci_device *pci;
-    struct megasas_cmd_frame *frame;
-    u32 iobase;
-    u8 target;
-    u8 lun;
-};
-
-static int megasas_fire_cmd(u16 pci_id, u32 ioaddr,
-                            struct megasas_cmd_frame *frame)
-{
-    u32 frame_addr = (u32)frame;
-    int frame_count = 1;
-    u8 cmd_state;
-
-    dprintf(2, "Frame 0x%x\n", frame_addr);
-    if (pci_id == PCI_DEVICE_ID_LSI_SAS2004 ||
-        pci_id == PCI_DEVICE_ID_LSI_SAS2008) {
-        outl(0, ioaddr + MFI_IQPH);
-        outl(frame_addr | frame_count << 1 | 1, ioaddr + MFI_IQPL);
-    } else if (pci_id == PCI_DEVICE_ID_DELL_PERC5 ||
-               pci_id == PCI_DEVICE_ID_LSI_SAS1064R ||
-               pci_id == PCI_DEVICE_ID_LSI_VERDE_ZCR) {
-        outl(frame_addr >> 3 | frame_count, ioaddr + MFI_IQP);
-    } else {
-        outl(frame_addr | frame_count << 1 | 1, ioaddr + MFI_IQP);
-    }
-
-    u32 end = timer_calc(MEGASAS_POLL_TIMEOUT);
-    do {
-        for (;;) {
-            cmd_state = GET_LOWFLAT(frame->cmd_status);
-            if (cmd_state != 0xff)
-                break;
-            if (timer_check(end)) {
-                warn_timeout();
-                return -1;
-            }
-            yield();
-        }
-    } while (cmd_state == 0xff);
-
-    if (cmd_state == 0 || cmd_state == 0x2d)
-        return 0;
-    dprintf(1, "ERROR: Frame 0x%x, status 0x%x\n", frame_addr, cmd_state);
-    return -1;
-}
-
-int
-megasas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    struct megasas_lun_s *mlun =
-        container_of(op->drive_g, struct megasas_lun_s, drive);
-    u8 *cdb = cdbcmd;
-    struct megasas_cmd_frame *frame = GET_GLOBAL(mlun->frame);
-    u16 pci_id = GET_GLOBAL(mlun->pci->device);
-    int i;
-
-    if (!CONFIG_MEGASAS)
-        return DISK_RET_EBADTRACK;
-
-    memset_fl(frame, 0, sizeof(*frame));
-    SET_LOWFLAT(frame->cmd, MFI_CMD_LD_SCSI_IO);
-    SET_LOWFLAT(frame->cmd_status, 0xFF);
-    SET_LOWFLAT(frame->target_id, GET_GLOBAL(mlun->target));
-    SET_LOWFLAT(frame->lun, GET_GLOBAL(mlun->lun));
-    SET_LOWFLAT(frame->flags, 0x0001);
-    SET_LOWFLAT(frame->data_xfer_len, op->count * blocksize);
-    SET_LOWFLAT(frame->cdb_len, 16);
-
-    for (i = 0; i < 16; i++) {
-        SET_LOWFLAT(frame->pthru.cdb[i], cdb[i]);
-    }
-    dprintf(2, "pthru cmd 0x%x count %d bs %d\n",
-            cdb[0], op->count, blocksize);
-
-    if (op->count) {
-        SET_LOWFLAT(frame->pthru.sgl_addr, (u32)op->buf_fl);
-        SET_LOWFLAT(frame->pthru.sgl_len, op->count * blocksize);
-        SET_LOWFLAT(frame->sge_count, 1);
-    }
-    SET_LOWFLAT(frame->context, (u32)frame);
-
-    if (megasas_fire_cmd(pci_id, GET_GLOBAL(mlun->iobase), frame) == 0)
-        return DISK_RET_SUCCESS;
-
-    dprintf(2, "pthru cmd 0x%x failed\n", cdb[0]);
-    return DISK_RET_EBADTRACK;
-}
-
-static int
-megasas_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
-{
-    struct megasas_lun_s *mlun = malloc_fseg(sizeof(*mlun));
-    char *name;
-    int prio, ret = 0;
-
-    if (!mlun) {
-        warn_noalloc();
-        return -1;
-    }
-    memset(mlun, 0, sizeof(*mlun));
-    mlun->drive.type = DTYPE_MEGASAS;
-    mlun->drive.cntl_id = pci->bdf;
-    mlun->pci = pci;
-    mlun->target = target;
-    mlun->lun = lun;
-    mlun->iobase = iobase;
-    mlun->frame = memalign_low(256, sizeof(struct megasas_cmd_frame));
-    if (!mlun->frame) {
-        warn_noalloc();
-        free(mlun);
-        return -1;
-    }
-    name = znprintf(36, "MegaRAID SAS (PCI %02x:%02x.%x) LD %d:%d",
-                    pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
-                    pci_bdf_to_fn(pci->bdf), target, lun);
-    prio = bootprio_find_scsi_device(pci, target, lun);
-    ret = scsi_drive_setup(&mlun->drive, name, prio);
-    free(name);
-    if (ret) {
-        free(mlun->frame);
-        free(mlun);
-        ret = -1;
-    }
-
-    return ret;
-}
-
-static void megasas_scan_target(struct pci_device *pci, u32 iobase)
-{
-    struct mfi_ld_list_s ld_list;
-    struct megasas_cmd_frame *frame = memalign_tmp(256, sizeof(*frame));
-    int i;
-
-    memset(&ld_list, 0, sizeof(ld_list));
-    memset_fl(frame, 0, sizeof(*frame));
-
-    frame->cmd = MFI_CMD_DCMD;
-    frame->cmd_status = 0xFF;
-    frame->sge_count = 1;
-    frame->flags = 0x0011;
-    frame->data_xfer_len = sizeof(ld_list);
-    frame->dcmd.opcode = 0x03010000;
-    frame->dcmd.sgl_addr = (u32)MAKE_FLATPTR(GET_SEG(SS), &ld_list);
-    frame->dcmd.sgl_len = sizeof(ld_list);
-    frame->context = (u32)frame;
-
-    if (megasas_fire_cmd(pci->device, iobase, frame) == 0) {
-        dprintf(2, "%d LD found\n", ld_list.count);
-        for (i = 0; i < ld_list.count; i++) {
-            dprintf(2, "LD %d:%d state 0x%x\n",
-                    ld_list.lds[i].target, ld_list.lds[i].lun,
-                    ld_list.lds[i].state);
-            if (ld_list.lds[i].state != 0) {
-                megasas_add_lun(pci, iobase,
-                                ld_list.lds[i].target, ld_list.lds[i].lun);
-            }
-        }
-    }
-}
-
-static int megasas_transition_to_ready(struct pci_device *pci, u32 ioaddr)
-{
-    u32 fw_state = 0, new_state, mfi_flags = 0;
-
-    if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R ||
-        pci->device == PCI_DEVICE_ID_DELL_PERC5)
-        new_state = inl(ioaddr + MFI_OMSG0) & MFI_STATE_MASK;
-    else
-        new_state = inl(ioaddr + MFI_OSP0) & MFI_STATE_MASK;
-
-    while (fw_state != new_state) {
-        switch (new_state) {
-        case MFI_STATE_FAULT:
-            dprintf(1, "ERROR: fw in fault state\n");
-            return -1;
-            break;
-        case MFI_STATE_WAIT_HANDSHAKE:
-            mfi_flags = 0x08;
-            /* fallthrough */
-        case MFI_STATE_BOOT_MESSAGE_PENDING:
-            mfi_flags |= 0x10;
-            if (pci->device == PCI_DEVICE_ID_LSI_SAS2004 ||
-                pci->device == PCI_DEVICE_ID_LSI_SAS2008 ||
-                pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
-                pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
-                outl(ioaddr + MFI_DB, mfi_flags);
-            } else {
-                outl(ioaddr + MFI_IDB, mfi_flags);
-            }
-            break;
-        case MFI_STATE_OPERATIONAL:
-            mfi_flags = 0x07;
-            if (pci->device == PCI_DEVICE_ID_LSI_SAS2004 ||
-                pci->device == PCI_DEVICE_ID_LSI_SAS2008 ||
-                pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
-                pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
-                outl(ioaddr + MFI_DB, mfi_flags);
-                if (pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
-                    pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
-                    int j = 0;
-                    u32 doorbell;
-
-                    while (j < MEGASAS_POLL_TIMEOUT) {
-                        doorbell = inl(ioaddr + MFI_DB) & 1;
-                        if (!doorbell)
-                            break;
-                        msleep(20);
-                        j++;
-                    }
-                }
-            } else {
-                outw(ioaddr + MFI_IDB, mfi_flags);
-            }
-            break;
-        case MFI_STATE_READY:
-            dprintf(2, "MegaRAID SAS fw ready\n");
-            return 0;
-        }
-        // The current state should not last longer than poll timeout
-        u32 end = timer_calc(MEGASAS_POLL_TIMEOUT);
-        for (;;) {
-            if (timer_check(end)) {
-                break;
-            }
-            yield();
-            fw_state = new_state;
-            if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R ||
-                pci->device == PCI_DEVICE_ID_DELL_PERC5)
-                new_state = inl(ioaddr + MFI_OMSG0) & MFI_STATE_MASK;
-            else
-                new_state = inl(ioaddr + MFI_OSP0) & MFI_STATE_MASK;
-            if (new_state != fw_state) {
-                break;
-            }
-        }
-    }
-    dprintf(1, "ERROR: fw in state %x\n", new_state & MFI_STATE_MASK);
-    return -1;
-}
-
-static void
-init_megasas(struct pci_device *pci)
-{
-    u16 bdf = pci->bdf;
-    u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_2)
-        & PCI_BASE_ADDRESS_IO_MASK;
-
-    dprintf(1, "found MegaRAID SAS at %02x:%02x.%x, io @ %x\n",
-            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
-            pci_bdf_to_fn(bdf), iobase);
-
-    pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
-                     PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-    // reset
-    if (megasas_transition_to_ready(pci, iobase) == 0)
-        megasas_scan_target(pci, iobase);
-
-    return;
-}
-
-void
-megasas_setup(void)
-{
-    ASSERT32FLAT();
-    if (!CONFIG_MEGASAS)
-        return;
-
-    dprintf(3, "init megasas\n");
-
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci->vendor != PCI_VENDOR_ID_LSI_LOGIC &&
-            pci->vendor != PCI_VENDOR_ID_DELL)
-            continue;
-        if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R ||
-            pci->device == PCI_DEVICE_ID_LSI_SAS1078 ||
-            pci->device == PCI_DEVICE_ID_LSI_SAS1078DE ||
-            pci->device == PCI_DEVICE_ID_LSI_SAS2108 ||
-            pci->device == PCI_DEVICE_ID_LSI_SAS2108E ||
-            pci->device == PCI_DEVICE_ID_LSI_SAS2004 ||
-            pci->device == PCI_DEVICE_ID_LSI_SAS2008 ||
-            pci->device == PCI_DEVICE_ID_LSI_VERDE_ZCR ||
-            pci->device == PCI_DEVICE_ID_DELL_PERC5 ||
-            pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
-            pci->device == PCI_DEVICE_ID_LSI_SAS3108)
-            init_megasas(pci);
-    }
-}
diff --git a/src/megasas.h b/src/megasas.h
deleted file mode 100644 (file)
index 124042e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __MEGASAS_H
-#define __MEGASAS_H
-
-struct disk_op_s;
-int megasas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
-void megasas_setup(void);
-
-#endif /* __MEGASAS_H */
index c84cac82569d05591fc5b6d60483e9ed8894df6d..338c6073274c5adbabb9e0068b287563777ee8ad 100644 (file)
@@ -8,7 +8,7 @@
 #include "bregs.h" // struct bregs
 #include "biosvar.h" // GET_BDA
 #include "util.h" // debug_enter
-#include "pic.h" // enable_hwirq
+#include "hw/pic.h" // enable_hwirq
 
 
 /****************************************************************
index 5371cf63de0d1beabb37eb16a9d756a76c1a6777..5a7ae0a141f1287f3e6fb60a0149d603aeeb9c7c 100644 (file)
@@ -8,8 +8,8 @@
 #include "biosvar.h" // GET_EBDA
 #include "util.h" // dprintf
 #include "bregs.h" // struct bregs
-#include "ps2port.h" // ps2_mouse_command
-#include "usb-hid.h" // usb_mouse_command
+#include "hw/ps2port.h" // ps2_mouse_command
+#include "hw/usb-hid.h" // usb_mouse_command
 
 void
 mouse_init(void)
index 0413063db7ba95103446cb6a607542246062e359..2d128653f7edfcbcb5f0be6114d32367b6277d01 100644 (file)
@@ -8,8 +8,8 @@
 #include "util.h" // dprintf
 #include "config.h" // CONFIG_*
 #include "mptable.h" // MPTABLE_SIGNATURE
-#include "pci.h"
-#include "pci_regs.h"
+#include "hw/pci.h"
+#include "hw/pci_regs.h"
 
 void
 mptable_setup(void)
index 0f94c2c555d559cd436323a8f78d4a269a8d2118..001e2755918426b33ff47858e9d6d46f19603fbd 100644 (file)
@@ -6,7 +6,7 @@
 
 #include "util.h" // dprintf
 #include "config.h" // CONFIG_*
-#include "pci.h" // pcimem_start
+#include "hw/pci.h" // pcimem_start
 #include "paravirt.h" // RamSize
 
 #define MSR_MTRRcap                    0x000000fe
index ac92613b142777bc9568f2b4e5c6285c22bc501a..ffa426dcbeca898b4217383db138d5aae7c6d7eb 100644 (file)
@@ -9,9 +9,9 @@
 #include "farptr.h" // FLATPTR_TO_SEG
 #include "config.h" // CONFIG_*
 #include "util.h" // dprintf
-#include "pci.h" // foreachpci
-#include "pci_regs.h" // PCI_ROM_ADDRESS
-#include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA
+#include "hw/pci.h" // foreachpci
+#include "hw/pci_regs.h" // PCI_ROM_ADDRESS
+#include "hw/pci_ids.h" // PCI_CLASS_DISPLAY_VGA
 #include "boot.h" // IPL
 #include "optionroms.h" // struct rom_header
 
index d1a5d3e2f20bd739d0ec2acad42223c01a994f68..b1dd8b0cb727d4b010540dbd64336a30ca11908e 100644 (file)
 #include "paravirt.h" // qemu_cfg_preinit
 #include "smbios.h" // smbios_setup
 #include "memmap.h" // add_e820
-#include "cmos.h" // CMOS_*
+#include "hw/cmos.h" // CMOS_*
 #include "acpi.h" // acpi_setup
 #include "mptable.h" // mptable_setup
-#include "pci.h" // create_pirtable
+#include "hw/pci.h" // create_pirtable
 #include "xen.h" // xen_biostable_setup
 
 // Amount of continuous ram under 4Gig
diff --git a/src/pci.c b/src/pci.c
deleted file mode 100644 (file)
index dc62c5c..0000000
--- a/src/pci.c
+++ /dev/null
@@ -1,277 +0,0 @@
-// PCI config space access functions.
-//
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2002  MandrakeSoft S.A.
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "config.h" // CONFIG_*
-#include "pci.h" // pci_config_writel
-#include "ioport.h" // outl
-#include "util.h" // dprintf
-#include "farptr.h" // MAKE_FLATPTR
-#include "pci_regs.h" // PCI_VENDOR_ID
-#include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA
-
-void pci_config_writel(u16 bdf, u32 addr, u32 val)
-{
-    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
-    outl(val, PORT_PCI_DATA);
-}
-
-void pci_config_writew(u16 bdf, u32 addr, u16 val)
-{
-    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
-    outw(val, PORT_PCI_DATA + (addr & 2));
-}
-
-void pci_config_writeb(u16 bdf, u32 addr, u8 val)
-{
-    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
-    outb(val, PORT_PCI_DATA + (addr & 3));
-}
-
-u32 pci_config_readl(u16 bdf, u32 addr)
-{
-    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
-    return inl(PORT_PCI_DATA);
-}
-
-u16 pci_config_readw(u16 bdf, u32 addr)
-{
-    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
-    return inw(PORT_PCI_DATA + (addr & 2));
-}
-
-u8 pci_config_readb(u16 bdf, u32 addr)
-{
-    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
-    return inb(PORT_PCI_DATA + (addr & 3));
-}
-
-void
-pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
-{
-    u16 val = pci_config_readw(bdf, addr);
-    val = (val & ~off) | on;
-    pci_config_writew(bdf, addr, val);
-}
-
-// Helper function for foreachbdf() macro - return next device
-int
-pci_next(int bdf, int bus)
-{
-    if (pci_bdf_to_fn(bdf) == 0
-        && (pci_config_readb(bdf, PCI_HEADER_TYPE) & 0x80) == 0)
-        // Last found device wasn't a multi-function device - skip to
-        // the next device.
-        bdf += 8;
-    else
-        bdf += 1;
-
-    for (;;) {
-        if (pci_bdf_to_bus(bdf) != bus)
-            return -1;
-
-        u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
-        if (v != 0x0000 && v != 0xffff)
-            // Device is present.
-            return bdf;
-
-        if (pci_bdf_to_fn(bdf) == 0)
-            bdf += 8;
-        else
-            bdf += 1;
-    }
-}
-
-struct hlist_head PCIDevices VARVERIFY32INIT;
-int MaxPCIBus VARFSEG;
-
-// Check if PCI is available at all
-int
-pci_probe_host(void)
-{
-    outl(0x80000000, PORT_PCI_CMD);
-    if (inl(PORT_PCI_CMD) != 0x80000000) {
-        dprintf(1, "Detected non-PCI system\n");
-        return -1;
-    }
-    return 0;
-}
-
-// Find all PCI devices and populate PCIDevices linked list.
-void
-pci_probe_devices(void)
-{
-    dprintf(3, "PCI probe\n");
-    struct pci_device *busdevs[256];
-    memset(busdevs, 0, sizeof(busdevs));
-    struct hlist_node **pprev = &PCIDevices.first;
-    int extraroots = romfile_loadint("etc/extra-pci-roots", 0);
-    int bus = -1, lastbus = 0, rootbuses = 0, count=0;
-    while (bus < 0xff && (bus < MaxPCIBus || rootbuses < extraroots)) {
-        bus++;
-        int bdf;
-        foreachbdf(bdf, bus) {
-            // Create new pci_device struct and add to list.
-            struct pci_device *dev = malloc_tmp(sizeof(*dev));
-            if (!dev) {
-                warn_noalloc();
-                return;
-            }
-            memset(dev, 0, sizeof(*dev));
-            hlist_add(&dev->node, pprev);
-            pprev = &dev->node.next;
-            count++;
-
-            // Find parent device.
-            int rootbus;
-            struct pci_device *parent = busdevs[bus];
-            if (!parent) {
-                if (bus != lastbus)
-                    rootbuses++;
-                lastbus = bus;
-                rootbus = rootbuses;
-                if (bus > MaxPCIBus)
-                    MaxPCIBus = bus;
-            } else {
-                rootbus = parent->rootbus;
-            }
-
-            // Populate pci_device info.
-            dev->bdf = bdf;
-            dev->parent = parent;
-            dev->rootbus = rootbus;
-            u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
-            dev->vendor = vendev & 0xffff;
-            dev->device = vendev >> 16;
-            u32 classrev = pci_config_readl(bdf, PCI_CLASS_REVISION);
-            dev->class = classrev >> 16;
-            dev->prog_if = classrev >> 8;
-            dev->revision = classrev & 0xff;
-            dev->header_type = pci_config_readb(bdf, PCI_HEADER_TYPE);
-            u8 v = dev->header_type & 0x7f;
-            if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) {
-                u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
-                dev->secondary_bus = secbus;
-                if (secbus > bus && !busdevs[secbus])
-                    busdevs[secbus] = dev;
-                if (secbus > MaxPCIBus)
-                    MaxPCIBus = secbus;
-            }
-            dprintf(4, "PCI device %02x:%02x.%x (vd=%04x:%04x c=%04x)\n"
-                    , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)
-                    , pci_bdf_to_fn(bdf)
-                    , dev->vendor, dev->device, dev->class);
-        }
-    }
-    dprintf(1, "Found %d PCI devices (max PCI bus is %02x)\n", count, MaxPCIBus);
-}
-
-// Search for a device with the specified vendor and device ids.
-struct pci_device *
-pci_find_device(u16 vendid, u16 devid)
-{
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci->vendor == vendid && pci->device == devid)
-            return pci;
-    }
-    return NULL;
-}
-
-// Search for a device with the specified class id.
-struct pci_device *
-pci_find_class(u16 classid)
-{
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci->class == classid)
-            return pci;
-    }
-    return NULL;
-}
-
-int pci_init_device(const struct pci_device_id *ids
-                    , struct pci_device *pci, void *arg)
-{
-    while (ids->vendid || ids->class_mask) {
-        if ((ids->vendid == PCI_ANY_ID || ids->vendid == pci->vendor) &&
-            (ids->devid == PCI_ANY_ID || ids->devid == pci->device) &&
-            !((ids->class ^ pci->class) & ids->class_mask)) {
-            if (ids->func)
-                ids->func(pci, arg);
-            return 0;
-        }
-        ids++;
-    }
-    return -1;
-}
-
-struct pci_device *
-pci_find_init_device(const struct pci_device_id *ids, void *arg)
-{
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci_init_device(ids, pci, arg) == 0)
-            return pci;
-    }
-    return NULL;
-}
-
-void
-pci_reboot(void)
-{
-    u8 v = inb(PORT_PCI_REBOOT) & ~6;
-    outb(v|2, PORT_PCI_REBOOT); /* Request hard reset */
-    udelay(50);
-    outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */
-    udelay(50);
-}
-
-// helper functions to access pci mmio bars from real mode
-
-u32 VISIBLE32FLAT
-pci_readl_32(u32 addr)
-{
-    dprintf(9, "32: pci read : %x\n", addr);
-    return readl((void*)addr);
-}
-
-u32 pci_readl(u32 addr)
-{
-    if (MODESEGMENT) {
-        dprintf(9, "16: pci read : %x\n", addr);
-        extern void _cfunc32flat_pci_readl_32(u32 addr);
-        return call32(_cfunc32flat_pci_readl_32, addr, -1);
-    } else {
-        return pci_readl_32(addr);
-    }
-}
-
-struct reg32 {
-    u32 addr;
-    u32 data;
-};
-
-void VISIBLE32FLAT
-pci_writel_32(struct reg32 *reg32)
-{
-    dprintf(9, "32: pci write: %x, %x (%p)\n", reg32->addr, reg32->data, reg32);
-    writel((void*)(reg32->addr), reg32->data);
-}
-
-void pci_writel(u32 addr, u32 val)
-{
-    struct reg32 reg32 = { .addr = addr, .data = val };
-    if (MODESEGMENT) {
-        dprintf(9, "16: pci write: %x, %x (%x:%p)\n",
-                reg32.addr, reg32.data, GET_SEG(SS), &reg32);
-        void *flatptr = MAKE_FLATPTR(GET_SEG(SS), &reg32);
-        extern void _cfunc32flat_pci_writel_32(struct reg32 *reg32);
-        call32(_cfunc32flat_pci_writel_32, (u32)flatptr, -1);
-    } else {
-        pci_writel_32(&reg32);
-    }
-}
diff --git a/src/pci.h b/src/pci.h
deleted file mode 100644 (file)
index 7760d21..0000000
--- a/src/pci.h
+++ /dev/null
@@ -1,161 +0,0 @@
-#ifndef __PCI_H
-#define __PCI_H
-
-#include "types.h" // u32
-#include "list.h" // hlist_node
-
-#define PCI_ROM_SLOT 6
-#define PCI_NUM_REGIONS 7
-#define PCI_BRIDGE_NUM_REGIONS 2
-
-static inline u8 pci_bdf_to_bus(u16 bdf) {
-    return bdf >> 8;
-}
-static inline u8 pci_bdf_to_devfn(u16 bdf) {
-    return bdf & 0xff;
-}
-static inline u16 pci_bdf_to_busdev(u16 bdf) {
-    return bdf & ~0x07;
-}
-static inline u8 pci_bdf_to_dev(u16 bdf) {
-    return (bdf >> 3) & 0x1f;
-}
-static inline u8 pci_bdf_to_fn(u16 bdf) {
-    return bdf & 0x07;
-}
-static inline u16 pci_to_bdf(int bus, int dev, int fn) {
-    return (bus<<8) | (dev<<3) | fn;
-}
-static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) {
-    return (bus << 8) | devfn;
-}
-
-void pci_config_writel(u16 bdf, u32 addr, u32 val);
-void pci_config_writew(u16 bdf, u32 addr, u16 val);
-void pci_config_writeb(u16 bdf, u32 addr, u8 val);
-u32 pci_config_readl(u16 bdf, u32 addr);
-u16 pci_config_readw(u16 bdf, u32 addr);
-u8 pci_config_readb(u16 bdf, u32 addr);
-void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
-
-struct pci_device *pci_find_device(u16 vendid, u16 devid);
-struct pci_device *pci_find_class(u16 classid);
-
-struct pci_device {
-    u16 bdf;
-    u8 rootbus;
-    struct hlist_node node;
-    struct pci_device *parent;
-
-    // Configuration space device information
-    u16 vendor, device;
-    u16 class;
-    u8 prog_if, revision;
-    u8 header_type;
-    u8 secondary_bus;
-
-    // Local information on device.
-    int have_driver;
-};
-extern u64 pcimem_start, pcimem_end;
-extern u64 pcimem64_start, pcimem64_end;
-extern struct hlist_head PCIDevices;
-extern int MaxPCIBus;
-int pci_probe_host(void);
-void pci_probe_devices(void);
-static inline u32 pci_classprog(struct pci_device *pci) {
-    return (pci->class << 8) | pci->prog_if;
-}
-
-#define foreachpci(PCI)                                 \
-    hlist_for_each_entry(PCI, &PCIDevices, node)
-
-int pci_next(int bdf, int bus);
-#define foreachbdf(BDF, BUS)                                    \
-    for (BDF=pci_next(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS))  \
-         ; BDF >= 0                                             \
-         ; BDF=pci_next(BDF, (BUS)))
-
-#define PCI_ANY_ID      (~0)
-struct pci_device_id {
-    u32 vendid;
-    u32 devid;
-    u32 class;
-    u32 class_mask;
-    void (*func)(struct pci_device *pci, void *arg);
-};
-
-#define PCI_DEVICE(vendor_id, device_id, init_func)     \
-    {                                                   \
-        .vendid = (vendor_id),                          \
-        .devid = (device_id),                           \
-        .class = PCI_ANY_ID,                            \
-        .class_mask = 0,                                \
-        .func = (init_func)                             \
-    }
-
-#define PCI_DEVICE_CLASS(vendor_id, device_id, class_code, init_func)   \
-    {                                                                   \
-        .vendid = (vendor_id),                                          \
-        .devid = (device_id),                                           \
-        .class = (class_code),                                          \
-        .class_mask = ~0,                                               \
-        .func = (init_func)                                             \
-    }
-
-#define PCI_DEVICE_END                          \
-    {                                           \
-        .vendid = 0,                            \
-    }
-
-int pci_init_device(const struct pci_device_id *ids
-                    , struct pci_device *pci, void *arg);
-struct pci_device *pci_find_init_device(const struct pci_device_id *ids
-                                        , void *arg);
-void pci_reboot(void);
-
-// helper functions to access pci mmio bars from real mode
-u32 pci_readl(u32 addr);
-void pci_writel(u32 addr, u32 val);
-
-// pirtable.c
-void pirtable_setup(void);
-
-
-/****************************************************************
- * PIR table
- ****************************************************************/
-
-struct link_info {
-    u8 link;
-    u16 bitmap;
-} PACKED;
-
-struct pir_slot {
-    u8 bus;
-    u8 dev;
-    struct link_info links[4];
-    u8 slot_nr;
-    u8 reserved;
-} PACKED;
-
-struct pir_header {
-    u32 signature;
-    u16 version;
-    u16 size;
-    u8 router_bus;
-    u8 router_devfunc;
-    u16 exclusive_irqs;
-    u32 compatible_devid;
-    u32 miniport_data;
-    u8 reserved[11];
-    u8 checksum;
-    struct pir_slot slots[0];
-} PACKED;
-
-extern struct pir_header *PirAddr;
-
-#define PIR_SIGNATURE 0x52495024 // $PIR
-
-
-#endif
diff --git a/src/pci_ids.h b/src/pci_ids.h
deleted file mode 100644 (file)
index 665e945..0000000
+++ /dev/null
@@ -1,2619 +0,0 @@
-/*
- *     PCI Class, Vendor and Device IDs
- *
- *     Please keep sorted.
- */
-
-/* Device classes and subclasses */
-
-#define PCI_CLASS_NOT_DEFINED          0x0000
-#define PCI_CLASS_NOT_DEFINED_VGA      0x0001
-
-#define PCI_BASE_CLASS_STORAGE         0x01
-#define PCI_CLASS_STORAGE_SCSI         0x0100
-#define PCI_CLASS_STORAGE_IDE          0x0101
-#define PCI_CLASS_STORAGE_FLOPPY       0x0102
-#define PCI_CLASS_STORAGE_IPI          0x0103
-#define PCI_CLASS_STORAGE_RAID         0x0104
-#define PCI_CLASS_STORAGE_SATA         0x0106
-#define PCI_CLASS_STORAGE_SATA_AHCI    0x010601
-#define PCI_CLASS_STORAGE_SAS          0x0107
-#define PCI_CLASS_STORAGE_OTHER                0x0180
-
-#define PCI_BASE_CLASS_NETWORK         0x02
-#define PCI_CLASS_NETWORK_ETHERNET     0x0200
-#define PCI_CLASS_NETWORK_TOKEN_RING   0x0201
-#define PCI_CLASS_NETWORK_FDDI         0x0202
-#define PCI_CLASS_NETWORK_ATM          0x0203
-#define PCI_CLASS_NETWORK_OTHER                0x0280
-
-#define PCI_BASE_CLASS_DISPLAY         0x03
-#define PCI_CLASS_DISPLAY_VGA          0x0300
-#define PCI_CLASS_DISPLAY_XGA          0x0301
-#define PCI_CLASS_DISPLAY_3D           0x0302
-#define PCI_CLASS_DISPLAY_OTHER                0x0380
-
-#define PCI_BASE_CLASS_MULTIMEDIA      0x04
-#define PCI_CLASS_MULTIMEDIA_VIDEO     0x0400
-#define PCI_CLASS_MULTIMEDIA_AUDIO     0x0401
-#define PCI_CLASS_MULTIMEDIA_PHONE     0x0402
-#define PCI_CLASS_MULTIMEDIA_OTHER     0x0480
-
-#define PCI_BASE_CLASS_MEMORY          0x05
-#define PCI_CLASS_MEMORY_RAM           0x0500
-#define PCI_CLASS_MEMORY_FLASH         0x0501
-#define PCI_CLASS_MEMORY_OTHER         0x0580
-
-#define PCI_BASE_CLASS_BRIDGE          0x06
-#define PCI_CLASS_BRIDGE_HOST          0x0600
-#define PCI_CLASS_BRIDGE_ISA           0x0601
-#define PCI_CLASS_BRIDGE_EISA          0x0602
-#define PCI_CLASS_BRIDGE_MC            0x0603
-#define PCI_CLASS_BRIDGE_PCI           0x0604
-#define PCI_CLASS_BRIDGE_PCMCIA                0x0605
-#define PCI_CLASS_BRIDGE_NUBUS         0x0606
-#define PCI_CLASS_BRIDGE_CARDBUS       0x0607
-#define PCI_CLASS_BRIDGE_RACEWAY       0x0608
-#define PCI_CLASS_BRIDGE_OTHER         0x0680
-
-#define PCI_BASE_CLASS_COMMUNICATION   0x07
-#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
-#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
-#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702
-#define PCI_CLASS_COMMUNICATION_MODEM  0x0703
-#define PCI_CLASS_COMMUNICATION_OTHER  0x0780
-
-#define PCI_BASE_CLASS_SYSTEM          0x08
-#define PCI_CLASS_SYSTEM_PIC           0x0800
-#define PCI_CLASS_SYSTEM_PIC_IOAPIC    0x080010
-#define PCI_CLASS_SYSTEM_PIC_IOXAPIC   0x080020
-#define PCI_CLASS_SYSTEM_DMA           0x0801
-#define PCI_CLASS_SYSTEM_TIMER         0x0802
-#define PCI_CLASS_SYSTEM_RTC           0x0803
-#define PCI_CLASS_SYSTEM_PCI_HOTPLUG   0x0804
-#define PCI_CLASS_SYSTEM_SDHCI         0x0805
-#define PCI_CLASS_SYSTEM_OTHER         0x0880
-
-#define PCI_BASE_CLASS_INPUT           0x09
-#define PCI_CLASS_INPUT_KEYBOARD       0x0900
-#define PCI_CLASS_INPUT_PEN            0x0901
-#define PCI_CLASS_INPUT_MOUSE          0x0902
-#define PCI_CLASS_INPUT_SCANNER                0x0903
-#define PCI_CLASS_INPUT_GAMEPORT       0x0904
-#define PCI_CLASS_INPUT_OTHER          0x0980
-
-#define PCI_BASE_CLASS_DOCKING         0x0a
-#define PCI_CLASS_DOCKING_GENERIC      0x0a00
-#define PCI_CLASS_DOCKING_OTHER                0x0a80
-
-#define PCI_BASE_CLASS_PROCESSOR       0x0b
-#define PCI_CLASS_PROCESSOR_386                0x0b00
-#define PCI_CLASS_PROCESSOR_486                0x0b01
-#define PCI_CLASS_PROCESSOR_PENTIUM    0x0b02
-#define PCI_CLASS_PROCESSOR_ALPHA      0x0b10
-#define PCI_CLASS_PROCESSOR_POWERPC    0x0b20
-#define PCI_CLASS_PROCESSOR_MIPS       0x0b30
-#define PCI_CLASS_PROCESSOR_CO         0x0b40
-
-#define PCI_BASE_CLASS_SERIAL          0x0c
-#define PCI_CLASS_SERIAL_FIREWIRE      0x0c00
-#define PCI_CLASS_SERIAL_FIREWIRE_OHCI 0x0c0010
-#define PCI_CLASS_SERIAL_ACCESS                0x0c01
-#define PCI_CLASS_SERIAL_SSA           0x0c02
-#define PCI_CLASS_SERIAL_USB           0x0c03
-#define PCI_CLASS_SERIAL_USB_UHCI      0x0c0300
-#define PCI_CLASS_SERIAL_USB_OHCI      0x0c0310
-#define PCI_CLASS_SERIAL_USB_EHCI      0x0c0320
-#define PCI_CLASS_SERIAL_FIBER         0x0c04
-#define PCI_CLASS_SERIAL_SMBUS         0x0c05
-
-#define PCI_BASE_CLASS_WIRELESS                        0x0d
-#define PCI_CLASS_WIRELESS_RF_CONTROLLER       0x0d10
-#define PCI_CLASS_WIRELESS_WHCI                        0x0d1010
-
-#define PCI_BASE_CLASS_INTELLIGENT     0x0e
-#define PCI_CLASS_INTELLIGENT_I2O      0x0e00
-
-#define PCI_BASE_CLASS_SATELLITE       0x0f
-#define PCI_CLASS_SATELLITE_TV         0x0f00
-#define PCI_CLASS_SATELLITE_AUDIO      0x0f01
-#define PCI_CLASS_SATELLITE_VOICE      0x0f03
-#define PCI_CLASS_SATELLITE_DATA       0x0f04
-
-#define PCI_BASE_CLASS_CRYPT           0x10
-#define PCI_CLASS_CRYPT_NETWORK                0x1000
-#define PCI_CLASS_CRYPT_ENTERTAINMENT  0x1001
-#define PCI_CLASS_CRYPT_OTHER          0x1080
-
-#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11
-#define PCI_CLASS_SP_DPIO              0x1100
-#define PCI_CLASS_SP_OTHER             0x1180
-
-#define PCI_CLASS_OTHERS               0xff
-
-/* Vendors and devices.  Sort key: vendor first, device next. */
-
-#define PCI_VENDOR_ID_TTTECH           0x0357
-#define PCI_DEVICE_ID_TTTECH_MC322     0x000a
-
-#define PCI_VENDOR_ID_DYNALINK         0x0675
-#define PCI_DEVICE_ID_DYNALINK_IS64PH  0x1702
-
-#define PCI_VENDOR_ID_BERKOM                   0x0871
-#define PCI_DEVICE_ID_BERKOM_A1T               0xffa1
-#define PCI_DEVICE_ID_BERKOM_T_CONCEPT         0xffa2
-#define PCI_DEVICE_ID_BERKOM_A4T               0xffa4
-#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO     0xffa8
-
-#define PCI_VENDOR_ID_COMPAQ           0x0e11
-#define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508
-#define PCI_DEVICE_ID_COMPAQ_TACHYON   0xa0fc
-#define PCI_DEVICE_ID_COMPAQ_SMART2P   0xae10
-#define PCI_DEVICE_ID_COMPAQ_NETEL100  0xae32
-#define PCI_DEVICE_ID_COMPAQ_NETEL10   0xae34
-#define PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE 0xae33
-#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I 0xae35
-#define PCI_DEVICE_ID_COMPAQ_NETEL100D 0xae40
-#define PCI_DEVICE_ID_COMPAQ_NETEL100PI        0xae43
-#define PCI_DEVICE_ID_COMPAQ_NETEL100I 0xb011
-#define PCI_DEVICE_ID_COMPAQ_CISS      0xb060
-#define PCI_DEVICE_ID_COMPAQ_CISSB     0xb178
-#define PCI_DEVICE_ID_COMPAQ_CISSC     0x46
-#define PCI_DEVICE_ID_COMPAQ_THUNDER   0xf130
-#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B 0xf150
-
-#define PCI_VENDOR_ID_NCR              0x1000
-#define PCI_VENDOR_ID_LSI_LOGIC                0x1000
-#define PCI_DEVICE_ID_NCR_53C810       0x0001
-#define PCI_DEVICE_ID_NCR_53C820       0x0002
-#define PCI_DEVICE_ID_NCR_53C825       0x0003
-#define PCI_DEVICE_ID_NCR_53C815       0x0004
-#define PCI_DEVICE_ID_LSI_53C810AP     0x0005
-#define PCI_DEVICE_ID_NCR_53C860       0x0006
-#define PCI_DEVICE_ID_LSI_53C1510      0x000a
-#define PCI_DEVICE_ID_NCR_53C896       0x000b
-#define PCI_DEVICE_ID_NCR_53C895       0x000c
-#define PCI_DEVICE_ID_NCR_53C885       0x000d
-#define PCI_DEVICE_ID_NCR_53C875       0x000f
-#define PCI_DEVICE_ID_NCR_53C1510      0x0010
-#define PCI_DEVICE_ID_LSI_53C895A      0x0012
-#define PCI_DEVICE_ID_LSI_53C875A      0x0013
-#define PCI_DEVICE_ID_LSI_53C1010_33   0x0020
-#define PCI_DEVICE_ID_LSI_53C1010_66   0x0021
-#define PCI_DEVICE_ID_LSI_53C1030      0x0030
-#define PCI_DEVICE_ID_LSI_1030_53C1035 0x0032
-#define PCI_DEVICE_ID_LSI_53C1035      0x0040
-#define PCI_DEVICE_ID_NCR_53C875J      0x008f
-#define PCI_DEVICE_ID_LSI_FC909                0x0621
-#define PCI_DEVICE_ID_LSI_FC929                0x0622
-#define PCI_DEVICE_ID_LSI_FC929_LAN    0x0623
-#define PCI_DEVICE_ID_LSI_FC919                0x0624
-#define PCI_DEVICE_ID_LSI_FC919_LAN    0x0625
-#define PCI_DEVICE_ID_LSI_FC929X       0x0626
-#define PCI_DEVICE_ID_LSI_FC939X       0x0642
-#define PCI_DEVICE_ID_LSI_FC949X       0x0640
-#define PCI_DEVICE_ID_LSI_FC949ES      0x0646
-#define PCI_DEVICE_ID_LSI_FC919X       0x0628
-#define PCI_DEVICE_ID_NCR_YELLOWFIN    0x0701
-#define PCI_DEVICE_ID_LSI_61C102       0x0901
-#define PCI_DEVICE_ID_LSI_63C815       0x1000
-#define PCI_DEVICE_ID_LSI_SAS1064      0x0050
-#define PCI_DEVICE_ID_LSI_SAS1064R     0x0411
-#define PCI_DEVICE_ID_LSI_VERDE_ZCR    0x0413
-#define PCI_DEVICE_ID_LSI_SAS1066      0x005E
-#define PCI_DEVICE_ID_LSI_SAS1068      0x0054
-#define PCI_DEVICE_ID_LSI_SAS1064A     0x005C
-#define PCI_DEVICE_ID_LSI_SAS1064E     0x0056
-#define PCI_DEVICE_ID_LSI_SAS1066E     0x005A
-#define PCI_DEVICE_ID_LSI_SAS1068E     0x0058
-#define PCI_DEVICE_ID_LSI_SAS1078      0x0060
-#define PCI_DEVICE_ID_LSI_SAS1078DE    0x007C
-#define PCI_DEVICE_ID_LSI_SAS2108E     0x0078
-#define PCI_DEVICE_ID_LSI_SAS2108      0x0079
-#define PCI_DEVICE_ID_LSI_SAS2208      0x005B
-#define PCI_DEVICE_ID_LSI_SAS3108      0x005D
-#define PCI_DEVICE_ID_LSI_SAS2004      0x0071
-#define PCI_DEVICE_ID_LSI_SAS2008      0x0073
-
-#define PCI_VENDOR_ID_ATI              0x1002
-/* Mach64 */
-#define PCI_DEVICE_ID_ATI_68800                0x4158
-#define PCI_DEVICE_ID_ATI_215CT222     0x4354
-#define PCI_DEVICE_ID_ATI_210888CX     0x4358
-#define PCI_DEVICE_ID_ATI_215ET222     0x4554
-/* Mach64 / Rage */
-#define PCI_DEVICE_ID_ATI_215GB                0x4742
-#define PCI_DEVICE_ID_ATI_215GD                0x4744
-#define PCI_DEVICE_ID_ATI_215GI                0x4749
-#define PCI_DEVICE_ID_ATI_215GP                0x4750
-#define PCI_DEVICE_ID_ATI_215GQ                0x4751
-#define PCI_DEVICE_ID_ATI_215XL                0x4752
-#define PCI_DEVICE_ID_ATI_215GT                0x4754
-#define PCI_DEVICE_ID_ATI_215GTB       0x4755
-#define PCI_DEVICE_ID_ATI_215_IV       0x4756
-#define PCI_DEVICE_ID_ATI_215_IW       0x4757
-#define PCI_DEVICE_ID_ATI_215_IZ       0x475A
-#define PCI_DEVICE_ID_ATI_210888GX     0x4758
-#define PCI_DEVICE_ID_ATI_215_LB       0x4c42
-#define PCI_DEVICE_ID_ATI_215_LD       0x4c44
-#define PCI_DEVICE_ID_ATI_215_LG       0x4c47
-#define PCI_DEVICE_ID_ATI_215_LI       0x4c49
-#define PCI_DEVICE_ID_ATI_215_LM       0x4c4D
-#define PCI_DEVICE_ID_ATI_215_LN       0x4c4E
-#define PCI_DEVICE_ID_ATI_215_LR       0x4c52
-#define PCI_DEVICE_ID_ATI_215_LS       0x4c53
-#define PCI_DEVICE_ID_ATI_264_LT       0x4c54
-/* Mach64 VT */
-#define PCI_DEVICE_ID_ATI_264VT                0x5654
-#define PCI_DEVICE_ID_ATI_264VU                0x5655
-#define PCI_DEVICE_ID_ATI_264VV                0x5656
-/* Rage128 GL */
-#define PCI_DEVICE_ID_ATI_RAGE128_RE   0x5245
-#define PCI_DEVICE_ID_ATI_RAGE128_RF   0x5246
-#define PCI_DEVICE_ID_ATI_RAGE128_RG   0x5247
-/* Rage128 VR */
-#define PCI_DEVICE_ID_ATI_RAGE128_RK   0x524b
-#define PCI_DEVICE_ID_ATI_RAGE128_RL   0x524c
-#define PCI_DEVICE_ID_ATI_RAGE128_SE   0x5345
-#define PCI_DEVICE_ID_ATI_RAGE128_SF   0x5346
-#define PCI_DEVICE_ID_ATI_RAGE128_SG   0x5347
-#define PCI_DEVICE_ID_ATI_RAGE128_SH   0x5348
-#define PCI_DEVICE_ID_ATI_RAGE128_SK   0x534b
-#define PCI_DEVICE_ID_ATI_RAGE128_SL   0x534c
-#define PCI_DEVICE_ID_ATI_RAGE128_SM   0x534d
-#define PCI_DEVICE_ID_ATI_RAGE128_SN   0x534e
-/* Rage128 Ultra */
-#define PCI_DEVICE_ID_ATI_RAGE128_TF   0x5446
-#define PCI_DEVICE_ID_ATI_RAGE128_TL   0x544c
-#define PCI_DEVICE_ID_ATI_RAGE128_TR   0x5452
-#define PCI_DEVICE_ID_ATI_RAGE128_TS   0x5453
-#define PCI_DEVICE_ID_ATI_RAGE128_TT   0x5454
-#define PCI_DEVICE_ID_ATI_RAGE128_TU   0x5455
-/* Rage128 M3 */
-#define PCI_DEVICE_ID_ATI_RAGE128_LE   0x4c45
-#define PCI_DEVICE_ID_ATI_RAGE128_LF   0x4c46
-/* Rage128 M4 */
-#define PCI_DEVICE_ID_ATI_RAGE128_MF    0x4d46
-#define PCI_DEVICE_ID_ATI_RAGE128_ML    0x4d4c
-/* Rage128 Pro GL */
-#define PCI_DEVICE_ID_ATI_RAGE128_PA   0x5041
-#define PCI_DEVICE_ID_ATI_RAGE128_PB   0x5042
-#define PCI_DEVICE_ID_ATI_RAGE128_PC   0x5043
-#define PCI_DEVICE_ID_ATI_RAGE128_PD   0x5044
-#define PCI_DEVICE_ID_ATI_RAGE128_PE   0x5045
-#define PCI_DEVICE_ID_ATI_RAGE128_PF   0x5046
-/* Rage128 Pro VR */
-#define PCI_DEVICE_ID_ATI_RAGE128_PG   0x5047
-#define PCI_DEVICE_ID_ATI_RAGE128_PH   0x5048
-#define PCI_DEVICE_ID_ATI_RAGE128_PI   0x5049
-#define PCI_DEVICE_ID_ATI_RAGE128_PJ   0x504A
-#define PCI_DEVICE_ID_ATI_RAGE128_PK   0x504B
-#define PCI_DEVICE_ID_ATI_RAGE128_PL   0x504C
-#define PCI_DEVICE_ID_ATI_RAGE128_PM   0x504D
-#define PCI_DEVICE_ID_ATI_RAGE128_PN   0x504E
-#define PCI_DEVICE_ID_ATI_RAGE128_PO   0x504F
-#define PCI_DEVICE_ID_ATI_RAGE128_PP   0x5050
-#define PCI_DEVICE_ID_ATI_RAGE128_PQ   0x5051
-#define PCI_DEVICE_ID_ATI_RAGE128_PR   0x5052
-#define PCI_DEVICE_ID_ATI_RAGE128_PS   0x5053
-#define PCI_DEVICE_ID_ATI_RAGE128_PT   0x5054
-#define PCI_DEVICE_ID_ATI_RAGE128_PU   0x5055
-#define PCI_DEVICE_ID_ATI_RAGE128_PV   0x5056
-#define PCI_DEVICE_ID_ATI_RAGE128_PW   0x5057
-#define PCI_DEVICE_ID_ATI_RAGE128_PX   0x5058
-/* Rage128 M4 */
-/* Radeon R100 */
-#define PCI_DEVICE_ID_ATI_RADEON_QD    0x5144
-#define PCI_DEVICE_ID_ATI_RADEON_QE    0x5145
-#define PCI_DEVICE_ID_ATI_RADEON_QF    0x5146
-#define PCI_DEVICE_ID_ATI_RADEON_QG    0x5147
-/* Radeon RV100 (VE) */
-#define PCI_DEVICE_ID_ATI_RADEON_QY    0x5159
-#define PCI_DEVICE_ID_ATI_RADEON_QZ    0x515a
-/* Radeon R200 (8500) */
-#define PCI_DEVICE_ID_ATI_RADEON_QL    0x514c
-#define PCI_DEVICE_ID_ATI_RADEON_QN    0x514e
-#define PCI_DEVICE_ID_ATI_RADEON_QO    0x514f
-#define PCI_DEVICE_ID_ATI_RADEON_Ql    0x516c
-#define PCI_DEVICE_ID_ATI_RADEON_BB    0x4242
-/* Radeon R200 (9100) */
-#define PCI_DEVICE_ID_ATI_RADEON_QM    0x514d
-/* Radeon RV200 (7500) */
-#define PCI_DEVICE_ID_ATI_RADEON_QW    0x5157
-#define PCI_DEVICE_ID_ATI_RADEON_QX    0x5158
-/* Radeon NV-100 */
-/* Radeon RV250 (9000) */
-#define PCI_DEVICE_ID_ATI_RADEON_Id    0x4964
-#define PCI_DEVICE_ID_ATI_RADEON_Ie    0x4965
-#define PCI_DEVICE_ID_ATI_RADEON_If    0x4966
-#define PCI_DEVICE_ID_ATI_RADEON_Ig    0x4967
-/* Radeon RV280 (9200) */
-#define PCI_DEVICE_ID_ATI_RADEON_Ya    0x5961
-#define PCI_DEVICE_ID_ATI_RADEON_Yd    0x5964
-/* Radeon R300 (9500) */
-/* Radeon R300 (9700) */
-#define PCI_DEVICE_ID_ATI_RADEON_ND    0x4e44
-#define PCI_DEVICE_ID_ATI_RADEON_NE    0x4e45
-#define PCI_DEVICE_ID_ATI_RADEON_NF    0x4e46
-#define PCI_DEVICE_ID_ATI_RADEON_NG    0x4e47
-/* Radeon R350 (9800) */
-/* Radeon RV350 (9600) */
-/* Radeon M6 */
-#define PCI_DEVICE_ID_ATI_RADEON_LY    0x4c59
-#define PCI_DEVICE_ID_ATI_RADEON_LZ    0x4c5a
-/* Radeon M7 */
-#define PCI_DEVICE_ID_ATI_RADEON_LW    0x4c57
-#define PCI_DEVICE_ID_ATI_RADEON_LX    0x4c58
-/* Radeon M9 */
-#define PCI_DEVICE_ID_ATI_RADEON_Ld    0x4c64
-#define PCI_DEVICE_ID_ATI_RADEON_Le    0x4c65
-#define PCI_DEVICE_ID_ATI_RADEON_Lf    0x4c66
-#define PCI_DEVICE_ID_ATI_RADEON_Lg    0x4c67
-/* Radeon */
-/* RadeonIGP */
-#define PCI_DEVICE_ID_ATI_RS100                0xcab0
-#define PCI_DEVICE_ID_ATI_RS200                0xcab2
-#define PCI_DEVICE_ID_ATI_RS200_B      0xcbb2
-#define PCI_DEVICE_ID_ATI_RS250                0xcab3
-#define PCI_DEVICE_ID_ATI_RS300_100    0x5830
-#define PCI_DEVICE_ID_ATI_RS300_133    0x5831
-#define PCI_DEVICE_ID_ATI_RS300_166    0x5832
-#define PCI_DEVICE_ID_ATI_RS300_200    0x5833
-#define PCI_DEVICE_ID_ATI_RS350_100     0x7830
-#define PCI_DEVICE_ID_ATI_RS350_133     0x7831
-#define PCI_DEVICE_ID_ATI_RS350_166     0x7832
-#define PCI_DEVICE_ID_ATI_RS350_200     0x7833
-#define PCI_DEVICE_ID_ATI_RS400_100     0x5a30
-#define PCI_DEVICE_ID_ATI_RS400_133     0x5a31
-#define PCI_DEVICE_ID_ATI_RS400_166     0x5a32
-#define PCI_DEVICE_ID_ATI_RS400_200     0x5a33
-#define PCI_DEVICE_ID_ATI_RS480         0x5950
-/* ATI IXP Chipset */
-#define PCI_DEVICE_ID_ATI_IXP200_IDE   0x4349
-#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353
-#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363
-#define PCI_DEVICE_ID_ATI_IXP300_IDE   0x4369
-#define PCI_DEVICE_ID_ATI_IXP300_SATA   0x436e
-#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372
-#define PCI_DEVICE_ID_ATI_IXP400_IDE   0x4376
-#define PCI_DEVICE_ID_ATI_IXP400_SATA   0x4379
-#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a
-#define PCI_DEVICE_ID_ATI_IXP600_SATA  0x4380
-#define PCI_DEVICE_ID_ATI_SBX00_SMBUS  0x4385
-#define PCI_DEVICE_ID_ATI_IXP600_IDE   0x438c
-#define PCI_DEVICE_ID_ATI_IXP700_SATA  0x4390
-#define PCI_DEVICE_ID_ATI_IXP700_IDE   0x439c
-
-#define PCI_VENDOR_ID_VLSI             0x1004
-#define PCI_DEVICE_ID_VLSI_82C592      0x0005
-#define PCI_DEVICE_ID_VLSI_82C593      0x0006
-#define PCI_DEVICE_ID_VLSI_82C594      0x0007
-#define PCI_DEVICE_ID_VLSI_82C597      0x0009
-#define PCI_DEVICE_ID_VLSI_82C541      0x000c
-#define PCI_DEVICE_ID_VLSI_82C543      0x000d
-#define PCI_DEVICE_ID_VLSI_82C532      0x0101
-#define PCI_DEVICE_ID_VLSI_82C534      0x0102
-#define PCI_DEVICE_ID_VLSI_82C535      0x0104
-#define PCI_DEVICE_ID_VLSI_82C147      0x0105
-#define PCI_DEVICE_ID_VLSI_VAS96011    0x0702
-
-#define PCI_VENDOR_ID_ADL              0x1005
-#define PCI_DEVICE_ID_ADL_2301         0x2301
-
-#define PCI_VENDOR_ID_NS               0x100b
-#define PCI_DEVICE_ID_NS_87415         0x0002
-#define PCI_DEVICE_ID_NS_87560_LIO     0x000e
-#define PCI_DEVICE_ID_NS_87560_USB     0x0012
-#define PCI_DEVICE_ID_NS_83815         0x0020
-#define PCI_DEVICE_ID_NS_83820         0x0022
-#define PCI_DEVICE_ID_NS_CS5535_ISA    0x002b
-#define PCI_DEVICE_ID_NS_CS5535_IDE    0x002d
-#define PCI_DEVICE_ID_NS_CS5535_AUDIO  0x002e
-#define PCI_DEVICE_ID_NS_CS5535_USB    0x002f
-#define PCI_DEVICE_ID_NS_GX_VIDEO      0x0030
-#define PCI_DEVICE_ID_NS_SATURN                0x0035
-#define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500
-#define PCI_DEVICE_ID_NS_SCx200_SMI    0x0501
-#define PCI_DEVICE_ID_NS_SCx200_IDE    0x0502
-#define PCI_DEVICE_ID_NS_SCx200_AUDIO  0x0503
-#define PCI_DEVICE_ID_NS_SCx200_VIDEO  0x0504
-#define PCI_DEVICE_ID_NS_SCx200_XBUS   0x0505
-#define PCI_DEVICE_ID_NS_SC1100_BRIDGE 0x0510
-#define PCI_DEVICE_ID_NS_SC1100_SMI    0x0511
-#define PCI_DEVICE_ID_NS_SC1100_XBUS   0x0515
-#define PCI_DEVICE_ID_NS_87410         0xd001
-
-#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE  0x0028
-
-#define PCI_VENDOR_ID_TSENG            0x100c
-#define PCI_DEVICE_ID_TSENG_W32P_2     0x3202
-#define PCI_DEVICE_ID_TSENG_W32P_b     0x3205
-#define PCI_DEVICE_ID_TSENG_W32P_c     0x3206
-#define PCI_DEVICE_ID_TSENG_W32P_d     0x3207
-#define PCI_DEVICE_ID_TSENG_ET6000     0x3208
-
-#define PCI_VENDOR_ID_WEITEK           0x100e
-#define PCI_DEVICE_ID_WEITEK_P9000     0x9001
-#define PCI_DEVICE_ID_WEITEK_P9100     0x9100
-
-#define PCI_VENDOR_ID_DEC              0x1011
-#define PCI_DEVICE_ID_DEC_BRD          0x0001
-#define PCI_DEVICE_ID_DEC_TULIP                0x0002
-#define PCI_DEVICE_ID_DEC_TGA          0x0004
-#define PCI_DEVICE_ID_DEC_TULIP_FAST   0x0009
-#define PCI_DEVICE_ID_DEC_TGA2         0x000D
-#define PCI_DEVICE_ID_DEC_FDDI         0x000F
-#define PCI_DEVICE_ID_DEC_TULIP_PLUS   0x0014
-#define PCI_DEVICE_ID_DEC_21142                0x0019
-#define PCI_DEVICE_ID_DEC_21052                0x0021
-#define PCI_DEVICE_ID_DEC_21150                0x0022
-#define PCI_DEVICE_ID_DEC_21152                0x0024
-#define PCI_DEVICE_ID_DEC_21153                0x0025
-#define PCI_DEVICE_ID_DEC_21154                0x0026
-#define PCI_DEVICE_ID_DEC_21285                0x1065
-#define PCI_DEVICE_ID_COMPAQ_42XX      0x0046
-
-#define PCI_VENDOR_ID_CIRRUS           0x1013
-#define PCI_DEVICE_ID_CIRRUS_7548      0x0038
-#define PCI_DEVICE_ID_CIRRUS_5430      0x00a0
-#define PCI_DEVICE_ID_CIRRUS_5434_4    0x00a4
-#define PCI_DEVICE_ID_CIRRUS_5434_8    0x00a8
-#define PCI_DEVICE_ID_CIRRUS_5436      0x00ac
-#define PCI_DEVICE_ID_CIRRUS_5446      0x00b8
-#define PCI_DEVICE_ID_CIRRUS_5480      0x00bc
-#define PCI_DEVICE_ID_CIRRUS_5462      0x00d0
-#define PCI_DEVICE_ID_CIRRUS_5464      0x00d4
-#define PCI_DEVICE_ID_CIRRUS_5465      0x00d6
-#define PCI_DEVICE_ID_CIRRUS_6729      0x1100
-#define PCI_DEVICE_ID_CIRRUS_6832      0x1110
-#define PCI_DEVICE_ID_CIRRUS_7543      0x1202
-#define PCI_DEVICE_ID_CIRRUS_4610      0x6001
-#define PCI_DEVICE_ID_CIRRUS_4612      0x6003
-#define PCI_DEVICE_ID_CIRRUS_4615      0x6004
-
-#define PCI_VENDOR_ID_IBM              0x1014
-#define PCI_DEVICE_ID_IBM_TR           0x0018
-#define PCI_DEVICE_ID_IBM_TR_WAKE      0x003e
-#define PCI_DEVICE_ID_IBM_CPC710_PCI64 0x00fc
-#define PCI_DEVICE_ID_IBM_SNIPE                0x0180
-#define PCI_DEVICE_ID_IBM_CITRINE              0x028C
-#define PCI_DEVICE_ID_IBM_GEMSTONE             0xB166
-#define PCI_DEVICE_ID_IBM_OBSIDIAN             0x02BD
-#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1        0x0031
-#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2        0x0219
-#define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX                0x021A
-#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM    0x0251
-#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
-#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
-
-#define PCI_VENDOR_ID_UNISYS           0x1018
-#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C
-
-#define PCI_VENDOR_ID_COMPEX2          0x101a /* pci.ids says "AT&T GIS (NCR)" */
-#define PCI_DEVICE_ID_COMPEX2_100VG    0x0005
-
-#define PCI_VENDOR_ID_WD               0x101c
-#define PCI_DEVICE_ID_WD_90C           0xc24a
-
-#define PCI_VENDOR_ID_AMI              0x101e
-#define PCI_DEVICE_ID_AMI_MEGARAID3    0x1960
-#define PCI_DEVICE_ID_AMI_MEGARAID     0x9010
-#define PCI_DEVICE_ID_AMI_MEGARAID2    0x9060
-
-#define PCI_VENDOR_ID_AMD              0x1022
-#define PCI_DEVICE_ID_AMD_K8_NB                0x1100
-#define PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP        0x1101
-#define PCI_DEVICE_ID_AMD_K8_NB_MEMCTL 0x1102
-#define PCI_DEVICE_ID_AMD_K8_NB_MISC   0x1103
-#define PCI_DEVICE_ID_AMD_10H_NB_HT    0x1200
-#define PCI_DEVICE_ID_AMD_10H_NB_MAP   0x1201
-#define PCI_DEVICE_ID_AMD_10H_NB_DRAM  0x1202
-#define PCI_DEVICE_ID_AMD_10H_NB_MISC  0x1203
-#define PCI_DEVICE_ID_AMD_10H_NB_LINK  0x1204
-#define PCI_DEVICE_ID_AMD_11H_NB_HT    0x1300
-#define PCI_DEVICE_ID_AMD_11H_NB_MAP   0x1301
-#define PCI_DEVICE_ID_AMD_11H_NB_DRAM  0x1302
-#define PCI_DEVICE_ID_AMD_11H_NB_MISC  0x1303
-#define PCI_DEVICE_ID_AMD_11H_NB_LINK  0x1304
-#define PCI_DEVICE_ID_AMD_LANCE                0x2000
-#define PCI_DEVICE_ID_AMD_LANCE_HOME   0x2001
-#define PCI_DEVICE_ID_AMD_SCSI         0x2020
-#define PCI_DEVICE_ID_AMD_SERENADE     0x36c0
-#define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006
-#define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007
-#define PCI_DEVICE_ID_AMD_FE_GATE_700C 0x700C
-#define PCI_DEVICE_ID_AMD_FE_GATE_700E 0x700E
-#define PCI_DEVICE_ID_AMD_COBRA_7401   0x7401
-#define PCI_DEVICE_ID_AMD_VIPER_7409   0x7409
-#define PCI_DEVICE_ID_AMD_VIPER_740B   0x740B
-#define PCI_DEVICE_ID_AMD_VIPER_7410   0x7410
-#define PCI_DEVICE_ID_AMD_VIPER_7411   0x7411
-#define PCI_DEVICE_ID_AMD_VIPER_7413   0x7413
-#define PCI_DEVICE_ID_AMD_VIPER_7440   0x7440
-#define PCI_DEVICE_ID_AMD_OPUS_7441    0x7441
-#define PCI_DEVICE_ID_AMD_OPUS_7443    0x7443
-#define PCI_DEVICE_ID_AMD_VIPER_7443   0x7443
-#define PCI_DEVICE_ID_AMD_OPUS_7445    0x7445
-#define PCI_DEVICE_ID_AMD_8111_LPC     0x7468
-#define PCI_DEVICE_ID_AMD_8111_IDE     0x7469
-#define PCI_DEVICE_ID_AMD_8111_SMBUS2  0x746a
-#define PCI_DEVICE_ID_AMD_8111_SMBUS   0x746b
-#define PCI_DEVICE_ID_AMD_8111_AUDIO   0x746d
-#define PCI_DEVICE_ID_AMD_8151_0       0x7454
-#define PCI_DEVICE_ID_AMD_8131_BRIDGE  0x7450
-#define PCI_DEVICE_ID_AMD_8131_APIC    0x7451
-#define PCI_DEVICE_ID_AMD_8132_BRIDGE  0x7458
-#define PCI_DEVICE_ID_AMD_CS5536_ISA    0x2090
-#define PCI_DEVICE_ID_AMD_CS5536_FLASH  0x2091
-#define PCI_DEVICE_ID_AMD_CS5536_AUDIO  0x2093
-#define PCI_DEVICE_ID_AMD_CS5536_OHC    0x2094
-#define PCI_DEVICE_ID_AMD_CS5536_EHC    0x2095
-#define PCI_DEVICE_ID_AMD_CS5536_UDC    0x2096
-#define PCI_DEVICE_ID_AMD_CS5536_UOC    0x2097
-#define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
-
-#define PCI_DEVICE_ID_AMD_LX_VIDEO  0x2081
-#define PCI_DEVICE_ID_AMD_LX_AES    0x2082
-
-#define PCI_VENDOR_ID_TRIDENT          0x1023
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX        0x2000
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX        0x2001
-#define PCI_DEVICE_ID_TRIDENT_9320     0x9320
-#define PCI_DEVICE_ID_TRIDENT_9388     0x9388
-#define PCI_DEVICE_ID_TRIDENT_9397     0x9397
-#define PCI_DEVICE_ID_TRIDENT_939A     0x939A
-#define PCI_DEVICE_ID_TRIDENT_9520     0x9520
-#define PCI_DEVICE_ID_TRIDENT_9525     0x9525
-#define PCI_DEVICE_ID_TRIDENT_9420     0x9420
-#define PCI_DEVICE_ID_TRIDENT_9440     0x9440
-#define PCI_DEVICE_ID_TRIDENT_9660     0x9660
-#define PCI_DEVICE_ID_TRIDENT_9750     0x9750
-#define PCI_DEVICE_ID_TRIDENT_9850     0x9850
-#define PCI_DEVICE_ID_TRIDENT_9880     0x9880
-#define PCI_DEVICE_ID_TRIDENT_8400     0x8400
-#define PCI_DEVICE_ID_TRIDENT_8420     0x8420
-#define PCI_DEVICE_ID_TRIDENT_8500     0x8500
-
-#define PCI_VENDOR_ID_AI               0x1025
-#define PCI_DEVICE_ID_AI_M1435         0x1435
-
-#define PCI_VENDOR_ID_DELL             0x1028
-#define PCI_DEVICE_ID_DELL_RACIII      0x0008
-#define PCI_DEVICE_ID_DELL_RAC4                0x0012
-#define PCI_DEVICE_ID_DELL_PERC5       0x0015
-
-#define PCI_VENDOR_ID_MATROX           0x102B
-#define PCI_DEVICE_ID_MATROX_MGA_2     0x0518
-#define PCI_DEVICE_ID_MATROX_MIL       0x0519
-#define PCI_DEVICE_ID_MATROX_MYS       0x051A
-#define PCI_DEVICE_ID_MATROX_MIL_2     0x051b
-#define PCI_DEVICE_ID_MATROX_MYS_AGP   0x051e
-#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f
-#define PCI_DEVICE_ID_MATROX_MGA_IMP   0x0d10
-#define PCI_DEVICE_ID_MATROX_G100_MM   0x1000
-#define PCI_DEVICE_ID_MATROX_G100_AGP  0x1001
-#define PCI_DEVICE_ID_MATROX_G200_PCI  0x0520
-#define PCI_DEVICE_ID_MATROX_G200_AGP  0x0521
-#define        PCI_DEVICE_ID_MATROX_G400       0x0525
-#define        PCI_DEVICE_ID_MATROX_G200EV_PCI 0x0530
-#define PCI_DEVICE_ID_MATROX_G550      0x2527
-#define PCI_DEVICE_ID_MATROX_VIA       0x4536
-
-#define PCI_VENDOR_ID_CT               0x102c
-#define PCI_DEVICE_ID_CT_69000         0x00c0
-#define PCI_DEVICE_ID_CT_65545         0x00d8
-#define PCI_DEVICE_ID_CT_65548         0x00dc
-#define PCI_DEVICE_ID_CT_65550         0x00e0
-#define PCI_DEVICE_ID_CT_65554         0x00e4
-#define PCI_DEVICE_ID_CT_65555         0x00e5
-
-#define PCI_VENDOR_ID_MIRO             0x1031
-#define PCI_DEVICE_ID_MIRO_36050       0x5601
-#define PCI_DEVICE_ID_MIRO_DC10PLUS    0x7efe
-#define PCI_DEVICE_ID_MIRO_DC30PLUS    0xd801
-
-#define PCI_VENDOR_ID_NEC              0x1033
-#define PCI_DEVICE_ID_NEC_CBUS_1       0x0001 /* PCI-Cbus Bridge */
-#define PCI_DEVICE_ID_NEC_LOCAL                0x0002 /* Local Bridge */
-#define PCI_DEVICE_ID_NEC_ATM          0x0003 /* ATM LAN Controller */
-#define PCI_DEVICE_ID_NEC_R4000                0x0004 /* R4000 Bridge */
-#define PCI_DEVICE_ID_NEC_486          0x0005 /* 486 Like Peripheral Bus Bridge */
-#define PCI_DEVICE_ID_NEC_ACCEL_1      0x0006 /* Graphic Accelerator */
-#define PCI_DEVICE_ID_NEC_UXBUS                0x0007 /* UX-Bus Bridge */
-#define PCI_DEVICE_ID_NEC_ACCEL_2      0x0008 /* Graphic Accelerator */
-#define PCI_DEVICE_ID_NEC_GRAPH                0x0009 /* PCI-CoreGraph Bridge */
-#define PCI_DEVICE_ID_NEC_VL           0x0016 /* PCI-VL Bridge */
-#define PCI_DEVICE_ID_NEC_STARALPHA2   0x002c /* STAR ALPHA2 */
-#define PCI_DEVICE_ID_NEC_CBUS_2       0x002d /* PCI-Cbus Bridge */
-#define PCI_DEVICE_ID_NEC_USB          0x0035 /* PCI-USB Host */
-#define PCI_DEVICE_ID_NEC_CBUS_3       0x003b
-#define PCI_DEVICE_ID_NEC_NAPCCARD     0x003e
-#define PCI_DEVICE_ID_NEC_PCX2         0x0046 /* PowerVR */
-#define PCI_DEVICE_ID_NEC_VRC5476       0x009b
-#define PCI_DEVICE_ID_NEC_VRC4173      0x00a5
-#define PCI_DEVICE_ID_NEC_VRC5477_AC97  0x00a6
-#define PCI_DEVICE_ID_NEC_PC9821CS01    0x800c /* PC-9821-CS01 */
-#define PCI_DEVICE_ID_NEC_PC9821NRB06   0x800d /* PC-9821NR-B06 */
-
-#define PCI_VENDOR_ID_FD               0x1036
-#define PCI_DEVICE_ID_FD_36C70         0x0000
-
-#define PCI_VENDOR_ID_SI               0x1039
-#define PCI_DEVICE_ID_SI_5591_AGP      0x0001
-#define PCI_DEVICE_ID_SI_6202          0x0002
-#define PCI_DEVICE_ID_SI_503           0x0008
-#define PCI_DEVICE_ID_SI_ACPI          0x0009
-#define PCI_DEVICE_ID_SI_SMBUS         0x0016
-#define PCI_DEVICE_ID_SI_LPC           0x0018
-#define PCI_DEVICE_ID_SI_5597_VGA      0x0200
-#define PCI_DEVICE_ID_SI_6205          0x0205
-#define PCI_DEVICE_ID_SI_501           0x0406
-#define PCI_DEVICE_ID_SI_496           0x0496
-#define PCI_DEVICE_ID_SI_300           0x0300
-#define PCI_DEVICE_ID_SI_315H          0x0310
-#define PCI_DEVICE_ID_SI_315           0x0315
-#define PCI_DEVICE_ID_SI_315PRO                0x0325
-#define PCI_DEVICE_ID_SI_530           0x0530
-#define PCI_DEVICE_ID_SI_540           0x0540
-#define PCI_DEVICE_ID_SI_550           0x0550
-#define PCI_DEVICE_ID_SI_540_VGA       0x5300
-#define PCI_DEVICE_ID_SI_550_VGA       0x5315
-#define PCI_DEVICE_ID_SI_620           0x0620
-#define PCI_DEVICE_ID_SI_630           0x0630
-#define PCI_DEVICE_ID_SI_633           0x0633
-#define PCI_DEVICE_ID_SI_635           0x0635
-#define PCI_DEVICE_ID_SI_640           0x0640
-#define PCI_DEVICE_ID_SI_645           0x0645
-#define PCI_DEVICE_ID_SI_646           0x0646
-#define PCI_DEVICE_ID_SI_648           0x0648
-#define PCI_DEVICE_ID_SI_650           0x0650
-#define PCI_DEVICE_ID_SI_651           0x0651
-#define PCI_DEVICE_ID_SI_655           0x0655
-#define PCI_DEVICE_ID_SI_661           0x0661
-#define PCI_DEVICE_ID_SI_730           0x0730
-#define PCI_DEVICE_ID_SI_733           0x0733
-#define PCI_DEVICE_ID_SI_630_VGA       0x6300
-#define PCI_DEVICE_ID_SI_735           0x0735
-#define PCI_DEVICE_ID_SI_740           0x0740
-#define PCI_DEVICE_ID_SI_741           0x0741
-#define PCI_DEVICE_ID_SI_745           0x0745
-#define PCI_DEVICE_ID_SI_746           0x0746
-#define PCI_DEVICE_ID_SI_755           0x0755
-#define PCI_DEVICE_ID_SI_760           0x0760
-#define PCI_DEVICE_ID_SI_900           0x0900
-#define PCI_DEVICE_ID_SI_961           0x0961
-#define PCI_DEVICE_ID_SI_962           0x0962
-#define PCI_DEVICE_ID_SI_963           0x0963
-#define PCI_DEVICE_ID_SI_965           0x0965
-#define PCI_DEVICE_ID_SI_966           0x0966
-#define PCI_DEVICE_ID_SI_968           0x0968
-#define PCI_DEVICE_ID_SI_1180          0x1180
-#define PCI_DEVICE_ID_SI_5511          0x5511
-#define PCI_DEVICE_ID_SI_5513          0x5513
-#define PCI_DEVICE_ID_SI_5517          0x5517
-#define PCI_DEVICE_ID_SI_5518          0x5518
-#define PCI_DEVICE_ID_SI_5571          0x5571
-#define PCI_DEVICE_ID_SI_5581          0x5581
-#define PCI_DEVICE_ID_SI_5582          0x5582
-#define PCI_DEVICE_ID_SI_5591          0x5591
-#define PCI_DEVICE_ID_SI_5596          0x5596
-#define PCI_DEVICE_ID_SI_5597          0x5597
-#define PCI_DEVICE_ID_SI_5598          0x5598
-#define PCI_DEVICE_ID_SI_5600          0x5600
-#define PCI_DEVICE_ID_SI_7012          0x7012
-#define PCI_DEVICE_ID_SI_7013          0x7013
-#define PCI_DEVICE_ID_SI_7016          0x7016
-#define PCI_DEVICE_ID_SI_7018          0x7018
-
-#define PCI_VENDOR_ID_HP               0x103c
-#define PCI_DEVICE_ID_HP_VISUALIZE_EG  0x1005
-#define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006
-#define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008
-#define PCI_DEVICE_ID_HP_VISUALIZE_FX2 0x100a
-#define PCI_DEVICE_ID_HP_TACHYON       0x1028
-#define PCI_DEVICE_ID_HP_TACHLITE      0x1029
-#define PCI_DEVICE_ID_HP_J2585A                0x1030
-#define PCI_DEVICE_ID_HP_J2585B                0x1031
-#define PCI_DEVICE_ID_HP_J2973A                0x1040
-#define PCI_DEVICE_ID_HP_J2970A                0x1042
-#define PCI_DEVICE_ID_HP_DIVA          0x1048
-#define PCI_DEVICE_ID_HP_DIVA_TOSCA1   0x1049
-#define PCI_DEVICE_ID_HP_DIVA_TOSCA2   0x104A
-#define PCI_DEVICE_ID_HP_DIVA_MAESTRO  0x104B
-#define PCI_DEVICE_ID_HP_REO_IOC       0x10f1
-#define PCI_DEVICE_ID_HP_VISUALIZE_FXE 0x108b
-#define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223
-#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226
-#define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227
-#define PCI_DEVICE_ID_HP_ZX1_IOC       0x122a
-#define PCI_DEVICE_ID_HP_PCIX_LBA      0x122e
-#define PCI_DEVICE_ID_HP_SX1000_IOC    0x127c
-#define PCI_DEVICE_ID_HP_DIVA_EVEREST  0x1282
-#define PCI_DEVICE_ID_HP_DIVA_AUX      0x1290
-#define PCI_DEVICE_ID_HP_DIVA_RMP3     0x1301
-#define PCI_DEVICE_ID_HP_DIVA_HURRICANE        0x132a
-#define PCI_DEVICE_ID_HP_CISSA         0x3220
-#define PCI_DEVICE_ID_HP_CISSC         0x3230
-#define PCI_DEVICE_ID_HP_CISSD         0x3238
-#define PCI_DEVICE_ID_HP_CISSE         0x323a
-#define PCI_DEVICE_ID_HP_ZX2_IOC       0x4031
-
-#define PCI_VENDOR_ID_PCTECH           0x1042
-#define PCI_DEVICE_ID_PCTECH_RZ1000    0x1000
-#define PCI_DEVICE_ID_PCTECH_RZ1001    0x1001
-#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
-
-#define PCI_VENDOR_ID_ASUSTEK          0x1043
-#define PCI_DEVICE_ID_ASUSTEK_0675     0x0675
-
-#define PCI_VENDOR_ID_DPT              0x1044
-#define PCI_DEVICE_ID_DPT              0xa400
-
-#define PCI_VENDOR_ID_OPTI             0x1045
-#define PCI_DEVICE_ID_OPTI_82C558      0xc558
-#define PCI_DEVICE_ID_OPTI_82C621      0xc621
-#define PCI_DEVICE_ID_OPTI_82C700      0xc700
-#define PCI_DEVICE_ID_OPTI_82C825      0xd568
-
-#define PCI_VENDOR_ID_ELSA             0x1048
-#define PCI_DEVICE_ID_ELSA_MICROLINK   0x1000
-#define PCI_DEVICE_ID_ELSA_QS3000      0x3000
-
-#define PCI_VENDOR_ID_BUSLOGIC               0x104B
-#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
-#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER    0x1040
-#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT     0x8130
-
-#define PCI_VENDOR_ID_TI               0x104c
-#define PCI_DEVICE_ID_TI_TVP4020       0x3d07
-#define PCI_DEVICE_ID_TI_4450          0x8011
-#define PCI_DEVICE_ID_TI_TSB43AB22     0x8023
-#define PCI_DEVICE_ID_TI_XX21_XX11     0x8031
-#define PCI_DEVICE_ID_TI_XX21_XX11_FM  0x8033
-#define PCI_DEVICE_ID_TI_XX21_XX11_SD  0x8034
-#define PCI_DEVICE_ID_TI_X515          0x8036
-#define PCI_DEVICE_ID_TI_XX12          0x8039
-#define PCI_DEVICE_ID_TI_XX12_FM       0x803b
-#define PCI_DEVICE_ID_TI_1130          0xac12
-#define PCI_DEVICE_ID_TI_1031          0xac13
-#define PCI_DEVICE_ID_TI_1131          0xac15
-#define PCI_DEVICE_ID_TI_1250          0xac16
-#define PCI_DEVICE_ID_TI_1220          0xac17
-#define PCI_DEVICE_ID_TI_1221          0xac19
-#define PCI_DEVICE_ID_TI_1210          0xac1a
-#define PCI_DEVICE_ID_TI_1450          0xac1b
-#define PCI_DEVICE_ID_TI_1225          0xac1c
-#define PCI_DEVICE_ID_TI_1251A         0xac1d
-#define PCI_DEVICE_ID_TI_1211          0xac1e
-#define PCI_DEVICE_ID_TI_1251B         0xac1f
-#define PCI_DEVICE_ID_TI_4410          0xac41
-#define PCI_DEVICE_ID_TI_4451          0xac42
-#define PCI_DEVICE_ID_TI_4510          0xac44
-#define PCI_DEVICE_ID_TI_4520          0xac46
-#define PCI_DEVICE_ID_TI_7510          0xac47
-#define PCI_DEVICE_ID_TI_7610          0xac48
-#define PCI_DEVICE_ID_TI_7410          0xac49
-#define PCI_DEVICE_ID_TI_1410          0xac50
-#define PCI_DEVICE_ID_TI_1420          0xac51
-#define PCI_DEVICE_ID_TI_1451A         0xac52
-#define PCI_DEVICE_ID_TI_1620          0xac54
-#define PCI_DEVICE_ID_TI_1520          0xac55
-#define PCI_DEVICE_ID_TI_1510          0xac56
-#define PCI_DEVICE_ID_TI_X620          0xac8d
-#define PCI_DEVICE_ID_TI_X420          0xac8e
-#define PCI_DEVICE_ID_TI_XX20_FM       0xac8f
-
-#define PCI_VENDOR_ID_SONY             0x104d
-
-/* Winbond have two vendor IDs! See 0x10ad as well */
-#define PCI_VENDOR_ID_WINBOND2         0x1050
-#define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a
-#define PCI_DEVICE_ID_WINBOND2_6692    0x6692
-
-#define PCI_VENDOR_ID_ANIGMA           0x1051
-#define PCI_DEVICE_ID_ANIGMA_MC145575  0x0100
-  
-#define PCI_VENDOR_ID_EFAR             0x1055
-#define PCI_DEVICE_ID_EFAR_SLC90E66_1  0x9130
-#define PCI_DEVICE_ID_EFAR_SLC90E66_3  0x9463
-
-#define PCI_VENDOR_ID_MOTOROLA         0x1057
-#define PCI_DEVICE_ID_MOTOROLA_MPC105  0x0001
-#define PCI_DEVICE_ID_MOTOROLA_MPC106  0x0002
-#define PCI_DEVICE_ID_MOTOROLA_MPC107  0x0004
-#define PCI_DEVICE_ID_MOTOROLA_RAVEN   0x4801
-#define PCI_DEVICE_ID_MOTOROLA_FALCON  0x4802
-#define PCI_DEVICE_ID_MOTOROLA_HAWK    0x4803
-#define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b
-#define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803
-#define PCI_DEVICE_ID_MOTOROLA_MPC5200B        0x5809
-
-#define PCI_VENDOR_ID_PROMISE          0x105a
-#define PCI_DEVICE_ID_PROMISE_20265    0x0d30
-#define PCI_DEVICE_ID_PROMISE_20267    0x4d30
-#define PCI_DEVICE_ID_PROMISE_20246    0x4d33
-#define PCI_DEVICE_ID_PROMISE_20262    0x4d38
-#define PCI_DEVICE_ID_PROMISE_20263    0x0D38
-#define PCI_DEVICE_ID_PROMISE_20268    0x4d68
-#define PCI_DEVICE_ID_PROMISE_20269    0x4d69
-#define PCI_DEVICE_ID_PROMISE_20270    0x6268
-#define PCI_DEVICE_ID_PROMISE_20271    0x6269
-#define PCI_DEVICE_ID_PROMISE_20275    0x1275
-#define PCI_DEVICE_ID_PROMISE_20276    0x5275
-#define PCI_DEVICE_ID_PROMISE_20277    0x7275
-
-#define PCI_VENDOR_ID_UMC              0x1060
-#define PCI_DEVICE_ID_UMC_UM8673F      0x0101
-#define PCI_DEVICE_ID_UMC_UM8886BF     0x673a
-#define PCI_DEVICE_ID_UMC_UM8886A      0x886a
-
-#define PCI_VENDOR_ID_PICOPOWER                0x1066
-#define PCI_DEVICE_ID_PICOPOWER_PT86C523       0x0002
-#define PCI_DEVICE_ID_PICOPOWER_PT86C523BBP    0x8002
-
-#define PCI_VENDOR_ID_MYLEX            0x1069
-#define PCI_DEVICE_ID_MYLEX_DAC960_P   0x0001
-#define PCI_DEVICE_ID_MYLEX_DAC960_PD  0x0002
-#define PCI_DEVICE_ID_MYLEX_DAC960_PG  0x0010
-#define PCI_DEVICE_ID_MYLEX_DAC960_LA  0x0020
-#define PCI_DEVICE_ID_MYLEX_DAC960_LP  0x0050
-#define PCI_DEVICE_ID_MYLEX_DAC960_BA  0xBA56
-#define PCI_DEVICE_ID_MYLEX_DAC960_GEM 0xB166
-
-#define PCI_VENDOR_ID_APPLE            0x106b
-#define PCI_DEVICE_ID_APPLE_BANDIT     0x0001
-#define PCI_DEVICE_ID_APPLE_HYDRA      0x000e
-#define PCI_DEVICE_ID_APPLE_UNI_N_FW   0x0018
-#define PCI_DEVICE_ID_APPLE_UNI_N_AGP  0x0020
-#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021
-#define PCI_DEVICE_ID_APPLE_UNI_N_GMACP        0x0024
-#define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P        0x0027
-#define PCI_DEVICE_ID_APPLE_UNI_N_AGP15        0x002d
-#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15        0x002e
-#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2        0x0032
-#define PCI_DEVICE_ID_APPLE_UNI_N_ATA  0x0033
-#define PCI_DEVICE_ID_APPLE_UNI_N_AGP2 0x0034
-#define PCI_DEVICE_ID_APPLE_IPID_ATA100        0x003b
-#define PCI_DEVICE_ID_APPLE_K2_ATA100  0x0043
-#define PCI_DEVICE_ID_APPLE_U3_AGP     0x004b
-#define PCI_DEVICE_ID_APPLE_K2_GMAC    0x004c
-#define PCI_DEVICE_ID_APPLE_SH_ATA      0x0050
-#define PCI_DEVICE_ID_APPLE_SH_SUNGEM   0x0051
-#define PCI_DEVICE_ID_APPLE_U3L_AGP    0x0058
-#define PCI_DEVICE_ID_APPLE_U3H_AGP    0x0059
-#define PCI_DEVICE_ID_APPLE_IPID2_AGP  0x0066
-#define PCI_DEVICE_ID_APPLE_IPID2_ATA  0x0069
-#define PCI_DEVICE_ID_APPLE_IPID2_FW   0x006a
-#define PCI_DEVICE_ID_APPLE_IPID2_GMAC 0x006b
-#define PCI_DEVICE_ID_APPLE_TIGON3     0x1645
-
-#define PCI_VENDOR_ID_YAMAHA           0x1073
-#define PCI_DEVICE_ID_YAMAHA_724       0x0004
-#define PCI_DEVICE_ID_YAMAHA_724F      0x000d
-#define PCI_DEVICE_ID_YAMAHA_740       0x000a
-#define PCI_DEVICE_ID_YAMAHA_740C      0x000c
-#define PCI_DEVICE_ID_YAMAHA_744       0x0010
-#define PCI_DEVICE_ID_YAMAHA_754       0x0012
-
-#define PCI_VENDOR_ID_QLOGIC           0x1077
-#define PCI_DEVICE_ID_QLOGIC_ISP10160  0x1016
-#define PCI_DEVICE_ID_QLOGIC_ISP1020   0x1020
-#define PCI_DEVICE_ID_QLOGIC_ISP1080   0x1080
-#define PCI_DEVICE_ID_QLOGIC_ISP12160  0x1216
-#define PCI_DEVICE_ID_QLOGIC_ISP1240   0x1240
-#define PCI_DEVICE_ID_QLOGIC_ISP1280   0x1280
-#define PCI_DEVICE_ID_QLOGIC_ISP2100   0x2100
-#define PCI_DEVICE_ID_QLOGIC_ISP2200   0x2200
-#define PCI_DEVICE_ID_QLOGIC_ISP2300   0x2300
-#define PCI_DEVICE_ID_QLOGIC_ISP2312   0x2312
-#define PCI_DEVICE_ID_QLOGIC_ISP2322   0x2322
-#define PCI_DEVICE_ID_QLOGIC_ISP6312   0x6312
-#define PCI_DEVICE_ID_QLOGIC_ISP6322   0x6322
-#define PCI_DEVICE_ID_QLOGIC_ISP2422   0x2422
-#define PCI_DEVICE_ID_QLOGIC_ISP2432   0x2432
-#define PCI_DEVICE_ID_QLOGIC_ISP2512   0x2512
-#define PCI_DEVICE_ID_QLOGIC_ISP2522   0x2522
-#define PCI_DEVICE_ID_QLOGIC_ISP5422   0x5422
-#define PCI_DEVICE_ID_QLOGIC_ISP5432   0x5432
-
-#define PCI_VENDOR_ID_CYRIX            0x1078
-#define PCI_DEVICE_ID_CYRIX_5510       0x0000
-#define PCI_DEVICE_ID_CYRIX_PCI_MASTER 0x0001
-#define PCI_DEVICE_ID_CYRIX_5520       0x0002
-#define PCI_DEVICE_ID_CYRIX_5530_LEGACY        0x0100
-#define PCI_DEVICE_ID_CYRIX_5530_IDE   0x0102
-#define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103
-#define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104
-
-#define PCI_VENDOR_ID_CONTAQ           0x1080
-#define PCI_DEVICE_ID_CONTAQ_82C693    0xc693
-
-#define PCI_VENDOR_ID_OLICOM           0x108d
-#define PCI_DEVICE_ID_OLICOM_OC2325    0x0012
-#define PCI_DEVICE_ID_OLICOM_OC2183    0x0013
-#define PCI_DEVICE_ID_OLICOM_OC2326    0x0014
-
-#define PCI_VENDOR_ID_SUN              0x108e
-#define PCI_DEVICE_ID_SUN_EBUS         0x1000
-#define PCI_DEVICE_ID_SUN_HAPPYMEAL    0x1001
-#define PCI_DEVICE_ID_SUN_RIO_EBUS     0x1100
-#define PCI_DEVICE_ID_SUN_RIO_GEM      0x1101
-#define PCI_DEVICE_ID_SUN_RIO_1394     0x1102
-#define PCI_DEVICE_ID_SUN_RIO_USB      0x1103
-#define PCI_DEVICE_ID_SUN_GEM          0x2bad
-#define PCI_DEVICE_ID_SUN_SIMBA                0x5000
-#define PCI_DEVICE_ID_SUN_PBM          0x8000
-#define PCI_DEVICE_ID_SUN_SCHIZO       0x8001
-#define PCI_DEVICE_ID_SUN_SABRE                0xa000
-#define PCI_DEVICE_ID_SUN_HUMMINGBIRD  0xa001
-#define PCI_DEVICE_ID_SUN_TOMATILLO    0xa801
-#define PCI_DEVICE_ID_SUN_CASSINI      0xabba
-
-#define PCI_VENDOR_ID_CMD              0x1095
-#define PCI_DEVICE_ID_CMD_643          0x0643
-#define PCI_DEVICE_ID_CMD_646          0x0646
-#define PCI_DEVICE_ID_CMD_648          0x0648
-#define PCI_DEVICE_ID_CMD_649          0x0649
-
-#define PCI_DEVICE_ID_SII_680          0x0680
-#define PCI_DEVICE_ID_SII_3112         0x3112
-#define PCI_DEVICE_ID_SII_1210SA       0x0240
-
-#define PCI_VENDOR_ID_BROOKTREE                0x109e
-#define PCI_DEVICE_ID_BROOKTREE_878    0x0878
-#define PCI_DEVICE_ID_BROOKTREE_879    0x0879
-
-#define PCI_VENDOR_ID_SGI              0x10a9
-#define PCI_DEVICE_ID_SGI_IOC3         0x0003
-#define PCI_DEVICE_ID_SGI_LITHIUM      0x1002
-#define PCI_DEVICE_ID_SGI_IOC4         0x100a
-
-#define PCI_VENDOR_ID_WINBOND          0x10ad
-#define PCI_DEVICE_ID_WINBOND_82C105   0x0105
-#define PCI_DEVICE_ID_WINBOND_83C553   0x0565
-
-#define PCI_VENDOR_ID_PLX              0x10b5
-#define PCI_DEVICE_ID_PLX_R685         0x1030
-#define PCI_DEVICE_ID_PLX_ROMULUS      0x106a
-#define PCI_DEVICE_ID_PLX_SPCOM800     0x1076
-#define PCI_DEVICE_ID_PLX_1077         0x1077
-#define PCI_DEVICE_ID_PLX_SPCOM200     0x1103
-#define PCI_DEVICE_ID_PLX_DJINN_ITOO   0x1151
-#define PCI_DEVICE_ID_PLX_R753         0x1152
-#define PCI_DEVICE_ID_PLX_OLITEC       0x1187
-#define PCI_DEVICE_ID_PLX_PCI200SYN    0x3196
-#define PCI_DEVICE_ID_PLX_9030          0x9030
-#define PCI_DEVICE_ID_PLX_9050         0x9050
-#define PCI_DEVICE_ID_PLX_9080         0x9080
-#define PCI_DEVICE_ID_PLX_GTEK_SERIAL2 0xa001
-
-#define PCI_VENDOR_ID_MADGE            0x10b6
-#define PCI_DEVICE_ID_MADGE_MK2                0x0002
-
-#define PCI_VENDOR_ID_3COM             0x10b7
-#define PCI_DEVICE_ID_3COM_3C985       0x0001
-#define PCI_DEVICE_ID_3COM_3C940       0x1700
-#define PCI_DEVICE_ID_3COM_3C339       0x3390
-#define PCI_DEVICE_ID_3COM_3C359       0x3590
-#define PCI_DEVICE_ID_3COM_3C940B      0x80eb
-#define PCI_DEVICE_ID_3COM_3CR990      0x9900
-#define PCI_DEVICE_ID_3COM_3CR990_TX_95        0x9902
-#define PCI_DEVICE_ID_3COM_3CR990_TX_97        0x9903
-#define PCI_DEVICE_ID_3COM_3CR990B     0x9904
-#define PCI_DEVICE_ID_3COM_3CR990_FX   0x9905
-#define PCI_DEVICE_ID_3COM_3CR990SVR95 0x9908
-#define PCI_DEVICE_ID_3COM_3CR990SVR97 0x9909
-#define PCI_DEVICE_ID_3COM_3CR990SVR   0x990a
-
-#define PCI_VENDOR_ID_AL               0x10b9
-#define PCI_DEVICE_ID_AL_M1533         0x1533
-#define PCI_DEVICE_ID_AL_M1535                 0x1535
-#define PCI_DEVICE_ID_AL_M1541         0x1541
-#define PCI_DEVICE_ID_AL_M1563         0x1563
-#define PCI_DEVICE_ID_AL_M1621         0x1621
-#define PCI_DEVICE_ID_AL_M1631         0x1631
-#define PCI_DEVICE_ID_AL_M1632         0x1632
-#define PCI_DEVICE_ID_AL_M1641         0x1641
-#define PCI_DEVICE_ID_AL_M1644         0x1644
-#define PCI_DEVICE_ID_AL_M1647         0x1647
-#define PCI_DEVICE_ID_AL_M1651         0x1651
-#define PCI_DEVICE_ID_AL_M1671         0x1671
-#define PCI_DEVICE_ID_AL_M1681         0x1681
-#define PCI_DEVICE_ID_AL_M1683         0x1683
-#define PCI_DEVICE_ID_AL_M1689         0x1689
-#define PCI_DEVICE_ID_AL_M5219         0x5219
-#define PCI_DEVICE_ID_AL_M5228         0x5228
-#define PCI_DEVICE_ID_AL_M5229         0x5229
-#define PCI_DEVICE_ID_AL_M5451         0x5451
-#define PCI_DEVICE_ID_AL_M7101         0x7101
-
-#define PCI_VENDOR_ID_NEOMAGIC         0x10c8
-#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
-#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
-#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
-
-#define PCI_VENDOR_ID_TCONRAD          0x10da
-#define PCI_DEVICE_ID_TCONRAD_TOKENRING        0x0508
-
-#define PCI_VENDOR_ID_NVIDIA                   0x10de
-#define PCI_DEVICE_ID_NVIDIA_TNT               0x0020
-#define PCI_DEVICE_ID_NVIDIA_TNT2              0x0028
-#define PCI_DEVICE_ID_NVIDIA_UTNT2             0x0029
-#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN        0x002a
-#define PCI_DEVICE_ID_NVIDIA_VTNT2             0x002C
-#define PCI_DEVICE_ID_NVIDIA_UVTNT2            0x002D
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS        0x0034
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE  0x0035
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA 0x0036
-#define PCI_DEVICE_ID_NVIDIA_NVENET_10         0x0037
-#define PCI_DEVICE_ID_NVIDIA_NVENET_11         0x0038
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2        0x003e
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800       0x0041
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE    0x0042
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT    0x0045
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000     0x004E
-#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS     0x0052
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE  0x0053
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA 0x0054
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2        0x0055
-#define PCI_DEVICE_ID_NVIDIA_NVENET_8          0x0056
-#define PCI_DEVICE_ID_NVIDIA_NVENET_9          0x0057
-#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO       0x0059
-#define PCI_DEVICE_ID_NVIDIA_CK804_PCIE                0x005d
-#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS     0x0064
-#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE       0x0065
-#define PCI_DEVICE_ID_NVIDIA_NVENET_2          0x0066
-#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM                0x0069
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO                0x006a
-#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS    0x0084
-#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE      0x0085
-#define PCI_DEVICE_ID_NVIDIA_NVENET_4          0x0086
-#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM       0x0089
-#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO         0x008a
-#define PCI_DEVICE_ID_NVIDIA_NVENET_5          0x008c
-#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA     0x008e
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT   0x0090
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX  0x0091
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800   0x0098
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX 0x0099
-#define PCI_DEVICE_ID_NVIDIA_ITNT2             0x00A0
-#define PCI_DEVICE_ID_GEFORCE_6800A             0x00c1
-#define PCI_DEVICE_ID_GEFORCE_6800A_LE          0x00c2
-#define PCI_DEVICE_ID_GEFORCE_GO_6800           0x00c8
-#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA     0x00c9
-#define PCI_DEVICE_ID_QUADRO_FX_GO1400          0x00cc
-#define PCI_DEVICE_ID_QUADRO_FX_1400            0x00ce
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3           0x00d1
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS     0x00d4
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE       0x00d5
-#define PCI_DEVICE_ID_NVIDIA_NVENET_3          0x00d6
-#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM                0x00d9
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO                0x00da
-#define PCI_DEVICE_ID_NVIDIA_NVENET_7          0x00df
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3S          0x00e1
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA     0x00e3
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS    0x00e4
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE      0x00e5
-#define PCI_DEVICE_ID_NVIDIA_NVENET_6          0x00e6
-#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO                0x00ea
-#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2    0x00ee
-#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0
-#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1 0x00f1
-#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2
-#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3
-#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT   0x00f9
-#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280    0x00fd
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR       0x0100
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR       0x0101
-#define PCI_DEVICE_ID_NVIDIA_QUADRO            0x0103
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX       0x0110
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2      0x0111
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO       0x0112
-#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR       0x0113
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT   0x0140
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600      0x0141
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL   0x0145
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540     0x014E
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200      0x014F
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS      0x0150
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2     0x0151
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA    0x0152
-#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO       0x0153
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200    0x0164
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250    0x0166
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1  0x0167
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1  0x0168
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460   0x0170
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440   0x0171
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420   0x0172
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE        0x0173
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO   0x0174
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO   0x0175
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO    0x0177
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL    0x0178
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_200       0x017A
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL    0x017B
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL  0x017C
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000   0x0185
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO    0x0186
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO    0x0187
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL    0x0188
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC    0x0189
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS    0x018A
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL    0x018B
-#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2         0x01a0
-#define PCI_DEVICE_ID_NVIDIA_NFORCE            0x01a4
-#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO                0x01b1
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS      0x01b4
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE                0x01bc
-#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM                0x01c1
-#define PCI_DEVICE_ID_NVIDIA_NVENET_1          0x01c3
-#define PCI_DEVICE_ID_NVIDIA_NFORCE2           0x01e0
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE3          0x0200
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1                0x0201
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2                0x0202
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC                0x0203
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B      0x0211
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE   0x0212
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT   0x0215
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600  0x0250
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400  0x0251
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200  0x0253
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL    0x0258
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL    0x0259
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL    0x025B
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS        0x0264
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE  0x0265
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2        0x0267
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS        0x0368
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE  0x036E
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2        0x037F
-#define PCI_DEVICE_ID_NVIDIA_NVENET_12         0x0268
-#define PCI_DEVICE_ID_NVIDIA_NVENET_13         0x0269
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800  0x0280
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X    0x0281
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE     0x0282
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO       0x0286
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL        0x0288
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL        0x0289
-#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL       0x028C
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA  0x0301
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800        0x0302
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000         0x0308
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000         0x0309
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA  0x0311
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600        0x0312
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE      0x0314
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600      0x031A
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650      0x031B
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700        0x031C
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200        0x0320
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA  0x0321
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1      0x0322
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE      0x0323
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200      0x0324
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250      0x0325
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500        0x0326
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100        0x0327
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32   0x0328
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200            0x0329
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI     0x032A
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500          0x032B
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300      0x032C
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100      0x032D
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA  0x0330
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900        0x0331
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT      0x0332
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA  0x0333
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT      0x0334
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000         0x0338
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700          0x033F
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA  0x0341
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700        0x0342
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE      0x0343
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE      0x0344
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1    0x0347
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2    0x0348
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000       0x034C
-#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
-#define PCI_DEVICE_ID_NVIDIA_NVENET_14              0x0372
-#define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
-#define PCI_DEVICE_ID_NVIDIA_NVENET_16              0x03E5
-#define PCI_DEVICE_ID_NVIDIA_NVENET_17              0x03E6
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA      0x03E7
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS            0x03EB
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE       0x03EC
-#define PCI_DEVICE_ID_NVIDIA_NVENET_18              0x03EE
-#define PCI_DEVICE_ID_NVIDIA_NVENET_19              0x03EF
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2     0x03F6
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3     0x03F7
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS            0x0446
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE      0x0448
-#define PCI_DEVICE_ID_NVIDIA_NVENET_20              0x0450
-#define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
-#define PCI_DEVICE_ID_NVIDIA_NVENET_22              0x0452
-#define PCI_DEVICE_ID_NVIDIA_NVENET_23              0x0453
-#define PCI_DEVICE_ID_NVIDIA_NVENET_24              0x054C
-#define PCI_DEVICE_ID_NVIDIA_NVENET_25              0x054D
-#define PCI_DEVICE_ID_NVIDIA_NVENET_26              0x054E
-#define PCI_DEVICE_ID_NVIDIA_NVENET_27              0x054F
-#define PCI_DEVICE_ID_NVIDIA_NVENET_28              0x07DC
-#define PCI_DEVICE_ID_NVIDIA_NVENET_29              0x07DD
-#define PCI_DEVICE_ID_NVIDIA_NVENET_30              0x07DE
-#define PCI_DEVICE_ID_NVIDIA_NVENET_31              0x07DF
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE       0x0560
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE       0x056C
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
-#define PCI_DEVICE_ID_NVIDIA_NVENET_32              0x0760
-#define PCI_DEVICE_ID_NVIDIA_NVENET_33              0x0761
-#define PCI_DEVICE_ID_NVIDIA_NVENET_34              0x0762
-#define PCI_DEVICE_ID_NVIDIA_NVENET_35              0x0763
-#define PCI_DEVICE_ID_NVIDIA_NVENET_36              0x0AB0
-#define PCI_DEVICE_ID_NVIDIA_NVENET_37              0x0AB1
-#define PCI_DEVICE_ID_NVIDIA_NVENET_38              0x0AB2
-#define PCI_DEVICE_ID_NVIDIA_NVENET_39              0x0AB3
-
-#define PCI_VENDOR_ID_IMS              0x10e0
-#define PCI_DEVICE_ID_IMS_TT128                0x9128
-#define PCI_DEVICE_ID_IMS_TT3D         0x9135
-
-#define PCI_VENDOR_ID_INTERG           0x10ea
-#define PCI_DEVICE_ID_INTERG_1682      0x1682
-#define PCI_DEVICE_ID_INTERG_2000      0x2000
-#define PCI_DEVICE_ID_INTERG_2010      0x2010
-#define PCI_DEVICE_ID_INTERG_5000      0x5000
-#define PCI_DEVICE_ID_INTERG_5050      0x5050
-
-#define PCI_VENDOR_ID_REALTEK          0x10ec
-#define PCI_DEVICE_ID_REALTEK_8139     0x8139
-
-#define PCI_VENDOR_ID_XILINX           0x10ee
-#define PCI_DEVICE_ID_RME_DIGI96       0x3fc0
-#define PCI_DEVICE_ID_RME_DIGI96_8     0x3fc1
-#define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2
-#define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
-
-#define PCI_VENDOR_ID_INIT             0x1101
-
-#define PCI_VENDOR_ID_CREATIVE         0x1102 /* duplicate: ECTIVA */
-#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
-
-#define PCI_VENDOR_ID_ECTIVA           0x1102 /* duplicate: CREATIVE */
-#define PCI_DEVICE_ID_ECTIVA_EV1938    0x8938
-
-#define PCI_VENDOR_ID_TTI              0x1103
-#define PCI_DEVICE_ID_TTI_HPT343       0x0003
-#define PCI_DEVICE_ID_TTI_HPT366       0x0004
-#define PCI_DEVICE_ID_TTI_HPT372       0x0005
-#define PCI_DEVICE_ID_TTI_HPT302       0x0006
-#define PCI_DEVICE_ID_TTI_HPT371       0x0007
-#define PCI_DEVICE_ID_TTI_HPT374       0x0008
-#define PCI_DEVICE_ID_TTI_HPT372N      0x0009  /* apparently a 372N variant? */
-
-#define PCI_VENDOR_ID_VIA              0x1106
-#define PCI_DEVICE_ID_VIA_8763_0       0x0198
-#define PCI_DEVICE_ID_VIA_8380_0       0x0204
-#define PCI_DEVICE_ID_VIA_3238_0       0x0238
-#define PCI_DEVICE_ID_VIA_PT880                0x0258
-#define PCI_DEVICE_ID_VIA_PT880ULTRA   0x0308
-#define PCI_DEVICE_ID_VIA_PX8X0_0      0x0259
-#define PCI_DEVICE_ID_VIA_3269_0       0x0269
-#define PCI_DEVICE_ID_VIA_K8T800PRO_0  0x0282
-#define PCI_DEVICE_ID_VIA_3296_0       0x0296
-#define PCI_DEVICE_ID_VIA_8363_0       0x0305
-#define PCI_DEVICE_ID_VIA_P4M800CE     0x0314
-#define PCI_DEVICE_ID_VIA_P4M890       0x0327
-#define PCI_DEVICE_ID_VIA_VT3324       0x0324
-#define PCI_DEVICE_ID_VIA_VT3336       0x0336
-#define PCI_DEVICE_ID_VIA_VT3351       0x0351
-#define PCI_DEVICE_ID_VIA_VT3364       0x0364
-#define PCI_DEVICE_ID_VIA_8371_0       0x0391
-#define PCI_DEVICE_ID_VIA_8501_0       0x0501
-#define PCI_DEVICE_ID_VIA_82C561       0x0561
-#define PCI_DEVICE_ID_VIA_82C586_1     0x0571
-#define PCI_DEVICE_ID_VIA_82C576       0x0576
-#define PCI_DEVICE_ID_VIA_82C586_0     0x0586
-#define PCI_DEVICE_ID_VIA_82C596       0x0596
-#define PCI_DEVICE_ID_VIA_82C597_0     0x0597
-#define PCI_DEVICE_ID_VIA_82C598_0     0x0598
-#define PCI_DEVICE_ID_VIA_8601_0       0x0601
-#define PCI_DEVICE_ID_VIA_8605_0       0x0605
-#define PCI_DEVICE_ID_VIA_82C686       0x0686
-#define PCI_DEVICE_ID_VIA_82C691_0     0x0691
-#define PCI_DEVICE_ID_VIA_82C576_1     0x1571
-#define PCI_DEVICE_ID_VIA_82C586_2     0x3038
-#define PCI_DEVICE_ID_VIA_82C586_3     0x3040
-#define PCI_DEVICE_ID_VIA_82C596_3     0x3050
-#define PCI_DEVICE_ID_VIA_82C596B_3    0x3051
-#define PCI_DEVICE_ID_VIA_82C686_4     0x3057
-#define PCI_DEVICE_ID_VIA_82C686_5     0x3058
-#define PCI_DEVICE_ID_VIA_8233_5       0x3059
-#define PCI_DEVICE_ID_VIA_8233_0       0x3074
-#define PCI_DEVICE_ID_VIA_8633_0       0x3091
-#define PCI_DEVICE_ID_VIA_8367_0       0x3099
-#define PCI_DEVICE_ID_VIA_8653_0       0x3101
-#define PCI_DEVICE_ID_VIA_8622         0x3102
-#define PCI_DEVICE_ID_VIA_8235_USB_2   0x3104
-#define PCI_DEVICE_ID_VIA_8233C_0      0x3109
-#define PCI_DEVICE_ID_VIA_8361         0x3112
-#define PCI_DEVICE_ID_VIA_XM266                0x3116
-#define PCI_DEVICE_ID_VIA_612X         0x3119
-#define PCI_DEVICE_ID_VIA_862X_0       0x3123
-#define PCI_DEVICE_ID_VIA_8753_0       0x3128
-#define PCI_DEVICE_ID_VIA_8233A                0x3147
-#define PCI_DEVICE_ID_VIA_8703_51_0    0x3148
-#define PCI_DEVICE_ID_VIA_8237_SATA    0x3149
-#define PCI_DEVICE_ID_VIA_XN266                0x3156
-#define PCI_DEVICE_ID_VIA_6410         0x3164
-#define PCI_DEVICE_ID_VIA_8754C_0      0x3168
-#define PCI_DEVICE_ID_VIA_8235         0x3177
-#define PCI_DEVICE_ID_VIA_8385_0       0x3188
-#define PCI_DEVICE_ID_VIA_8377_0       0x3189
-#define PCI_DEVICE_ID_VIA_8378_0       0x3205
-#define PCI_DEVICE_ID_VIA_8783_0       0x3208
-#define PCI_DEVICE_ID_VIA_8237         0x3227
-#define PCI_DEVICE_ID_VIA_8251         0x3287
-#define PCI_DEVICE_ID_VIA_8237A                0x3337
-#define PCI_DEVICE_ID_VIA_8237S                0x3372
-#define PCI_DEVICE_ID_VIA_SATA_EIDE    0x5324
-#define PCI_DEVICE_ID_VIA_8231         0x8231
-#define PCI_DEVICE_ID_VIA_8231_4       0x8235
-#define PCI_DEVICE_ID_VIA_8365_1       0x8305
-#define PCI_DEVICE_ID_VIA_CX700                0x8324
-#define PCI_DEVICE_ID_VIA_CX700_IDE    0x0581
-#define PCI_DEVICE_ID_VIA_VX800                0x8353
-#define PCI_DEVICE_ID_VIA_8371_1       0x8391
-#define PCI_DEVICE_ID_VIA_82C598_1     0x8598
-#define PCI_DEVICE_ID_VIA_838X_1       0xB188
-#define PCI_DEVICE_ID_VIA_83_87XX_1    0xB198
-
-#define PCI_VENDOR_ID_SIEMENS           0x110A
-#define PCI_DEVICE_ID_SIEMENS_DSCC4     0x2102
-
-#define PCI_VENDOR_ID_VORTEX           0x1119
-#define PCI_DEVICE_ID_VORTEX_GDT60x0   0x0000
-#define PCI_DEVICE_ID_VORTEX_GDT6000B  0x0001
-#define PCI_DEVICE_ID_VORTEX_GDT6x10   0x0002
-#define PCI_DEVICE_ID_VORTEX_GDT6x20   0x0003
-#define PCI_DEVICE_ID_VORTEX_GDT6530   0x0004
-#define PCI_DEVICE_ID_VORTEX_GDT6550   0x0005
-#define PCI_DEVICE_ID_VORTEX_GDT6x17   0x0006
-#define PCI_DEVICE_ID_VORTEX_GDT6x27   0x0007
-#define PCI_DEVICE_ID_VORTEX_GDT6537   0x0008
-#define PCI_DEVICE_ID_VORTEX_GDT6557   0x0009
-#define PCI_DEVICE_ID_VORTEX_GDT6x15   0x000a
-#define PCI_DEVICE_ID_VORTEX_GDT6x25   0x000b
-#define PCI_DEVICE_ID_VORTEX_GDT6535   0x000c
-#define PCI_DEVICE_ID_VORTEX_GDT6555   0x000d
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP 0x0100
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP 0x0101
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP 0x0102
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP 0x0103
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x0104
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x0105
-
-#define PCI_VENDOR_ID_EF               0x111a
-#define PCI_DEVICE_ID_EF_ATM_FPGA      0x0000
-#define PCI_DEVICE_ID_EF_ATM_ASIC      0x0002
-#define PCI_DEVICE_ID_EF_ATM_LANAI2    0x0003
-#define PCI_DEVICE_ID_EF_ATM_LANAIHB   0x0005
-
-#define PCI_VENDOR_ID_IDT              0x111d
-#define PCI_DEVICE_ID_IDT_IDT77201     0x0001
-
-#define PCI_VENDOR_ID_FORE             0x1127
-#define PCI_DEVICE_ID_FORE_PCA200E     0x0300
-
-#define PCI_VENDOR_ID_PHILIPS          0x1131
-#define PCI_DEVICE_ID_PHILIPS_SAA7146  0x7146
-#define PCI_DEVICE_ID_PHILIPS_SAA9730  0x9730
-
-#define PCI_VENDOR_ID_EICON            0x1133
-#define PCI_DEVICE_ID_EICON_DIVA20     0xe002
-#define PCI_DEVICE_ID_EICON_DIVA20_U   0xe004
-#define PCI_DEVICE_ID_EICON_DIVA201    0xe005
-#define PCI_DEVICE_ID_EICON_DIVA202    0xe00b
-#define PCI_DEVICE_ID_EICON_MAESTRA    0xe010
-#define PCI_DEVICE_ID_EICON_MAESTRAQ   0xe012
-#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
-#define PCI_DEVICE_ID_EICON_MAESTRAP   0xe014
-
-#define PCI_VENDOR_ID_CISCO            0x1137
-
-#define PCI_VENDOR_ID_ZIATECH          0x1138
-#define PCI_DEVICE_ID_ZIATECH_5550_HC  0x5550
-
-#define PCI_VENDOR_ID_SYSKONNECT       0x1148
-#define PCI_DEVICE_ID_SYSKONNECT_TR    0x4200
-#define PCI_DEVICE_ID_SYSKONNECT_GE    0x4300
-#define PCI_DEVICE_ID_SYSKONNECT_YU    0x4320
-#define PCI_DEVICE_ID_SYSKONNECT_9DXX  0x4400
-#define PCI_DEVICE_ID_SYSKONNECT_9MXX  0x4500
-
-#define PCI_VENDOR_ID_DIGI             0x114f
-#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
-#define PCI_DEVICE_ID_DIGI_DF_M_E      0x0071
-#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
-#define PCI_DEVICE_ID_DIGI_DF_M_A      0x0073
-#define PCI_DEVICE_ID_NEO_2DB9          0x00C8
-#define PCI_DEVICE_ID_NEO_2DB9PRI       0x00C9
-#define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
-#define PCI_DEVICE_ID_NEO_2RJ45PRI      0x00CB
-#define PCIE_DEVICE_ID_NEO_4_IBM        0x00F4
-
-#define PCI_VENDOR_ID_XIRCOM           0x115d
-#define PCI_DEVICE_ID_XIRCOM_RBM56G    0x0101
-#define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103
-
-#define PCI_VENDOR_ID_SERVERWORKS        0x1166
-#define PCI_DEVICE_ID_SERVERWORKS_HE     0x0008
-#define PCI_DEVICE_ID_SERVERWORKS_LE     0x0009
-#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
-#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB   0x0036
-#define PCI_DEVICE_ID_SERVERWORKS_EPB    0x0103
-#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE  0x0132
-#define PCI_DEVICE_ID_SERVERWORKS_OSB4   0x0200
-#define PCI_DEVICE_ID_SERVERWORKS_CSB5   0x0201
-#define PCI_DEVICE_ID_SERVERWORKS_CSB6    0x0203
-#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205
-#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211
-#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212
-#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213
-#define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
-#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
-#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
-
-#define PCI_VENDOR_ID_SBE              0x1176
-#define PCI_DEVICE_ID_SBE_WANXL100     0x0301
-#define PCI_DEVICE_ID_SBE_WANXL200     0x0302
-#define PCI_DEVICE_ID_SBE_WANXL400     0x0104
-
-#define PCI_VENDOR_ID_TOSHIBA          0x1179
-#define PCI_DEVICE_ID_TOSHIBA_PICCOLO  0x0102
-#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_1        0x0103
-#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_2        0x0105
-#define PCI_DEVICE_ID_TOSHIBA_TOPIC95  0x060a
-#define PCI_DEVICE_ID_TOSHIBA_TOPIC97  0x060f
-#define PCI_DEVICE_ID_TOSHIBA_TOPIC100 0x0617
-
-#define PCI_VENDOR_ID_TOSHIBA_2                0x102f
-#define PCI_DEVICE_ID_TOSHIBA_TC35815CF        0x0030
-#define PCI_DEVICE_ID_TOSHIBA_TC35815_NWU      0x0031
-#define PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939   0x0032
-#define PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE     0x0105
-#define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC    0x0108
-#define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3
-
-#define PCI_VENDOR_ID_ATTO             0x117c
-
-#define PCI_VENDOR_ID_RICOH            0x1180
-#define PCI_DEVICE_ID_RICOH_RL5C465    0x0465
-#define PCI_DEVICE_ID_RICOH_RL5C466    0x0466
-#define PCI_DEVICE_ID_RICOH_RL5C475    0x0475
-#define PCI_DEVICE_ID_RICOH_RL5C476    0x0476
-#define PCI_DEVICE_ID_RICOH_RL5C478    0x0478
-#define PCI_DEVICE_ID_RICOH_R5C822     0x0822
-#define PCI_DEVICE_ID_RICOH_R5C832     0x0832
-#define PCI_DEVICE_ID_RICOH_R5C843     0x0843
-
-#define PCI_VENDOR_ID_DLINK            0x1186
-#define PCI_DEVICE_ID_DLINK_DGE510T    0x4c00
-
-#define PCI_VENDOR_ID_ARTOP            0x1191
-#define PCI_DEVICE_ID_ARTOP_ATP850UF   0x0005
-#define PCI_DEVICE_ID_ARTOP_ATP860     0x0006
-#define PCI_DEVICE_ID_ARTOP_ATP860R    0x0007
-#define PCI_DEVICE_ID_ARTOP_ATP865     0x0008
-#define PCI_DEVICE_ID_ARTOP_ATP865R    0x0009
-#define PCI_DEVICE_ID_ARTOP_AEC7610    0x8002
-#define PCI_DEVICE_ID_ARTOP_AEC7612UW  0x8010
-#define PCI_DEVICE_ID_ARTOP_AEC7612U   0x8020
-#define PCI_DEVICE_ID_ARTOP_AEC7612S   0x8030
-#define PCI_DEVICE_ID_ARTOP_AEC7612D   0x8040
-#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050
-#define PCI_DEVICE_ID_ARTOP_8060       0x8060
-
-#define PCI_VENDOR_ID_ZEITNET          0x1193
-#define PCI_DEVICE_ID_ZEITNET_1221     0x0001
-#define PCI_DEVICE_ID_ZEITNET_1225     0x0002
-
-#define PCI_VENDOR_ID_FUJITSU_ME       0x119e
-#define PCI_DEVICE_ID_FUJITSU_FS155    0x0001
-#define PCI_DEVICE_ID_FUJITSU_FS50     0x0003
-
-#define PCI_SUBVENDOR_ID_KEYSPAN       0x11a9
-#define PCI_SUBDEVICE_ID_KEYSPAN_SX2   0x5334
-
-#define PCI_VENDOR_ID_MARVELL          0x11ab
-#define PCI_DEVICE_ID_MARVELL_GT64111  0x4146
-#define PCI_DEVICE_ID_MARVELL_GT64260  0x6430
-#define PCI_DEVICE_ID_MARVELL_MV64360  0x6460
-#define PCI_DEVICE_ID_MARVELL_MV64460  0x6480
-#define PCI_DEVICE_ID_MARVELL_88ALP01_NAND     0x4100
-#define PCI_DEVICE_ID_MARVELL_88ALP01_SD       0x4101
-#define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC     0x4102
-
-#define PCI_VENDOR_ID_V3               0x11b0
-#define PCI_DEVICE_ID_V3_V960          0x0001
-#define PCI_DEVICE_ID_V3_V351          0x0002
-
-#define PCI_VENDOR_ID_ATT              0x11c1
-#define PCI_DEVICE_ID_ATT_VENUS_MODEM  0x480
-
-#define PCI_VENDOR_ID_SPECIALIX                0x11cb
-#define PCI_DEVICE_ID_SPECIALIX_IO8    0x2000
-#define PCI_DEVICE_ID_SPECIALIX_RIO    0x8000
-#define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004
-
-#define PCI_VENDOR_ID_ANALOG_DEVICES   0x11d4
-#define PCI_DEVICE_ID_AD1889JS         0x1889
-
-#define PCI_DEVICE_ID_SEGA_BBA         0x1234
-
-#define PCI_VENDOR_ID_ZORAN            0x11de
-#define PCI_DEVICE_ID_ZORAN_36057      0x6057
-#define PCI_DEVICE_ID_ZORAN_36120      0x6120
-
-#define PCI_VENDOR_ID_COMPEX           0x11f6
-#define PCI_DEVICE_ID_COMPEX_ENET100VG4        0x0112
-
-#define PCI_VENDOR_ID_RP               0x11fe
-#define PCI_DEVICE_ID_RP32INTF         0x0001
-#define PCI_DEVICE_ID_RP8INTF          0x0002
-#define PCI_DEVICE_ID_RP16INTF         0x0003
-#define PCI_DEVICE_ID_RP4QUAD          0x0004
-#define PCI_DEVICE_ID_RP8OCTA          0x0005
-#define PCI_DEVICE_ID_RP8J             0x0006
-#define PCI_DEVICE_ID_RP4J             0x0007
-#define PCI_DEVICE_ID_RP8SNI           0x0008  
-#define PCI_DEVICE_ID_RP16SNI          0x0009  
-#define PCI_DEVICE_ID_RPP4             0x000A
-#define PCI_DEVICE_ID_RPP8             0x000B
-#define PCI_DEVICE_ID_RP4M             0x000D
-#define PCI_DEVICE_ID_RP2_232          0x000E
-#define PCI_DEVICE_ID_RP2_422          0x000F
-#define PCI_DEVICE_ID_URP32INTF                0x0801
-#define PCI_DEVICE_ID_URP8INTF         0x0802
-#define PCI_DEVICE_ID_URP16INTF                0x0803
-#define PCI_DEVICE_ID_URP8OCTA         0x0805
-#define PCI_DEVICE_ID_UPCI_RM3_8PORT   0x080C       
-#define PCI_DEVICE_ID_UPCI_RM3_4PORT   0x080D
-#define PCI_DEVICE_ID_CRP16INTF                0x0903       
-
-#define PCI_VENDOR_ID_CYCLADES         0x120e
-#define PCI_DEVICE_ID_CYCLOM_Y_Lo      0x0100
-#define PCI_DEVICE_ID_CYCLOM_Y_Hi      0x0101
-#define PCI_DEVICE_ID_CYCLOM_4Y_Lo     0x0102
-#define PCI_DEVICE_ID_CYCLOM_4Y_Hi     0x0103
-#define PCI_DEVICE_ID_CYCLOM_8Y_Lo     0x0104
-#define PCI_DEVICE_ID_CYCLOM_8Y_Hi     0x0105
-#define PCI_DEVICE_ID_CYCLOM_Z_Lo      0x0200
-#define PCI_DEVICE_ID_CYCLOM_Z_Hi      0x0201
-#define PCI_DEVICE_ID_PC300_RX_2       0x0300
-#define PCI_DEVICE_ID_PC300_RX_1       0x0301
-#define PCI_DEVICE_ID_PC300_TE_2       0x0310
-#define PCI_DEVICE_ID_PC300_TE_1       0x0311
-#define PCI_DEVICE_ID_PC300_TE_M_2     0x0320
-#define PCI_DEVICE_ID_PC300_TE_M_1     0x0321
-
-#define PCI_VENDOR_ID_ESSENTIAL                0x120f
-#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER     0x0001
-
-#define PCI_VENDOR_ID_O2               0x1217
-#define PCI_DEVICE_ID_O2_6729          0x6729
-#define PCI_DEVICE_ID_O2_6730          0x673a
-#define PCI_DEVICE_ID_O2_6832          0x6832
-#define PCI_DEVICE_ID_O2_6836          0x6836
-
-#define PCI_VENDOR_ID_3DFX             0x121a
-#define PCI_DEVICE_ID_3DFX_VOODOO      0x0001
-#define PCI_DEVICE_ID_3DFX_VOODOO2     0x0002
-#define PCI_DEVICE_ID_3DFX_BANSHEE     0x0003
-#define PCI_DEVICE_ID_3DFX_VOODOO3     0x0005
-#define PCI_DEVICE_ID_3DFX_VOODOO5     0x0009
-
-#define PCI_VENDOR_ID_AVM              0x1244
-#define PCI_DEVICE_ID_AVM_B1           0x0700
-#define PCI_DEVICE_ID_AVM_C4           0x0800
-#define PCI_DEVICE_ID_AVM_A1           0x0a00
-#define PCI_DEVICE_ID_AVM_A1_V2                0x0e00
-#define PCI_DEVICE_ID_AVM_C2           0x1100
-#define PCI_DEVICE_ID_AVM_T1           0x1200
-
-#define PCI_VENDOR_ID_STALLION         0x124d
-
-/* Allied Telesyn */
-#define PCI_VENDOR_ID_AT               0x1259
-#define PCI_SUBDEVICE_ID_AT_2700FX     0x2701
-#define PCI_SUBDEVICE_ID_AT_2701FX     0x2703
-
-#define PCI_VENDOR_ID_ESS              0x125d
-#define PCI_DEVICE_ID_ESS_ESS1968      0x1968
-#define PCI_DEVICE_ID_ESS_ESS1978      0x1978
-#define PCI_DEVICE_ID_ESS_ALLEGRO_1    0x1988
-#define PCI_DEVICE_ID_ESS_ALLEGRO      0x1989
-#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990
-#define PCI_DEVICE_ID_ESS_CANYON3D_2   0x1992
-#define PCI_DEVICE_ID_ESS_MAESTRO3     0x1998
-#define PCI_DEVICE_ID_ESS_MAESTRO3_1   0x1999
-#define PCI_DEVICE_ID_ESS_MAESTRO3_HW  0x199a
-#define PCI_DEVICE_ID_ESS_MAESTRO3_2   0x199b
-
-#define PCI_VENDOR_ID_SATSAGEM         0x1267
-#define PCI_DEVICE_ID_SATSAGEM_NICCY   0x1016
-
-#define PCI_VENDOR_ID_ENSONIQ          0x1274
-#define PCI_DEVICE_ID_ENSONIQ_CT5880   0x5880
-#define PCI_DEVICE_ID_ENSONIQ_ES1370   0x5000
-#define PCI_DEVICE_ID_ENSONIQ_ES1371   0x1371
-
-#define PCI_VENDOR_ID_TRANSMETA                0x1279
-#define PCI_DEVICE_ID_EFFICEON         0x0060
-
-#define PCI_VENDOR_ID_ROCKWELL         0x127A
-
-#define PCI_VENDOR_ID_ITE              0x1283
-#define PCI_DEVICE_ID_ITE_8211         0x8211
-#define PCI_DEVICE_ID_ITE_8212         0x8212
-#define PCI_DEVICE_ID_ITE_8213         0x8213
-#define PCI_DEVICE_ID_ITE_8152         0x8152
-#define PCI_DEVICE_ID_ITE_8872         0x8872
-#define PCI_DEVICE_ID_ITE_IT8330G_0    0xe886
-
-/* formerly Platform Tech */
-#define PCI_DEVICE_ID_ESS_ESS0100      0x0100
-
-#define PCI_VENDOR_ID_ALTEON           0x12ae
-
-#define PCI_SUBVENDOR_ID_CONNECT_TECH                  0x12c4
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232          0x0001
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232          0x0002
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232          0x0003
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485          0x0004
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4      0x0005
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485          0x0006
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2      0x0007
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485          0x0008
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6      0x0009
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1       0x000A
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1       0x000B
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ                0x000C
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_PTM          0x000D
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_NT960PCI         0x0100
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2          0x0201
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4          0x0202
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232   0x0300
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232   0x0301
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232   0x0302
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1     0x0310
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2     0x0311
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4     0x0312
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2       0x0320
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4       0x0321
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8       0x0322
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485   0x0330
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485   0x0331
-#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485   0x0332
-
-#define PCI_VENDOR_ID_NVIDIA_SGS       0x12d2
-#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
-
-#define PCI_SUBVENDOR_ID_CHASE_PCIFAST         0x12E0
-#define PCI_SUBDEVICE_ID_CHASE_PCIFAST4                0x0031
-#define PCI_SUBDEVICE_ID_CHASE_PCIFAST8                0x0021
-#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16       0x0011
-#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC    0x0041
-#define PCI_SUBVENDOR_ID_CHASE_PCIRAS          0x124D
-#define PCI_SUBDEVICE_ID_CHASE_PCIRAS4         0xF001
-#define PCI_SUBDEVICE_ID_CHASE_PCIRAS8         0xF010
-
-#define PCI_VENDOR_ID_AUREAL           0x12eb
-#define PCI_DEVICE_ID_AUREAL_VORTEX_1  0x0001
-#define PCI_DEVICE_ID_AUREAL_VORTEX_2  0x0002
-#define PCI_DEVICE_ID_AUREAL_ADVANTAGE 0x0003
-
-#define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8
-#define PCI_DEVICE_ID_LML_33R10                0x8a02
-
-#define PCI_VENDOR_ID_ESDGMBH          0x12fe
-#define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111
-
-#define PCI_VENDOR_ID_SIIG             0x131f
-#define PCI_SUBVENDOR_ID_SIIG          0x131f
-#define PCI_DEVICE_ID_SIIG_1S_10x_550  0x1000
-#define PCI_DEVICE_ID_SIIG_1S_10x_650  0x1001
-#define PCI_DEVICE_ID_SIIG_1S_10x_850  0x1002
-#define PCI_DEVICE_ID_SIIG_1S1P_10x_550        0x1010
-#define PCI_DEVICE_ID_SIIG_1S1P_10x_650        0x1011
-#define PCI_DEVICE_ID_SIIG_1S1P_10x_850        0x1012
-#define PCI_DEVICE_ID_SIIG_1P_10x      0x1020
-#define PCI_DEVICE_ID_SIIG_2P_10x      0x1021
-#define PCI_DEVICE_ID_SIIG_2S_10x_550  0x1030
-#define PCI_DEVICE_ID_SIIG_2S_10x_650  0x1031
-#define PCI_DEVICE_ID_SIIG_2S_10x_850  0x1032
-#define PCI_DEVICE_ID_SIIG_2S1P_10x_550        0x1034
-#define PCI_DEVICE_ID_SIIG_2S1P_10x_650        0x1035
-#define PCI_DEVICE_ID_SIIG_2S1P_10x_850        0x1036
-#define PCI_DEVICE_ID_SIIG_4S_10x_550  0x1050
-#define PCI_DEVICE_ID_SIIG_4S_10x_650  0x1051
-#define PCI_DEVICE_ID_SIIG_4S_10x_850  0x1052
-#define PCI_DEVICE_ID_SIIG_1S_20x_550  0x2000
-#define PCI_DEVICE_ID_SIIG_1S_20x_650  0x2001
-#define PCI_DEVICE_ID_SIIG_1S_20x_850  0x2002
-#define PCI_DEVICE_ID_SIIG_1P_20x      0x2020
-#define PCI_DEVICE_ID_SIIG_2P_20x      0x2021
-#define PCI_DEVICE_ID_SIIG_2S_20x_550  0x2030
-#define PCI_DEVICE_ID_SIIG_2S_20x_650  0x2031
-#define PCI_DEVICE_ID_SIIG_2S_20x_850  0x2032
-#define PCI_DEVICE_ID_SIIG_2P1S_20x_550        0x2040
-#define PCI_DEVICE_ID_SIIG_2P1S_20x_650        0x2041
-#define PCI_DEVICE_ID_SIIG_2P1S_20x_850        0x2042
-#define PCI_DEVICE_ID_SIIG_1S1P_20x_550        0x2010
-#define PCI_DEVICE_ID_SIIG_1S1P_20x_650        0x2011
-#define PCI_DEVICE_ID_SIIG_1S1P_20x_850        0x2012
-#define PCI_DEVICE_ID_SIIG_4S_20x_550  0x2050
-#define PCI_DEVICE_ID_SIIG_4S_20x_650  0x2051
-#define PCI_DEVICE_ID_SIIG_4S_20x_850  0x2052
-#define PCI_DEVICE_ID_SIIG_2S1P_20x_550        0x2060
-#define PCI_DEVICE_ID_SIIG_2S1P_20x_650        0x2061
-#define PCI_DEVICE_ID_SIIG_2S1P_20x_850        0x2062
-#define PCI_DEVICE_ID_SIIG_8S_20x_550  0x2080
-#define PCI_DEVICE_ID_SIIG_8S_20x_650  0x2081
-#define PCI_DEVICE_ID_SIIG_8S_20x_850  0x2082
-#define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL   0x2050
-
-#define PCI_VENDOR_ID_RADISYS          0x1331
-
-#define PCI_VENDOR_ID_MICRO_MEMORY             0x1332
-#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN      0x5415
-#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN      0x5425
-#define PCI_DEVICE_ID_MICRO_MEMORY_6155                0x6155
-
-#define PCI_VENDOR_ID_DOMEX            0x134a
-#define PCI_DEVICE_ID_DOMEX_DMX3191D   0x0001
-
-#define PCI_VENDOR_ID_INTASHIELD       0x135a
-#define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80
-#define PCI_DEVICE_ID_INTASHIELD_IS400 0x0dc0
-
-#define PCI_VENDOR_ID_QUATECH          0x135C
-#define PCI_DEVICE_ID_QUATECH_QSC100   0x0010
-#define PCI_DEVICE_ID_QUATECH_DSC100   0x0020
-#define PCI_DEVICE_ID_QUATECH_ESC100D  0x0050
-#define PCI_DEVICE_ID_QUATECH_ESC100M  0x0060
-#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
-
-#define PCI_VENDOR_ID_SEALEVEL         0x135e
-#define PCI_DEVICE_ID_SEALEVEL_U530    0x7101
-#define PCI_DEVICE_ID_SEALEVEL_UCOMM2  0x7201
-#define PCI_DEVICE_ID_SEALEVEL_UCOMM422        0x7402
-#define PCI_DEVICE_ID_SEALEVEL_UCOMM232        0x7202
-#define PCI_DEVICE_ID_SEALEVEL_COMM4   0x7401
-#define PCI_DEVICE_ID_SEALEVEL_COMM8   0x7801
-#define PCI_DEVICE_ID_SEALEVEL_UCOMM8  0x7804
-
-#define PCI_VENDOR_ID_HYPERCOPE                0x1365
-#define PCI_DEVICE_ID_HYPERCOPE_PLX    0x9050
-#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO    0x0104
-#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO                0x0106
-#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO       0x0107
-#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2      0x0108
-
-#define PCI_VENDOR_ID_KAWASAKI         0x136b
-#define PCI_DEVICE_ID_MCHIP_KL5A72002  0xff01
-
-#define PCI_VENDOR_ID_CNET             0x1371
-#define PCI_DEVICE_ID_CNET_GIGACARD    0x434e
-
-#define PCI_VENDOR_ID_LMC              0x1376
-#define PCI_DEVICE_ID_LMC_HSSI         0x0003
-#define PCI_DEVICE_ID_LMC_DS3          0x0004
-#define PCI_DEVICE_ID_LMC_SSI          0x0005
-#define PCI_DEVICE_ID_LMC_T1           0x0006
-
-#define PCI_VENDOR_ID_NETGEAR          0x1385
-#define PCI_DEVICE_ID_NETGEAR_GA620    0x620a
-
-#define PCI_VENDOR_ID_APPLICOM         0x1389
-#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
-#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
-#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
-
-#define PCI_VENDOR_ID_MOXA             0x1393
-#define PCI_DEVICE_ID_MOXA_RC7000      0x0001
-#define PCI_DEVICE_ID_MOXA_CP102       0x1020
-#define PCI_DEVICE_ID_MOXA_CP102UL     0x1021
-#define PCI_DEVICE_ID_MOXA_CP102U      0x1022
-#define PCI_DEVICE_ID_MOXA_C104                0x1040
-#define PCI_DEVICE_ID_MOXA_CP104U      0x1041
-#define PCI_DEVICE_ID_MOXA_CP104JU     0x1042
-#define PCI_DEVICE_ID_MOXA_CP104EL     0x1043
-#define PCI_DEVICE_ID_MOXA_CT114       0x1140
-#define PCI_DEVICE_ID_MOXA_CP114       0x1141
-#define PCI_DEVICE_ID_MOXA_CP118U      0x1180
-#define PCI_DEVICE_ID_MOXA_CP118EL     0x1181
-#define PCI_DEVICE_ID_MOXA_CP132       0x1320
-#define PCI_DEVICE_ID_MOXA_CP132U      0x1321
-#define PCI_DEVICE_ID_MOXA_CP134U      0x1340
-#define PCI_DEVICE_ID_MOXA_C168                0x1680
-#define PCI_DEVICE_ID_MOXA_CP168U      0x1681
-#define PCI_DEVICE_ID_MOXA_CP168EL     0x1682
-#define PCI_DEVICE_ID_MOXA_CP204J      0x2040
-#define PCI_DEVICE_ID_MOXA_C218                0x2180
-#define PCI_DEVICE_ID_MOXA_C320                0x3200
-
-#define PCI_VENDOR_ID_CCD              0x1397
-#define PCI_DEVICE_ID_CCD_HFC4S                0x08B4
-#define PCI_SUBDEVICE_ID_CCD_PMX2S     0x1234
-#define PCI_DEVICE_ID_CCD_HFC8S                0x16B8
-#define PCI_DEVICE_ID_CCD_2BD0         0x2bd0
-#define PCI_DEVICE_ID_CCD_HFCE1                0x30B1
-#define PCI_SUBDEVICE_ID_CCD_SPD4S     0x3136
-#define PCI_SUBDEVICE_ID_CCD_SPDE1     0x3137
-#define PCI_DEVICE_ID_CCD_B000         0xb000
-#define PCI_DEVICE_ID_CCD_B006         0xb006
-#define PCI_DEVICE_ID_CCD_B007         0xb007
-#define PCI_DEVICE_ID_CCD_B008         0xb008
-#define PCI_DEVICE_ID_CCD_B009         0xb009
-#define PCI_DEVICE_ID_CCD_B00A         0xb00a
-#define PCI_DEVICE_ID_CCD_B00B         0xb00b
-#define PCI_DEVICE_ID_CCD_B00C         0xb00c
-#define PCI_DEVICE_ID_CCD_B100         0xb100
-#define PCI_SUBDEVICE_ID_CCD_IOB4ST    0xB520
-#define PCI_SUBDEVICE_ID_CCD_IOB8STR   0xB521
-#define PCI_SUBDEVICE_ID_CCD_IOB8ST    0xB522
-#define PCI_SUBDEVICE_ID_CCD_IOB1E1    0xB523
-#define PCI_SUBDEVICE_ID_CCD_SWYX4S    0xB540
-#define PCI_SUBDEVICE_ID_CCD_JH4S20    0xB550
-#define PCI_SUBDEVICE_ID_CCD_IOB8ST_1  0xB552
-#define PCI_SUBDEVICE_ID_CCD_BN4S      0xB560
-#define PCI_SUBDEVICE_ID_CCD_BN8S      0xB562
-#define PCI_SUBDEVICE_ID_CCD_BNE1      0xB563
-#define PCI_SUBDEVICE_ID_CCD_BNE1D     0xB564
-#define PCI_SUBDEVICE_ID_CCD_BNE1DP    0xB565
-#define PCI_SUBDEVICE_ID_CCD_BN2S      0xB566
-#define PCI_SUBDEVICE_ID_CCD_BN1SM     0xB567
-#define PCI_SUBDEVICE_ID_CCD_BN4SM     0xB568
-#define PCI_SUBDEVICE_ID_CCD_BN2SM     0xB569
-#define PCI_SUBDEVICE_ID_CCD_BNE1M     0xB56A
-#define PCI_SUBDEVICE_ID_CCD_BN8SP     0xB56B
-#define PCI_SUBDEVICE_ID_CCD_HFC4S     0xB620
-#define PCI_SUBDEVICE_ID_CCD_HFC8S     0xB622
-#define PCI_DEVICE_ID_CCD_B700         0xb700
-#define PCI_DEVICE_ID_CCD_B701         0xb701
-#define PCI_SUBDEVICE_ID_CCD_HFCE1     0xC523
-#define PCI_SUBDEVICE_ID_CCD_OV2S      0xE884
-#define PCI_SUBDEVICE_ID_CCD_OV4S      0xE888
-#define PCI_SUBDEVICE_ID_CCD_OV8S      0xE998
-
-#define PCI_VENDOR_ID_EXAR             0x13a8
-#define PCI_DEVICE_ID_EXAR_XR17C152    0x0152
-#define PCI_DEVICE_ID_EXAR_XR17C154    0x0154
-#define PCI_DEVICE_ID_EXAR_XR17C158    0x0158
-
-#define PCI_VENDOR_ID_MICROGATE                0x13c0
-#define PCI_DEVICE_ID_MICROGATE_USC    0x0010
-#define PCI_DEVICE_ID_MICROGATE_SCA    0x0030
-
-#define PCI_VENDOR_ID_3WARE            0x13C1
-#define PCI_DEVICE_ID_3WARE_1000       0x1000
-#define PCI_DEVICE_ID_3WARE_7000       0x1001
-#define PCI_DEVICE_ID_3WARE_9000       0x1002
-
-#define PCI_VENDOR_ID_IOMEGA           0x13ca
-#define PCI_DEVICE_ID_IOMEGA_BUZ       0x4231
-
-#define PCI_VENDOR_ID_ABOCOM           0x13D1
-#define PCI_DEVICE_ID_ABOCOM_2BD1       0x2BD1
-
-#define PCI_VENDOR_ID_SUNDANCE         0x13f0
-
-#define PCI_VENDOR_ID_CMEDIA           0x13f6
-#define PCI_DEVICE_ID_CMEDIA_CM8338A   0x0100
-#define PCI_DEVICE_ID_CMEDIA_CM8338B   0x0101
-#define PCI_DEVICE_ID_CMEDIA_CM8738    0x0111
-#define PCI_DEVICE_ID_CMEDIA_CM8738B   0x0112
-
-#define PCI_VENDOR_ID_LAVA             0x1407
-#define PCI_DEVICE_ID_LAVA_DSERIAL     0x0100 /* 2x 16550 */
-#define PCI_DEVICE_ID_LAVA_QUATRO_A    0x0101 /* 2x 16550, half of 4 port */
-#define PCI_DEVICE_ID_LAVA_QUATRO_B    0x0102 /* 2x 16550, half of 4 port */
-#define PCI_DEVICE_ID_LAVA_OCTO_A      0x0180 /* 4x 16550A, half of 8 port */
-#define PCI_DEVICE_ID_LAVA_OCTO_B      0x0181 /* 4x 16550A, half of 8 port */
-#define PCI_DEVICE_ID_LAVA_PORT_PLUS   0x0200 /* 2x 16650 */
-#define PCI_DEVICE_ID_LAVA_QUAD_A      0x0201 /* 2x 16650, half of 4 port */
-#define PCI_DEVICE_ID_LAVA_QUAD_B      0x0202 /* 2x 16650, half of 4 port */
-#define PCI_DEVICE_ID_LAVA_SSERIAL     0x0500 /* 1x 16550 */
-#define PCI_DEVICE_ID_LAVA_PORT_650    0x0600 /* 1x 16650 */
-#define PCI_DEVICE_ID_LAVA_PARALLEL    0x8000
-#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A  0x8002 /* The Lava Dual Parallel is */
-#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B  0x8003 /* two PCI devices on a card */
-#define PCI_DEVICE_ID_LAVA_BOCA_IOPPAR 0x8800
-
-#define PCI_VENDOR_ID_TIMEDIA          0x1409
-#define PCI_DEVICE_ID_TIMEDIA_1889     0x7168
-
-#define PCI_VENDOR_ID_ICE              0x1412
-#define PCI_DEVICE_ID_ICE_1712         0x1712
-#define PCI_DEVICE_ID_VT1724           0x1724
-
-#define PCI_VENDOR_ID_OXSEMI           0x1415
-#define PCI_DEVICE_ID_OXSEMI_12PCI840  0x8403
-#define PCI_DEVICE_ID_OXSEMI_PCIe840           0xC000
-#define PCI_DEVICE_ID_OXSEMI_PCIe840_G         0xC004
-#define PCI_DEVICE_ID_OXSEMI_PCIe952_0         0xC100
-#define PCI_DEVICE_ID_OXSEMI_PCIe952_0_G       0xC104
-#define PCI_DEVICE_ID_OXSEMI_PCIe952_1         0xC110
-#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_G       0xC114
-#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_U       0xC118
-#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU      0xC11C
-#define PCI_DEVICE_ID_OXSEMI_16PCI954  0x9501
-#define PCI_DEVICE_ID_OXSEMI_16PCI95N  0x9511
-#define PCI_DEVICE_ID_OXSEMI_16PCI954PP        0x9513
-#define PCI_DEVICE_ID_OXSEMI_16PCI952  0x9521
-#define PCI_DEVICE_ID_OXSEMI_16PCI952PP        0x9523
-
-#define PCI_VENDOR_ID_CHELSIO          0x1425
-
-#define PCI_VENDOR_ID_SAMSUNG          0x144d
-
-#define PCI_VENDOR_ID_MYRICOM          0x14c1
-
-#define PCI_VENDOR_ID_TITAN            0x14D2
-#define PCI_DEVICE_ID_TITAN_010L       0x8001
-#define PCI_DEVICE_ID_TITAN_100L       0x8010
-#define PCI_DEVICE_ID_TITAN_110L       0x8011
-#define PCI_DEVICE_ID_TITAN_200L       0x8020
-#define PCI_DEVICE_ID_TITAN_210L       0x8021
-#define PCI_DEVICE_ID_TITAN_400L       0x8040
-#define PCI_DEVICE_ID_TITAN_800L       0x8080
-#define PCI_DEVICE_ID_TITAN_100                0xA001
-#define PCI_DEVICE_ID_TITAN_200                0xA005
-#define PCI_DEVICE_ID_TITAN_400                0xA003
-#define PCI_DEVICE_ID_TITAN_800B       0xA004
-
-#define PCI_VENDOR_ID_PANACOM          0x14d4
-#define PCI_DEVICE_ID_PANACOM_QUADMODEM        0x0400
-#define PCI_DEVICE_ID_PANACOM_DUALMODEM        0x0402
-
-#define PCI_VENDOR_ID_SIPACKETS                0x14d9
-#define PCI_DEVICE_ID_SP1011           0x0010
-
-#define PCI_VENDOR_ID_AFAVLAB          0x14db
-#define PCI_DEVICE_ID_AFAVLAB_P028     0x2180
-#define PCI_DEVICE_ID_AFAVLAB_P030     0x2182
-#define PCI_SUBDEVICE_ID_AFAVLAB_P061          0x2150
-
-#define PCI_VENDOR_ID_BROADCOM         0x14e4
-#define PCI_DEVICE_ID_TIGON3_5752      0x1600
-#define PCI_DEVICE_ID_TIGON3_5752M     0x1601
-#define PCI_DEVICE_ID_NX2_5709         0x1639
-#define PCI_DEVICE_ID_NX2_5709S                0x163a
-#define PCI_DEVICE_ID_TIGON3_5700      0x1644
-#define PCI_DEVICE_ID_TIGON3_5701      0x1645
-#define PCI_DEVICE_ID_TIGON3_5702      0x1646
-#define PCI_DEVICE_ID_TIGON3_5703      0x1647
-#define PCI_DEVICE_ID_TIGON3_5704      0x1648
-#define PCI_DEVICE_ID_TIGON3_5704S_2   0x1649
-#define PCI_DEVICE_ID_NX2_5706         0x164a
-#define PCI_DEVICE_ID_NX2_5708         0x164c
-#define PCI_DEVICE_ID_TIGON3_5702FE    0x164d
-#define PCI_DEVICE_ID_NX2_57710                0x164e
-#define PCI_DEVICE_ID_NX2_57711                0x164f
-#define PCI_DEVICE_ID_NX2_57711E       0x1650
-#define PCI_DEVICE_ID_TIGON3_5705      0x1653
-#define PCI_DEVICE_ID_TIGON3_5705_2    0x1654
-#define PCI_DEVICE_ID_TIGON3_5720      0x1658
-#define PCI_DEVICE_ID_TIGON3_5721      0x1659
-#define PCI_DEVICE_ID_TIGON3_5722      0x165a
-#define PCI_DEVICE_ID_TIGON3_5723      0x165b
-#define PCI_DEVICE_ID_TIGON3_5705M     0x165d
-#define PCI_DEVICE_ID_TIGON3_5705M_2   0x165e
-#define PCI_DEVICE_ID_TIGON3_5714      0x1668
-#define PCI_DEVICE_ID_TIGON3_5714S     0x1669
-#define PCI_DEVICE_ID_TIGON3_5780      0x166a
-#define PCI_DEVICE_ID_TIGON3_5780S     0x166b
-#define PCI_DEVICE_ID_TIGON3_5705F     0x166e
-#define PCI_DEVICE_ID_TIGON3_5754M     0x1672
-#define PCI_DEVICE_ID_TIGON3_5755M     0x1673
-#define PCI_DEVICE_ID_TIGON3_5756      0x1674
-#define PCI_DEVICE_ID_TIGON3_5750      0x1676
-#define PCI_DEVICE_ID_TIGON3_5751      0x1677
-#define PCI_DEVICE_ID_TIGON3_5715      0x1678
-#define PCI_DEVICE_ID_TIGON3_5715S     0x1679
-#define PCI_DEVICE_ID_TIGON3_5754      0x167a
-#define PCI_DEVICE_ID_TIGON3_5755      0x167b
-#define PCI_DEVICE_ID_TIGON3_5750M     0x167c
-#define PCI_DEVICE_ID_TIGON3_5751M     0x167d
-#define PCI_DEVICE_ID_TIGON3_5751F     0x167e
-#define PCI_DEVICE_ID_TIGON3_5787F     0x167f
-#define PCI_DEVICE_ID_TIGON3_5761E     0x1680
-#define PCI_DEVICE_ID_TIGON3_5761      0x1681
-#define PCI_DEVICE_ID_TIGON3_5764      0x1684
-#define PCI_DEVICE_ID_TIGON3_5787M     0x1693
-#define PCI_DEVICE_ID_TIGON3_5782      0x1696
-#define PCI_DEVICE_ID_TIGON3_5784      0x1698
-#define PCI_DEVICE_ID_TIGON3_5785      0x1699
-#define PCI_DEVICE_ID_TIGON3_5786      0x169a
-#define PCI_DEVICE_ID_TIGON3_5787      0x169b
-#define PCI_DEVICE_ID_TIGON3_5788      0x169c
-#define PCI_DEVICE_ID_TIGON3_5789      0x169d
-#define PCI_DEVICE_ID_TIGON3_5702X     0x16a6
-#define PCI_DEVICE_ID_TIGON3_5703X     0x16a7
-#define PCI_DEVICE_ID_TIGON3_5704S     0x16a8
-#define PCI_DEVICE_ID_NX2_5706S                0x16aa
-#define PCI_DEVICE_ID_NX2_5708S                0x16ac
-#define PCI_DEVICE_ID_TIGON3_5702A3    0x16c6
-#define PCI_DEVICE_ID_TIGON3_5703A3    0x16c7
-#define PCI_DEVICE_ID_TIGON3_5781      0x16dd
-#define PCI_DEVICE_ID_TIGON3_5753      0x16f7
-#define PCI_DEVICE_ID_TIGON3_5753M     0x16fd
-#define PCI_DEVICE_ID_TIGON3_5753F     0x16fe
-#define PCI_DEVICE_ID_TIGON3_5901      0x170d
-#define PCI_DEVICE_ID_BCM4401B1                0x170c
-#define PCI_DEVICE_ID_TIGON3_5901_2    0x170e
-#define PCI_DEVICE_ID_TIGON3_5906      0x1712
-#define PCI_DEVICE_ID_TIGON3_5906M     0x1713
-#define PCI_DEVICE_ID_BCM4401          0x4401
-#define PCI_DEVICE_ID_BCM4401B0                0x4402
-
-#define PCI_VENDOR_ID_TOPIC            0x151f
-#define PCI_DEVICE_ID_TOPIC_TP560      0x0000
-
-#define PCI_VENDOR_ID_MAINPINE         0x1522
-#define PCI_DEVICE_ID_MAINPINE_PBRIDGE 0x0100
-#define PCI_VENDOR_ID_ENE              0x1524
-#define PCI_DEVICE_ID_ENE_CB712_SD     0x0550
-#define PCI_DEVICE_ID_ENE_CB712_SD_2   0x0551
-#define PCI_DEVICE_ID_ENE_CB714_SD     0x0750
-#define PCI_DEVICE_ID_ENE_CB714_SD_2   0x0751
-#define PCI_DEVICE_ID_ENE_1211         0x1211
-#define PCI_DEVICE_ID_ENE_1225         0x1225
-#define PCI_DEVICE_ID_ENE_1410         0x1410
-#define PCI_DEVICE_ID_ENE_710          0x1411
-#define PCI_DEVICE_ID_ENE_712          0x1412
-#define PCI_DEVICE_ID_ENE_1420         0x1420
-#define PCI_DEVICE_ID_ENE_720          0x1421
-#define PCI_DEVICE_ID_ENE_722          0x1422
-
-#define PCI_SUBVENDOR_ID_PERLE          0x155f
-#define PCI_SUBDEVICE_ID_PCI_RAS4       0xf001
-#define PCI_SUBDEVICE_ID_PCI_RAS8       0xf010
-
-#define PCI_VENDOR_ID_SYBA             0x1592
-#define PCI_DEVICE_ID_SYBA_2P_EPP      0x0782
-#define PCI_DEVICE_ID_SYBA_1P_ECP      0x0783
-
-#define PCI_VENDOR_ID_MORETON          0x15aa
-#define PCI_DEVICE_ID_RASTEL_2PORT     0x2000
-
-#define PCI_VENDOR_ID_ZOLTRIX          0x15b0
-#define PCI_DEVICE_ID_ZOLTRIX_2BD0     0x2bd0 
-
-#define PCI_VENDOR_ID_MELLANOX         0x15b3
-#define PCI_DEVICE_ID_MELLANOX_TAVOR   0x5a44
-#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE    0x5a46
-#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278
-#define PCI_DEVICE_ID_MELLANOX_ARBEL   0x6282
-#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
-#define PCI_DEVICE_ID_MELLANOX_SINAI   0x6274
-
-#define PCI_VENDOR_ID_QUICKNET         0x15e2
-#define PCI_DEVICE_ID_QUICKNET_XJ      0x0500
-
-/*
- * ADDI-DATA GmbH communication cards <info@addi-data.com>
- */
-#define PCI_VENDOR_ID_ADDIDATA_OLD             0x10E8
-#define PCI_VENDOR_ID_ADDIDATA                 0x15B8
-#define PCI_DEVICE_ID_ADDIDATA_APCI7500        0x7000
-#define PCI_DEVICE_ID_ADDIDATA_APCI7420        0x7001
-#define PCI_DEVICE_ID_ADDIDATA_APCI7300        0x7002
-#define PCI_DEVICE_ID_ADDIDATA_APCI7800        0x818E
-#define PCI_DEVICE_ID_ADDIDATA_APCI7500_2      0x7009
-#define PCI_DEVICE_ID_ADDIDATA_APCI7420_2      0x700A
-#define PCI_DEVICE_ID_ADDIDATA_APCI7300_2      0x700B
-#define PCI_DEVICE_ID_ADDIDATA_APCI7500_3      0x700C
-#define PCI_DEVICE_ID_ADDIDATA_APCI7420_3      0x700D
-#define PCI_DEVICE_ID_ADDIDATA_APCI7300_3      0x700E
-#define PCI_DEVICE_ID_ADDIDATA_APCI7800_3      0x700F
-
-#define PCI_VENDOR_ID_PDC              0x15e9
-
-#define PCI_VENDOR_ID_FARSITE           0x1619
-#define PCI_DEVICE_ID_FARSITE_T2P       0x0400
-#define PCI_DEVICE_ID_FARSITE_T4P       0x0440
-#define PCI_DEVICE_ID_FARSITE_T1U       0x0610
-#define PCI_DEVICE_ID_FARSITE_T2U       0x0620
-#define PCI_DEVICE_ID_FARSITE_T4U       0x0640
-#define PCI_DEVICE_ID_FARSITE_TE1       0x1610
-#define PCI_DEVICE_ID_FARSITE_TE1C      0x1612
-
-#define PCI_VENDOR_ID_ARIMA            0x161f
-
-#define PCI_VENDOR_ID_BROCADE          0x1657
-
-#define PCI_VENDOR_ID_SIBYTE           0x166d
-#define PCI_DEVICE_ID_BCM1250_PCI      0x0001
-#define PCI_DEVICE_ID_BCM1250_HT       0x0002
-
-#define PCI_VENDOR_ID_ATHEROS          0x168c
-
-#define PCI_VENDOR_ID_NETCELL          0x169c
-#define PCI_DEVICE_ID_REVOLUTION       0x0044
-
-#define PCI_VENDOR_ID_CENATEK          0x16CA
-#define PCI_DEVICE_ID_CENATEK_IDE      0x0001
-
-#define PCI_VENDOR_ID_VITESSE          0x1725
-#define PCI_DEVICE_ID_VITESSE_VSC7174  0x7174
-
-#define PCI_VENDOR_ID_LINKSYS          0x1737
-#define PCI_DEVICE_ID_LINKSYS_EG1064   0x1064
-
-#define PCI_VENDOR_ID_ALTIMA           0x173b
-#define PCI_DEVICE_ID_ALTIMA_AC1000    0x03e8
-#define PCI_DEVICE_ID_ALTIMA_AC1001    0x03e9
-#define PCI_DEVICE_ID_ALTIMA_AC9100    0x03ea
-#define PCI_DEVICE_ID_ALTIMA_AC1003    0x03eb
-
-#define PCI_VENDOR_ID_BELKIN           0x1799
-#define PCI_DEVICE_ID_BELKIN_F5D7010V7 0x701f
-
-#define PCI_VENDOR_ID_RDC              0x17f3
-#define PCI_DEVICE_ID_RDC_R6020                0x6020
-#define PCI_DEVICE_ID_RDC_R6030                0x6030
-#define PCI_DEVICE_ID_RDC_R6040                0x6040
-#define PCI_DEVICE_ID_RDC_R6060                0x6060
-#define PCI_DEVICE_ID_RDC_R6061                0x6061
-
-#define PCI_VENDOR_ID_LENOVO           0x17aa
-
-#define PCI_VENDOR_ID_ARECA            0x17d3
-#define PCI_DEVICE_ID_ARECA_1110       0x1110
-#define PCI_DEVICE_ID_ARECA_1120       0x1120
-#define PCI_DEVICE_ID_ARECA_1130       0x1130
-#define PCI_DEVICE_ID_ARECA_1160       0x1160
-#define PCI_DEVICE_ID_ARECA_1170       0x1170
-#define PCI_DEVICE_ID_ARECA_1200       0x1200
-#define PCI_DEVICE_ID_ARECA_1201       0x1201
-#define PCI_DEVICE_ID_ARECA_1202       0x1202
-#define PCI_DEVICE_ID_ARECA_1210       0x1210
-#define PCI_DEVICE_ID_ARECA_1220       0x1220
-#define PCI_DEVICE_ID_ARECA_1230       0x1230
-#define PCI_DEVICE_ID_ARECA_1260       0x1260
-#define PCI_DEVICE_ID_ARECA_1270       0x1270
-#define PCI_DEVICE_ID_ARECA_1280       0x1280
-#define PCI_DEVICE_ID_ARECA_1380       0x1380
-#define PCI_DEVICE_ID_ARECA_1381       0x1381
-#define PCI_DEVICE_ID_ARECA_1680       0x1680
-#define PCI_DEVICE_ID_ARECA_1681       0x1681
-
-#define PCI_VENDOR_ID_S2IO             0x17d5
-#define        PCI_DEVICE_ID_S2IO_WIN          0x5731
-#define        PCI_DEVICE_ID_S2IO_UNI          0x5831
-#define PCI_DEVICE_ID_HERC_WIN         0x5732
-#define PCI_DEVICE_ID_HERC_UNI         0x5832
-
-#define PCI_VENDOR_ID_SITECOM          0x182d
-#define PCI_DEVICE_ID_SITECOM_DC105V2  0x3069
-
-#define PCI_VENDOR_ID_TOPSPIN          0x1867
-
-#define PCI_VENDOR_ID_TDI               0x192E
-#define PCI_DEVICE_ID_TDI_EHCI          0x0101
-
-#define PCI_VENDOR_ID_FREESCALE                0x1957
-#define PCI_DEVICE_ID_MPC8548E         0x0012
-#define PCI_DEVICE_ID_MPC8548          0x0013
-#define PCI_DEVICE_ID_MPC8543E         0x0014
-#define PCI_DEVICE_ID_MPC8543          0x0015
-#define PCI_DEVICE_ID_MPC8547E         0x0018
-#define PCI_DEVICE_ID_MPC8545E         0x0019
-#define PCI_DEVICE_ID_MPC8545          0x001a
-#define PCI_DEVICE_ID_MPC8568E         0x0020
-#define PCI_DEVICE_ID_MPC8568          0x0021
-#define PCI_DEVICE_ID_MPC8567E         0x0022
-#define PCI_DEVICE_ID_MPC8567          0x0023
-#define PCI_DEVICE_ID_MPC8533E         0x0030
-#define PCI_DEVICE_ID_MPC8533          0x0031
-#define PCI_DEVICE_ID_MPC8544E         0x0032
-#define PCI_DEVICE_ID_MPC8544          0x0033
-#define PCI_DEVICE_ID_MPC8572E         0x0040
-#define PCI_DEVICE_ID_MPC8572          0x0041
-#define PCI_DEVICE_ID_MPC8536E         0x0050
-#define PCI_DEVICE_ID_MPC8536          0x0051
-#define PCI_DEVICE_ID_MPC8641          0x7010
-#define PCI_DEVICE_ID_MPC8641D         0x7011
-#define PCI_DEVICE_ID_MPC8610          0x7018
-
-#define PCI_VENDOR_ID_PASEMI           0x1959
-
-#define PCI_VENDOR_ID_ATTANSIC         0x1969
-#define PCI_DEVICE_ID_ATTANSIC_L1      0x1048
-#define PCI_DEVICE_ID_ATTANSIC_L2      0x2048
-
-#define PCI_VENDOR_ID_JMICRON          0x197B
-#define PCI_DEVICE_ID_JMICRON_JMB360   0x2360
-#define PCI_DEVICE_ID_JMICRON_JMB361   0x2361
-#define PCI_DEVICE_ID_JMICRON_JMB363   0x2363
-#define PCI_DEVICE_ID_JMICRON_JMB365   0x2365
-#define PCI_DEVICE_ID_JMICRON_JMB366   0x2366
-#define PCI_DEVICE_ID_JMICRON_JMB368   0x2368
-#define PCI_DEVICE_ID_JMICRON_JMB38X_SD        0x2381
-#define PCI_DEVICE_ID_JMICRON_JMB38X_MMC 0x2382
-#define PCI_DEVICE_ID_JMICRON_JMB38X_MS        0x2383
-
-#define PCI_VENDOR_ID_KORENIX          0x1982
-#define PCI_DEVICE_ID_KORENIX_JETCARDF0        0x1600
-#define PCI_DEVICE_ID_KORENIX_JETCARDF1        0x16ff
-
-#define PCI_VENDOR_ID_TEKRAM           0x1de1
-#define PCI_DEVICE_ID_TEKRAM_DC290     0xdc29
-
-#define PCI_VENDOR_ID_TEHUTI           0x1fc9
-#define PCI_DEVICE_ID_TEHUTI_3009      0x3009
-#define PCI_DEVICE_ID_TEHUTI_3010      0x3010
-#define PCI_DEVICE_ID_TEHUTI_3014      0x3014
-
-#define PCI_VENDOR_ID_HINT             0x3388
-#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013
-
-#define PCI_VENDOR_ID_3DLABS           0x3d3d
-#define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007
-#define PCI_DEVICE_ID_3DLABS_PERMEDIA2V        0x0009
-
-#define PCI_VENDOR_ID_NETXEN           0x4040
-#define PCI_DEVICE_ID_NX2031_10GXSR    0x0001
-#define PCI_DEVICE_ID_NX2031_10GCX4    0x0002
-#define PCI_DEVICE_ID_NX2031_4GCU      0x0003
-#define PCI_DEVICE_ID_NX2031_IMEZ      0x0004
-#define PCI_DEVICE_ID_NX2031_HMEZ      0x0005
-#define PCI_DEVICE_ID_NX2031_XG_MGMT   0x0024
-#define PCI_DEVICE_ID_NX2031_XG_MGMT2  0x0025
-#define PCI_DEVICE_ID_NX3031           0x0100
-
-#define PCI_VENDOR_ID_AKS              0x416c
-#define PCI_DEVICE_ID_AKS_ALADDINCARD  0x0100
-
-#define PCI_VENDOR_ID_S3               0x5333
-#define PCI_DEVICE_ID_S3_TRIO          0x8811
-#define PCI_DEVICE_ID_S3_868           0x8880
-#define PCI_DEVICE_ID_S3_968           0x88f0
-#define PCI_DEVICE_ID_S3_SAVAGE4       0x8a25
-#define PCI_DEVICE_ID_S3_PROSAVAGE8    0x8d04
-#define PCI_DEVICE_ID_S3_SONICVIBES    0xca00
-
-#define PCI_VENDOR_ID_DUNORD           0x5544
-#define PCI_DEVICE_ID_DUNORD_I3000     0x0001
-
-#define PCI_VENDOR_ID_DCI              0x6666
-#define PCI_DEVICE_ID_DCI_PCCOM4       0x0001
-#define PCI_DEVICE_ID_DCI_PCCOM8       0x0002
-#define PCI_DEVICE_ID_DCI_PCCOM2       0x0004
-
-#define PCI_VENDOR_ID_INTEL            0x8086
-#define PCI_DEVICE_ID_INTEL_EESSC      0x0008
-#define PCI_DEVICE_ID_INTEL_PXHD_0     0x0320
-#define PCI_DEVICE_ID_INTEL_PXHD_1     0x0321
-#define PCI_DEVICE_ID_INTEL_PXH_0      0x0329
-#define PCI_DEVICE_ID_INTEL_PXH_1      0x032A
-#define PCI_DEVICE_ID_INTEL_PXHV       0x032C
-#define PCI_DEVICE_ID_INTEL_82375      0x0482
-#define PCI_DEVICE_ID_INTEL_82424      0x0483
-#define PCI_DEVICE_ID_INTEL_82378      0x0484
-#define PCI_DEVICE_ID_INTEL_I960       0x0960
-#define PCI_DEVICE_ID_INTEL_I960RM     0x0962
-#define PCI_DEVICE_ID_INTEL_82815_MC   0x1130
-#define PCI_DEVICE_ID_INTEL_82815_CGC  0x1132
-#define PCI_DEVICE_ID_INTEL_82092AA_0  0x1221
-#define PCI_DEVICE_ID_INTEL_7505_0     0x2550  
-#define PCI_DEVICE_ID_INTEL_7205_0     0x255d
-#define PCI_DEVICE_ID_INTEL_82437      0x122d
-#define PCI_DEVICE_ID_INTEL_82371FB_0  0x122e
-#define PCI_DEVICE_ID_INTEL_82371FB_1  0x1230
-#define PCI_DEVICE_ID_INTEL_82371MX    0x1234
-#define PCI_DEVICE_ID_INTEL_82441      0x1237
-#define PCI_DEVICE_ID_INTEL_82380FB    0x124b
-#define PCI_DEVICE_ID_INTEL_82439      0x1250
-#define PCI_DEVICE_ID_INTEL_80960_RP   0x1960
-#define PCI_DEVICE_ID_INTEL_82840_HB   0x1a21
-#define PCI_DEVICE_ID_INTEL_82845_HB   0x1a30
-#define PCI_DEVICE_ID_INTEL_IOAT       0x1a38
-#define PCI_DEVICE_ID_INTEL_82801AA_0  0x2410
-#define PCI_DEVICE_ID_INTEL_82801AA_1  0x2411
-#define PCI_DEVICE_ID_INTEL_82801AA_3  0x2413
-#define PCI_DEVICE_ID_INTEL_82801AA_5  0x2415
-#define PCI_DEVICE_ID_INTEL_82801AA_6  0x2416
-#define PCI_DEVICE_ID_INTEL_82801AA_8  0x2418
-#define PCI_DEVICE_ID_INTEL_82801AB_0  0x2420
-#define PCI_DEVICE_ID_INTEL_82801AB_1  0x2421
-#define PCI_DEVICE_ID_INTEL_82801AB_3  0x2423
-#define PCI_DEVICE_ID_INTEL_82801AB_5  0x2425
-#define PCI_DEVICE_ID_INTEL_82801AB_6  0x2426
-#define PCI_DEVICE_ID_INTEL_82801AB_8  0x2428
-#define PCI_DEVICE_ID_INTEL_82801BA_0  0x2440
-#define PCI_DEVICE_ID_INTEL_82801BA_2  0x2443
-#define PCI_DEVICE_ID_INTEL_82801BA_4  0x2445
-#define PCI_DEVICE_ID_INTEL_82801BA_6  0x2448
-#define PCI_DEVICE_ID_INTEL_82801BA_8  0x244a
-#define PCI_DEVICE_ID_INTEL_82801BA_9  0x244b
-#define PCI_DEVICE_ID_INTEL_82801BA_10 0x244c
-#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e
-#define PCI_DEVICE_ID_INTEL_82801E_0   0x2450
-#define PCI_DEVICE_ID_INTEL_82801E_11  0x245b
-#define PCI_DEVICE_ID_INTEL_82801CA_0  0x2480
-#define PCI_DEVICE_ID_INTEL_82801CA_3  0x2483
-#define PCI_DEVICE_ID_INTEL_82801CA_5  0x2485
-#define PCI_DEVICE_ID_INTEL_82801CA_6  0x2486
-#define PCI_DEVICE_ID_INTEL_82801CA_10 0x248a
-#define PCI_DEVICE_ID_INTEL_82801CA_11 0x248b
-#define PCI_DEVICE_ID_INTEL_82801CA_12 0x248c
-#define PCI_DEVICE_ID_INTEL_82801DB_0  0x24c0
-#define PCI_DEVICE_ID_INTEL_82801DB_1  0x24c1
-#define PCI_DEVICE_ID_INTEL_82801DB_3  0x24c3
-#define PCI_DEVICE_ID_INTEL_82801DB_5  0x24c5
-#define PCI_DEVICE_ID_INTEL_82801DB_6  0x24c6
-#define PCI_DEVICE_ID_INTEL_82801DB_9  0x24c9
-#define PCI_DEVICE_ID_INTEL_82801DB_10 0x24ca
-#define PCI_DEVICE_ID_INTEL_82801DB_11 0x24cb
-#define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
-#define PCI_DEVICE_ID_INTEL_82801EB_0  0x24d0
-#define PCI_DEVICE_ID_INTEL_82801EB_1  0x24d1
-#define PCI_DEVICE_ID_INTEL_82801EB_3  0x24d3
-#define PCI_DEVICE_ID_INTEL_82801EB_5  0x24d5
-#define PCI_DEVICE_ID_INTEL_82801EB_6  0x24d6
-#define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db
-#define PCI_DEVICE_ID_INTEL_82801EB_12 0x24dc
-#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd
-#define PCI_DEVICE_ID_INTEL_ESB_1      0x25a1
-#define PCI_DEVICE_ID_INTEL_ESB_2      0x25a2
-#define PCI_DEVICE_ID_INTEL_ESB_4      0x25a4
-#define PCI_DEVICE_ID_INTEL_ESB_5      0x25a6
-#define PCI_DEVICE_ID_INTEL_ESB_9      0x25ab
-#define PCI_DEVICE_ID_INTEL_82820_HB   0x2500
-#define PCI_DEVICE_ID_INTEL_82820_UP_HB        0x2501
-#define PCI_DEVICE_ID_INTEL_82850_HB   0x2530
-#define PCI_DEVICE_ID_INTEL_82860_HB   0x2531
-#define PCI_DEVICE_ID_INTEL_E7501_MCH  0x254c
-#define PCI_DEVICE_ID_INTEL_82845G_HB  0x2560
-#define PCI_DEVICE_ID_INTEL_82845G_IG  0x2562
-#define PCI_DEVICE_ID_INTEL_82865_HB   0x2570
-#define PCI_DEVICE_ID_INTEL_82865_IG   0x2572
-#define PCI_DEVICE_ID_INTEL_82875_HB   0x2578
-#define PCI_DEVICE_ID_INTEL_82915G_HB  0x2580
-#define PCI_DEVICE_ID_INTEL_82915G_IG  0x2582
-#define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590
-#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
-#define PCI_DEVICE_ID_INTEL_5000_ERR   0x25F0
-#define PCI_DEVICE_ID_INTEL_5000_FBD0  0x25F5
-#define PCI_DEVICE_ID_INTEL_5000_FBD1  0x25F6
-#define PCI_DEVICE_ID_INTEL_82945G_HB  0x2770
-#define PCI_DEVICE_ID_INTEL_82945G_IG  0x2772
-#define PCI_DEVICE_ID_INTEL_3000_HB    0x2778
-#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0
-#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2
-#define PCI_DEVICE_ID_INTEL_ICH6_0     0x2640
-#define PCI_DEVICE_ID_INTEL_ICH6_1     0x2641
-#define PCI_DEVICE_ID_INTEL_ICH6_2     0x2642
-#define PCI_DEVICE_ID_INTEL_ICH6_16    0x266a
-#define PCI_DEVICE_ID_INTEL_ICH6_17    0x266d
-#define PCI_DEVICE_ID_INTEL_ICH6_18    0x266e
-#define PCI_DEVICE_ID_INTEL_ICH6_19    0x266f
-#define PCI_DEVICE_ID_INTEL_ESB2_0     0x2670
-#define PCI_DEVICE_ID_INTEL_ESB2_14    0x2698
-#define PCI_DEVICE_ID_INTEL_ESB2_17    0x269b
-#define PCI_DEVICE_ID_INTEL_ESB2_18    0x269e
-#define PCI_DEVICE_ID_INTEL_ICH7_0     0x27b8
-#define PCI_DEVICE_ID_INTEL_ICH7_1     0x27b9
-#define PCI_DEVICE_ID_INTEL_ICH7_30    0x27b0
-#define PCI_DEVICE_ID_INTEL_ICH7_31    0x27bd
-#define PCI_DEVICE_ID_INTEL_ICH7_17    0x27da
-#define PCI_DEVICE_ID_INTEL_ICH7_19    0x27dd
-#define PCI_DEVICE_ID_INTEL_ICH7_20    0x27de
-#define PCI_DEVICE_ID_INTEL_ICH7_21    0x27df
-#define PCI_DEVICE_ID_INTEL_ICH8_0     0x2810
-#define PCI_DEVICE_ID_INTEL_ICH8_1     0x2811
-#define PCI_DEVICE_ID_INTEL_ICH8_2     0x2812
-#define PCI_DEVICE_ID_INTEL_ICH8_3     0x2814
-#define PCI_DEVICE_ID_INTEL_ICH8_4     0x2815
-#define PCI_DEVICE_ID_INTEL_ICH8_5     0x283e
-#define PCI_DEVICE_ID_INTEL_ICH8_6     0x2850
-#define PCI_DEVICE_ID_INTEL_ICH9_0     0x2910
-#define PCI_DEVICE_ID_INTEL_ICH9_1     0x2917
-#define PCI_DEVICE_ID_INTEL_ICH9_2     0x2912
-#define PCI_DEVICE_ID_INTEL_ICH9_3     0x2913
-#define PCI_DEVICE_ID_INTEL_ICH9_4     0x2914
-#define PCI_DEVICE_ID_INTEL_ICH9_5     0x2919
-#define PCI_DEVICE_ID_INTEL_ICH9_6     0x2930
-#define PCI_DEVICE_ID_INTEL_ICH9_7     0x2916
-#define PCI_DEVICE_ID_INTEL_ICH9_8     0x2918
-#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
-#define PCI_DEVICE_ID_INTEL_IOAT_TBG4  0x3429
-#define PCI_DEVICE_ID_INTEL_IOAT_TBG5  0x342a
-#define PCI_DEVICE_ID_INTEL_IOAT_TBG6  0x342b
-#define PCI_DEVICE_ID_INTEL_IOAT_TBG7  0x342c
-#define PCI_DEVICE_ID_INTEL_IOAT_TBG0  0x3430
-#define PCI_DEVICE_ID_INTEL_IOAT_TBG1  0x3431
-#define PCI_DEVICE_ID_INTEL_IOAT_TBG2  0x3432
-#define PCI_DEVICE_ID_INTEL_IOAT_TBG3  0x3433
-#define PCI_DEVICE_ID_INTEL_82830_HB   0x3575
-#define PCI_DEVICE_ID_INTEL_82830_CGC  0x3577
-#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
-#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
-#define PCI_DEVICE_ID_INTEL_E7520_MCH  0x3590
-#define PCI_DEVICE_ID_INTEL_E7320_MCH  0x3592
-#define PCI_DEVICE_ID_INTEL_MCH_PA     0x3595
-#define PCI_DEVICE_ID_INTEL_MCH_PA1    0x3596
-#define PCI_DEVICE_ID_INTEL_MCH_PB     0x3597
-#define PCI_DEVICE_ID_INTEL_MCH_PB1    0x3598
-#define PCI_DEVICE_ID_INTEL_MCH_PC     0x3599
-#define PCI_DEVICE_ID_INTEL_MCH_PC1    0x359a
-#define PCI_DEVICE_ID_INTEL_E7525_MCH  0x359e
-#define PCI_DEVICE_ID_INTEL_IOAT_CNB   0x360b
-#define PCI_DEVICE_ID_INTEL_FBD_CNB    0x360c
-#define PCI_DEVICE_ID_INTEL_ICH10_0    0x3a14
-#define PCI_DEVICE_ID_INTEL_ICH10_1    0x3a16
-#define PCI_DEVICE_ID_INTEL_ICH10_2    0x3a18
-#define PCI_DEVICE_ID_INTEL_ICH10_3    0x3a1a
-#define PCI_DEVICE_ID_INTEL_ICH10_4    0x3a30
-#define PCI_DEVICE_ID_INTEL_ICH10_5    0x3a60
-#define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN        0x3b00
-#define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX        0x3b1f
-#define PCI_DEVICE_ID_INTEL_PCH_SMBUS  0x3b30
-#define PCI_DEVICE_ID_INTEL_IOAT_SNB   0x402f
-#define PCI_DEVICE_ID_INTEL_5100_16    0x65f0
-#define PCI_DEVICE_ID_INTEL_5100_21    0x65f5
-#define PCI_DEVICE_ID_INTEL_5100_22    0x65f6
-#define PCI_DEVICE_ID_INTEL_5400_ERR   0x4030
-#define PCI_DEVICE_ID_INTEL_5400_FBD0  0x4035
-#define PCI_DEVICE_ID_INTEL_5400_FBD1  0x4036
-#define PCI_DEVICE_ID_INTEL_IOAT_SCNB  0x65ff
-#define PCI_DEVICE_ID_INTEL_TOLAPAI_0  0x5031
-#define PCI_DEVICE_ID_INTEL_TOLAPAI_1  0x5032
-#define PCI_DEVICE_ID_INTEL_82371SB_0  0x7000
-#define PCI_DEVICE_ID_INTEL_82371SB_1  0x7010
-#define PCI_DEVICE_ID_INTEL_82371SB_2  0x7020
-#define PCI_DEVICE_ID_INTEL_82437VX    0x7030
-#define PCI_DEVICE_ID_INTEL_82439TX    0x7100
-#define PCI_DEVICE_ID_INTEL_82371AB_0  0x7110
-#define PCI_DEVICE_ID_INTEL_82371AB    0x7111
-#define PCI_DEVICE_ID_INTEL_82371AB_2  0x7112
-#define PCI_DEVICE_ID_INTEL_82371AB_3  0x7113
-#define PCI_DEVICE_ID_INTEL_82810_MC1  0x7120
-#define PCI_DEVICE_ID_INTEL_82810_IG1  0x7121
-#define PCI_DEVICE_ID_INTEL_82810_MC3  0x7122
-#define PCI_DEVICE_ID_INTEL_82810_IG3  0x7123
-#define PCI_DEVICE_ID_INTEL_82810E_MC  0x7124
-#define PCI_DEVICE_ID_INTEL_82810E_IG  0x7125
-#define PCI_DEVICE_ID_INTEL_82443LX_0  0x7180
-#define PCI_DEVICE_ID_INTEL_82443LX_1  0x7181
-#define PCI_DEVICE_ID_INTEL_82443BX_0  0x7190
-#define PCI_DEVICE_ID_INTEL_82443BX_1  0x7191
-#define PCI_DEVICE_ID_INTEL_82443BX_2  0x7192
-#define PCI_DEVICE_ID_INTEL_440MX      0x7195
-#define PCI_DEVICE_ID_INTEL_440MX_6    0x7196
-#define PCI_DEVICE_ID_INTEL_82443MX_0  0x7198
-#define PCI_DEVICE_ID_INTEL_82443MX_1  0x7199
-#define PCI_DEVICE_ID_INTEL_82443MX_3  0x719b
-#define PCI_DEVICE_ID_INTEL_82443GX_0  0x71a0
-#define PCI_DEVICE_ID_INTEL_82443GX_2  0x71a2
-#define PCI_DEVICE_ID_INTEL_82372FB_1  0x7601
-#define PCI_DEVICE_ID_INTEL_SCH_LPC    0x8119
-#define PCI_DEVICE_ID_INTEL_SCH_IDE    0x811a
-#define PCI_DEVICE_ID_INTEL_82454GX    0x84c4
-#define PCI_DEVICE_ID_INTEL_82450GX    0x84c5
-#define PCI_DEVICE_ID_INTEL_82451NX    0x84ca
-#define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
-#define PCI_DEVICE_ID_INTEL_84460GX    0x84ea
-#define PCI_DEVICE_ID_INTEL_IXP4XX     0x8500
-#define PCI_DEVICE_ID_INTEL_IXP2800    0x9004
-#define PCI_DEVICE_ID_INTEL_S21152BB   0xb152
-
-#define PCI_VENDOR_ID_SCALEMP          0x8686
-#define PCI_DEVICE_ID_SCALEMP_VSMP_CTL 0x1010
-
-#define PCI_VENDOR_ID_COMPUTONE                0x8e0e
-#define PCI_DEVICE_ID_COMPUTONE_IP2EX  0x0291
-#define PCI_DEVICE_ID_COMPUTONE_PG     0x0302
-#define PCI_SUBVENDOR_ID_COMPUTONE     0x8e0e
-#define PCI_SUBDEVICE_ID_COMPUTONE_PG4 0x0001
-#define PCI_SUBDEVICE_ID_COMPUTONE_PG8 0x0002
-#define PCI_SUBDEVICE_ID_COMPUTONE_PG6 0x0003
-
-#define PCI_VENDOR_ID_KTI              0x8e2e
-
-#define PCI_VENDOR_ID_ADAPTEC          0x9004
-#define PCI_DEVICE_ID_ADAPTEC_7810     0x1078
-#define PCI_DEVICE_ID_ADAPTEC_7821     0x2178
-#define PCI_DEVICE_ID_ADAPTEC_38602    0x3860
-#define PCI_DEVICE_ID_ADAPTEC_7850     0x5078
-#define PCI_DEVICE_ID_ADAPTEC_7855     0x5578
-#define PCI_DEVICE_ID_ADAPTEC_3860     0x6038
-#define PCI_DEVICE_ID_ADAPTEC_1480A    0x6075
-#define PCI_DEVICE_ID_ADAPTEC_7860     0x6078
-#define PCI_DEVICE_ID_ADAPTEC_7861     0x6178
-#define PCI_DEVICE_ID_ADAPTEC_7870     0x7078
-#define PCI_DEVICE_ID_ADAPTEC_7871     0x7178
-#define PCI_DEVICE_ID_ADAPTEC_7872     0x7278
-#define PCI_DEVICE_ID_ADAPTEC_7873     0x7378
-#define PCI_DEVICE_ID_ADAPTEC_7874     0x7478
-#define PCI_DEVICE_ID_ADAPTEC_7895     0x7895
-#define PCI_DEVICE_ID_ADAPTEC_7880     0x8078
-#define PCI_DEVICE_ID_ADAPTEC_7881     0x8178
-#define PCI_DEVICE_ID_ADAPTEC_7882     0x8278
-#define PCI_DEVICE_ID_ADAPTEC_7883     0x8378
-#define PCI_DEVICE_ID_ADAPTEC_7884     0x8478
-#define PCI_DEVICE_ID_ADAPTEC_7885     0x8578
-#define PCI_DEVICE_ID_ADAPTEC_7886     0x8678
-#define PCI_DEVICE_ID_ADAPTEC_7887     0x8778
-#define PCI_DEVICE_ID_ADAPTEC_7888     0x8878
-
-#define PCI_VENDOR_ID_ADAPTEC2         0x9005
-#define PCI_DEVICE_ID_ADAPTEC2_2940U2  0x0010
-#define PCI_DEVICE_ID_ADAPTEC2_2930U2  0x0011
-#define PCI_DEVICE_ID_ADAPTEC2_7890B   0x0013
-#define PCI_DEVICE_ID_ADAPTEC2_7890    0x001f
-#define PCI_DEVICE_ID_ADAPTEC2_3940U2  0x0050
-#define PCI_DEVICE_ID_ADAPTEC2_3950U2D 0x0051
-#define PCI_DEVICE_ID_ADAPTEC2_7896    0x005f
-#define PCI_DEVICE_ID_ADAPTEC2_7892A   0x0080
-#define PCI_DEVICE_ID_ADAPTEC2_7892B   0x0081
-#define PCI_DEVICE_ID_ADAPTEC2_7892D   0x0083
-#define PCI_DEVICE_ID_ADAPTEC2_7892P   0x008f
-#define PCI_DEVICE_ID_ADAPTEC2_7899A   0x00c0
-#define PCI_DEVICE_ID_ADAPTEC2_7899B   0x00c1
-#define PCI_DEVICE_ID_ADAPTEC2_7899D   0x00c3
-#define PCI_DEVICE_ID_ADAPTEC2_7899P   0x00cf
-#define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN   0x0500
-#define PCI_DEVICE_ID_ADAPTEC2_SCAMP   0x0503
-
-#define PCI_VENDOR_ID_HOLTEK           0x9412
-#define PCI_DEVICE_ID_HOLTEK_6565      0x6565
-
-#define PCI_VENDOR_ID_NETMOS           0x9710
-#define PCI_DEVICE_ID_NETMOS_9705      0x9705
-#define PCI_DEVICE_ID_NETMOS_9715      0x9715
-#define PCI_DEVICE_ID_NETMOS_9735      0x9735
-#define PCI_DEVICE_ID_NETMOS_9745      0x9745
-#define PCI_DEVICE_ID_NETMOS_9755      0x9755
-#define PCI_DEVICE_ID_NETMOS_9805      0x9805
-#define PCI_DEVICE_ID_NETMOS_9815      0x9815
-#define PCI_DEVICE_ID_NETMOS_9835      0x9835
-#define PCI_DEVICE_ID_NETMOS_9845      0x9845
-#define PCI_DEVICE_ID_NETMOS_9855      0x9855
-
-#define PCI_VENDOR_ID_3COM_2           0xa727
-
-#define PCI_VENDOR_ID_DIGIUM           0xd161
-#define PCI_DEVICE_ID_DIGIUM_HFC4S     0xb410
-
-#define PCI_SUBVENDOR_ID_EXSYS         0xd84d
-#define PCI_SUBDEVICE_ID_EXSYS_4014    0x4014
-#define PCI_SUBDEVICE_ID_EXSYS_4055    0x4055
-
-#define PCI_VENDOR_ID_TIGERJET         0xe159
-#define PCI_DEVICE_ID_TIGERJET_300     0x0001
-#define PCI_DEVICE_ID_TIGERJET_100     0x0002
-
-#define PCI_VENDOR_ID_XILINX_RME       0xea60
-#define PCI_DEVICE_ID_RME_DIGI32       0x9896
-#define PCI_DEVICE_ID_RME_DIGI32_PRO   0x9897
-#define PCI_DEVICE_ID_RME_DIGI32_8     0x9898
-
-#define PCI_VENDOR_ID_REDHAT_QUMRANET  0x1af4
-#define PCI_DEVICE_ID_VIRTIO_BLK       0x1001
-#define PCI_DEVICE_ID_VIRTIO_SCSI      0x1004
diff --git a/src/pci_regs.h b/src/pci_regs.h
deleted file mode 100644 (file)
index e5effd4..0000000
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- *     pci_regs.h
- *
- *     PCI standard defines
- *     Copyright 1994, Drew Eckhardt
- *     Copyright 1997--1999 Martin Mares <mj@ucw.cz>
- *
- *     For more information, please consult the following manuals (look at
- *     http://www.pcisig.com/ for how to get them):
- *
- *     PCI BIOS Specification
- *     PCI Local Bus Specification
- *     PCI to PCI Bridge Specification
- *     PCI System Design Guide
- *
- *     For hypertransport information, please consult the following manuals
- *     from http://www.hypertransport.org
- *
- *     The Hypertransport I/O Link Specification
- */
-
-#ifndef LINUX_PCI_REGS_H
-#define LINUX_PCI_REGS_H
-
-/*
- * Under PCI, each device has 256 bytes of configuration address space,
- * of which the first 64 bytes are standardized as follows:
- */
-#define PCI_VENDOR_ID          0x00    /* 16 bits */
-#define PCI_DEVICE_ID          0x02    /* 16 bits */
-#define PCI_COMMAND            0x04    /* 16 bits */
-#define  PCI_COMMAND_IO                0x1     /* Enable response in I/O space */
-#define  PCI_COMMAND_MEMORY    0x2     /* Enable response in Memory space */
-#define  PCI_COMMAND_MASTER    0x4     /* Enable bus mastering */
-#define  PCI_COMMAND_SPECIAL   0x8     /* Enable response to special cycles */
-#define  PCI_COMMAND_INVALIDATE        0x10    /* Use memory write and invalidate */
-#define  PCI_COMMAND_VGA_PALETTE 0x20  /* Enable palette snooping */
-#define  PCI_COMMAND_PARITY    0x40    /* Enable parity checking */
-#define  PCI_COMMAND_WAIT      0x80    /* Enable address/data stepping */
-#define  PCI_COMMAND_SERR      0x100   /* Enable SERR */
-#define  PCI_COMMAND_FAST_BACK 0x200   /* Enable back-to-back writes */
-#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
-
-#define PCI_STATUS             0x06    /* 16 bits */
-#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
-#define  PCI_STATUS_66MHZ      0x20    /* Support 66 Mhz PCI 2.1 bus */
-#define  PCI_STATUS_UDF                0x40    /* Support User Definable Features [obsolete] */
-#define  PCI_STATUS_FAST_BACK  0x80    /* Accept fast-back to back */
-#define  PCI_STATUS_PARITY     0x100   /* Detected parity error */
-#define  PCI_STATUS_DEVSEL_MASK        0x600   /* DEVSEL timing */
-#define  PCI_STATUS_DEVSEL_FAST                0x000
-#define  PCI_STATUS_DEVSEL_MEDIUM      0x200
-#define  PCI_STATUS_DEVSEL_SLOW                0x400
-#define  PCI_STATUS_SIG_TARGET_ABORT   0x800 /* Set on target abort */
-#define  PCI_STATUS_REC_TARGET_ABORT   0x1000 /* Master ack of " */
-#define  PCI_STATUS_REC_MASTER_ABORT   0x2000 /* Set on master abort */
-#define  PCI_STATUS_SIG_SYSTEM_ERROR   0x4000 /* Set when we drive SERR */
-#define  PCI_STATUS_DETECTED_PARITY    0x8000 /* Set on parity error */
-
-#define PCI_CLASS_REVISION     0x08    /* High 24 bits are class, low 8 revision */
-#define PCI_REVISION_ID                0x08    /* Revision ID */
-#define PCI_CLASS_PROG         0x09    /* Reg. Level Programming Interface */
-#define PCI_CLASS_DEVICE       0x0a    /* Device class */
-
-#define PCI_CACHE_LINE_SIZE    0x0c    /* 8 bits */
-#define PCI_LATENCY_TIMER      0x0d    /* 8 bits */
-#define PCI_HEADER_TYPE                0x0e    /* 8 bits */
-#define  PCI_HEADER_TYPE_NORMAL                0
-#define  PCI_HEADER_TYPE_BRIDGE                1
-#define  PCI_HEADER_TYPE_CARDBUS       2
-
-#define PCI_BIST               0x0f    /* 8 bits */
-#define  PCI_BIST_CODE_MASK    0x0f    /* Return result */
-#define  PCI_BIST_START                0x40    /* 1 to start BIST, 2 secs or less */
-#define  PCI_BIST_CAPABLE      0x80    /* 1 if BIST capable */
-
-/*
- * Base addresses specify locations in memory or I/O space.
- * Decoded size can be determined by writing a value of
- * 0xffffffff to the register, and reading it back.  Only
- * 1 bits are decoded.
- */
-#define PCI_BASE_ADDRESS_0     0x10    /* 32 bits */
-#define PCI_BASE_ADDRESS_1     0x14    /* 32 bits [htype 0,1 only] */
-#define PCI_BASE_ADDRESS_2     0x18    /* 32 bits [htype 0 only] */
-#define PCI_BASE_ADDRESS_3     0x1c    /* 32 bits */
-#define PCI_BASE_ADDRESS_4     0x20    /* 32 bits */
-#define PCI_BASE_ADDRESS_5     0x24    /* 32 bits */
-#define  PCI_BASE_ADDRESS_SPACE                0x01    /* 0 = memory, 1 = I/O */
-#define  PCI_BASE_ADDRESS_SPACE_IO     0x01
-#define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
-#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK        0x06
-#define  PCI_BASE_ADDRESS_MEM_TYPE_32  0x00    /* 32 bit address */
-#define  PCI_BASE_ADDRESS_MEM_TYPE_1M  0x02    /* Below 1M [obsolete] */
-#define  PCI_BASE_ADDRESS_MEM_TYPE_64  0x04    /* 64 bit address */
-#define  PCI_BASE_ADDRESS_MEM_PREFETCH 0x08    /* prefetchable? */
-#define  PCI_BASE_ADDRESS_MEM_MASK     (~0x0fUL)
-#define  PCI_BASE_ADDRESS_IO_MASK      (~0x03UL)
-/* bit 1 is reserved if address_space = 1 */
-
-/* Header type 0 (normal devices) */
-#define PCI_CARDBUS_CIS                0x28
-#define PCI_SUBSYSTEM_VENDOR_ID        0x2c
-#define PCI_SUBSYSTEM_ID       0x2e
-#define PCI_ROM_ADDRESS                0x30    /* Bits 31..11 are address, 10..1 reserved */
-#define  PCI_ROM_ADDRESS_ENABLE        0x01
-#define PCI_ROM_ADDRESS_MASK   (~0x7ffUL)
-
-#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list entry */
-
-/* 0x35-0x3b are reserved */
-#define PCI_INTERRUPT_LINE     0x3c    /* 8 bits */
-#define PCI_INTERRUPT_PIN      0x3d    /* 8 bits */
-#define PCI_MIN_GNT            0x3e    /* 8 bits */
-#define PCI_MAX_LAT            0x3f    /* 8 bits */
-
-/* Header type 1 (PCI-to-PCI bridges) */
-#define PCI_PRIMARY_BUS                0x18    /* Primary bus number */
-#define PCI_SECONDARY_BUS      0x19    /* Secondary bus number */
-#define PCI_SUBORDINATE_BUS    0x1a    /* Highest bus number behind the bridge */
-#define PCI_SEC_LATENCY_TIMER  0x1b    /* Latency timer for secondary interface */
-#define PCI_IO_BASE            0x1c    /* I/O range behind the bridge */
-#define PCI_IO_LIMIT           0x1d
-#define  PCI_IO_RANGE_TYPE_MASK        0x0fUL  /* I/O bridging type */
-#define  PCI_IO_RANGE_TYPE_16  0x00
-#define  PCI_IO_RANGE_TYPE_32  0x01
-#define  PCI_IO_RANGE_MASK     (~0x0fUL)
-#define PCI_SEC_STATUS         0x1e    /* Secondary status register, only bit 14 used */
-#define PCI_MEMORY_BASE                0x20    /* Memory range behind */
-#define PCI_MEMORY_LIMIT       0x22
-#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
-#define  PCI_MEMORY_RANGE_MASK (~0x0fUL)
-#define PCI_PREF_MEMORY_BASE   0x24    /* Prefetchable memory range behind */
-#define PCI_PREF_MEMORY_LIMIT  0x26
-#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
-#define  PCI_PREF_RANGE_TYPE_32        0x00
-#define  PCI_PREF_RANGE_TYPE_64        0x01
-#define  PCI_PREF_RANGE_MASK   (~0x0fUL)
-#define PCI_PREF_BASE_UPPER32  0x28    /* Upper half of prefetchable memory range */
-#define PCI_PREF_LIMIT_UPPER32 0x2c
-#define PCI_IO_BASE_UPPER16    0x30    /* Upper half of I/O addresses */
-#define PCI_IO_LIMIT_UPPER16   0x32
-/* 0x34 same as for htype 0 */
-/* 0x35-0x3b is reserved */
-#define PCI_ROM_ADDRESS1       0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_BRIDGE_CONTROL     0x3e
-#define  PCI_BRIDGE_CTL_PARITY 0x01    /* Enable parity detection on secondary interface */
-#define  PCI_BRIDGE_CTL_SERR   0x02    /* The same for SERR forwarding */
-#define  PCI_BRIDGE_CTL_ISA    0x04    /* Enable ISA mode */
-#define  PCI_BRIDGE_CTL_VGA    0x08    /* Forward VGA addresses */
-#define  PCI_BRIDGE_CTL_MASTER_ABORT   0x20  /* Report master aborts */
-#define  PCI_BRIDGE_CTL_BUS_RESET      0x40    /* Secondary bus reset */
-#define  PCI_BRIDGE_CTL_FAST_BACK      0x80    /* Fast Back2Back enabled on secondary interface */
-
-/* Header type 2 (CardBus bridges) */
-#define PCI_CB_CAPABILITY_LIST 0x14
-/* 0x15 reserved */
-#define PCI_CB_SEC_STATUS      0x16    /* Secondary status */
-#define PCI_CB_PRIMARY_BUS     0x18    /* PCI bus number */
-#define PCI_CB_CARD_BUS                0x19    /* CardBus bus number */
-#define PCI_CB_SUBORDINATE_BUS 0x1a    /* Subordinate bus number */
-#define PCI_CB_LATENCY_TIMER   0x1b    /* CardBus latency timer */
-#define PCI_CB_MEMORY_BASE_0   0x1c
-#define PCI_CB_MEMORY_LIMIT_0  0x20
-#define PCI_CB_MEMORY_BASE_1   0x24
-#define PCI_CB_MEMORY_LIMIT_1  0x28
-#define PCI_CB_IO_BASE_0       0x2c
-#define PCI_CB_IO_BASE_0_HI    0x2e
-#define PCI_CB_IO_LIMIT_0      0x30
-#define PCI_CB_IO_LIMIT_0_HI   0x32
-#define PCI_CB_IO_BASE_1       0x34
-#define PCI_CB_IO_BASE_1_HI    0x36
-#define PCI_CB_IO_LIMIT_1      0x38
-#define PCI_CB_IO_LIMIT_1_HI   0x3a
-#define  PCI_CB_IO_RANGE_MASK  (~0x03UL)
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_CB_BRIDGE_CONTROL  0x3e
-#define  PCI_CB_BRIDGE_CTL_PARITY      0x01    /* Similar to standard bridge control register */
-#define  PCI_CB_BRIDGE_CTL_SERR                0x02
-#define  PCI_CB_BRIDGE_CTL_ISA         0x04
-#define  PCI_CB_BRIDGE_CTL_VGA         0x08
-#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT        0x20
-#define  PCI_CB_BRIDGE_CTL_CB_RESET    0x40    /* CardBus reset */
-#define  PCI_CB_BRIDGE_CTL_16BIT_INT   0x80    /* Enable interrupt for 16-bit cards */
-#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
-#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
-#define  PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
-#define PCI_CB_SUBSYSTEM_VENDOR_ID     0x40
-#define PCI_CB_SUBSYSTEM_ID            0x42
-#define PCI_CB_LEGACY_MODE_BASE                0x44    /* 16-bit PC Card legacy mode base address (ExCa) */
-/* 0x48-0x7f reserved */
-
-/* Capability lists */
-
-#define PCI_CAP_LIST_ID                0       /* Capability ID */
-#define  PCI_CAP_ID_PM         0x01    /* Power Management */
-#define  PCI_CAP_ID_AGP                0x02    /* Accelerated Graphics Port */
-#define  PCI_CAP_ID_VPD                0x03    /* Vital Product Data */
-#define  PCI_CAP_ID_SLOTID     0x04    /* Slot Identification */
-#define  PCI_CAP_ID_MSI                0x05    /* Message Signalled Interrupts */
-#define  PCI_CAP_ID_CHSWP      0x06    /* CompactPCI HotSwap */
-#define  PCI_CAP_ID_PCIX       0x07    /* PCI-X */
-#define  PCI_CAP_ID_HT         0x08    /* HyperTransport */
-#define  PCI_CAP_ID_VNDR       0x09    /* Vendor specific */
-#define  PCI_CAP_ID_DBG                0x0A    /* Debug port */
-#define  PCI_CAP_ID_CCRC       0x0B    /* CompactPCI Central Resource Control */
-#define  PCI_CAP_ID_SHPC       0x0C    /* PCI Standard Hot-Plug Controller */
-#define  PCI_CAP_ID_SSVID      0x0D    /* Bridge subsystem vendor/device ID */
-#define  PCI_CAP_ID_AGP3       0x0E    /* AGP Target PCI-PCI bridge */
-#define  PCI_CAP_ID_EXP        0x10    /* PCI Express */
-#define  PCI_CAP_ID_MSIX       0x11    /* MSI-X */
-#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
-#define PCI_CAP_FLAGS          2       /* Capability defined flags (16 bits) */
-#define PCI_CAP_SIZEOF         4
-
-/* Power Management Registers */
-
-#define PCI_PM_PMC             2       /* PM Capabilities Register */
-#define  PCI_PM_CAP_VER_MASK   0x0007  /* Version */
-#define  PCI_PM_CAP_PME_CLOCK  0x0008  /* PME clock required */
-#define  PCI_PM_CAP_RESERVED    0x0010  /* Reserved field */
-#define  PCI_PM_CAP_DSI                0x0020  /* Device specific initialization */
-#define  PCI_PM_CAP_AUX_POWER  0x01C0  /* Auxilliary power support mask */
-#define  PCI_PM_CAP_D1         0x0200  /* D1 power state support */
-#define  PCI_PM_CAP_D2         0x0400  /* D2 power state support */
-#define  PCI_PM_CAP_PME                0x0800  /* PME pin supported */
-#define  PCI_PM_CAP_PME_MASK   0xF800  /* PME Mask of all supported states */
-#define  PCI_PM_CAP_PME_D0     0x0800  /* PME# from D0 */
-#define  PCI_PM_CAP_PME_D1     0x1000  /* PME# from D1 */
-#define  PCI_PM_CAP_PME_D2     0x2000  /* PME# from D2 */
-#define  PCI_PM_CAP_PME_D3     0x4000  /* PME# from D3 (hot) */
-#define  PCI_PM_CAP_PME_D3cold 0x8000  /* PME# from D3 (cold) */
-#define  PCI_PM_CAP_PME_SHIFT  11      /* Start of the PME Mask in PMC */
-#define PCI_PM_CTRL            4       /* PM control and status register */
-#define  PCI_PM_CTRL_STATE_MASK        0x0003  /* Current power state (D0 to D3) */
-#define  PCI_PM_CTRL_NO_SOFT_RESET     0x0004  /* No reset for D3hot->D0 */
-#define  PCI_PM_CTRL_PME_ENABLE        0x0100  /* PME pin enable */
-#define  PCI_PM_CTRL_DATA_SEL_MASK     0x1e00  /* Data select (??) */
-#define  PCI_PM_CTRL_DATA_SCALE_MASK   0x6000  /* Data scale (??) */
-#define  PCI_PM_CTRL_PME_STATUS        0x8000  /* PME pin status */
-#define PCI_PM_PPB_EXTENSIONS  6       /* PPB support extensions (??) */
-#define  PCI_PM_PPB_B2_B3      0x40    /* Stop clock when in D3hot (??) */
-#define  PCI_PM_BPCC_ENABLE    0x80    /* Bus power/clock control enable (??) */
-#define PCI_PM_DATA_REGISTER   7       /* (??) */
-#define PCI_PM_SIZEOF          8
-
-/* AGP registers */
-
-#define PCI_AGP_VERSION                2       /* BCD version number */
-#define PCI_AGP_RFU            3       /* Rest of capability flags */
-#define PCI_AGP_STATUS         4       /* Status register */
-#define  PCI_AGP_STATUS_RQ_MASK        0xff000000      /* Maximum number of requests - 1 */
-#define  PCI_AGP_STATUS_SBA    0x0200  /* Sideband addressing supported */
-#define  PCI_AGP_STATUS_64BIT  0x0020  /* 64-bit addressing supported */
-#define  PCI_AGP_STATUS_FW     0x0010  /* FW transfers supported */
-#define  PCI_AGP_STATUS_RATE4  0x0004  /* 4x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE2  0x0002  /* 2x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE1  0x0001  /* 1x transfer rate supported */
-#define PCI_AGP_COMMAND                8       /* Control register */
-#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
-#define  PCI_AGP_COMMAND_SBA   0x0200  /* Sideband addressing enabled */
-#define  PCI_AGP_COMMAND_AGP   0x0100  /* Allow processing of AGP transactions */
-#define  PCI_AGP_COMMAND_64BIT 0x0020  /* Allow processing of 64-bit addresses */
-#define  PCI_AGP_COMMAND_FW    0x0010  /* Force FW transfers */
-#define  PCI_AGP_COMMAND_RATE4 0x0004  /* Use 4x rate */
-#define  PCI_AGP_COMMAND_RATE2 0x0002  /* Use 2x rate */
-#define  PCI_AGP_COMMAND_RATE1 0x0001  /* Use 1x rate */
-#define PCI_AGP_SIZEOF         12
-
-/* Vital Product Data */
-
-#define PCI_VPD_ADDR           2       /* Address to access (15 bits!) */
-#define  PCI_VPD_ADDR_MASK     0x7fff  /* Address mask */
-#define  PCI_VPD_ADDR_F                0x8000  /* Write 0, 1 indicates completion */
-#define PCI_VPD_DATA           4       /* 32-bits of data returned here */
-
-/* Slot Identification */
-
-#define PCI_SID_ESR            2       /* Expansion Slot Register */
-#define  PCI_SID_ESR_NSLOTS    0x1f    /* Number of expansion slots available */
-#define  PCI_SID_ESR_FIC       0x20    /* First In Chassis Flag */
-#define PCI_SID_CHASSIS_NR     3       /* Chassis Number */
-
-/* Message Signalled Interrupts registers */
-
-#define PCI_MSI_FLAGS          2       /* Various flags */
-#define  PCI_MSI_FLAGS_64BIT   0x80    /* 64-bit addresses allowed */
-#define  PCI_MSI_FLAGS_QSIZE   0x70    /* Message queue size configured */
-#define  PCI_MSI_FLAGS_QMASK   0x0e    /* Maximum queue size available */
-#define  PCI_MSI_FLAGS_ENABLE  0x01    /* MSI feature enabled */
-#define  PCI_MSI_FLAGS_MASKBIT 0x100   /* 64-bit mask bits allowed */
-#define PCI_MSI_RFU            3       /* Rest of capability flags */
-#define PCI_MSI_ADDRESS_LO     4       /* Lower 32 bits */
-#define PCI_MSI_ADDRESS_HI     8       /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
-#define PCI_MSI_DATA_32                8       /* 16 bits of data for 32-bit devices */
-#define PCI_MSI_DATA_64                12      /* 16 bits of data for 64-bit devices */
-#define PCI_MSI_MASK_BIT       16      /* Mask bits register */
-
-/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */
-#define PCI_MSIX_FLAGS         2
-#define  PCI_MSIX_FLAGS_QSIZE  0x7FF
-#define  PCI_MSIX_FLAGS_ENABLE (1 << 15)
-#define  PCI_MSIX_FLAGS_MASKALL        (1 << 14)
-#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
-#define PCI_MSIX_FLAGS_BITMASK (1 << 0)
-
-/* CompactPCI Hotswap Register */
-
-#define PCI_CHSWP_CSR          2       /* Control and Status Register */
-#define  PCI_CHSWP_DHA         0x01    /* Device Hiding Arm */
-#define  PCI_CHSWP_EIM         0x02    /* ENUM# Signal Mask */
-#define  PCI_CHSWP_PIE         0x04    /* Pending Insert or Extract */
-#define  PCI_CHSWP_LOO         0x08    /* LED On / Off */
-#define  PCI_CHSWP_PI          0x30    /* Programming Interface */
-#define  PCI_CHSWP_EXT         0x40    /* ENUM# status - extraction */
-#define  PCI_CHSWP_INS         0x80    /* ENUM# status - insertion */
-
-/* PCI-X registers */
-
-#define PCI_X_CMD              2       /* Modes & Features */
-#define  PCI_X_CMD_DPERR_E     0x0001  /* Data Parity Error Recovery Enable */
-#define  PCI_X_CMD_ERO         0x0002  /* Enable Relaxed Ordering */
-#define  PCI_X_CMD_READ_512    0x0000  /* 512 byte maximum read byte count */
-#define  PCI_X_CMD_READ_1K     0x0004  /* 1Kbyte maximum read byte count */
-#define  PCI_X_CMD_READ_2K     0x0008  /* 2Kbyte maximum read byte count */
-#define  PCI_X_CMD_READ_4K     0x000c  /* 4Kbyte maximum read byte count */
-#define  PCI_X_CMD_MAX_READ    0x000c  /* Max Memory Read Byte Count */
-                               /* Max # of outstanding split transactions */
-#define  PCI_X_CMD_SPLIT_1     0x0000  /* Max 1 */
-#define  PCI_X_CMD_SPLIT_2     0x0010  /* Max 2 */
-#define  PCI_X_CMD_SPLIT_3     0x0020  /* Max 3 */
-#define  PCI_X_CMD_SPLIT_4     0x0030  /* Max 4 */
-#define  PCI_X_CMD_SPLIT_8     0x0040  /* Max 8 */
-#define  PCI_X_CMD_SPLIT_12    0x0050  /* Max 12 */
-#define  PCI_X_CMD_SPLIT_16    0x0060  /* Max 16 */
-#define  PCI_X_CMD_SPLIT_32    0x0070  /* Max 32 */
-#define  PCI_X_CMD_MAX_SPLIT   0x0070  /* Max Outstanding Split Transactions */
-#define  PCI_X_CMD_VERSION(x)  (((x) >> 12) & 3) /* Version */
-#define PCI_X_STATUS           4       /* PCI-X capabilities */
-#define  PCI_X_STATUS_DEVFN    0x000000ff      /* A copy of devfn */
-#define  PCI_X_STATUS_BUS      0x0000ff00      /* A copy of bus nr */
-#define  PCI_X_STATUS_64BIT    0x00010000      /* 64-bit device */
-#define  PCI_X_STATUS_133MHZ   0x00020000      /* 133 MHz capable */
-#define  PCI_X_STATUS_SPL_DISC 0x00040000      /* Split Completion Discarded */
-#define  PCI_X_STATUS_UNX_SPL  0x00080000      /* Unexpected Split Completion */
-#define  PCI_X_STATUS_COMPLEX  0x00100000      /* Device Complexity */
-#define  PCI_X_STATUS_MAX_READ 0x00600000      /* Designed Max Memory Read Count */
-#define  PCI_X_STATUS_MAX_SPLIT        0x03800000      /* Designed Max Outstanding Split Transactions */
-#define  PCI_X_STATUS_MAX_CUM  0x1c000000      /* Designed Max Cumulative Read Size */
-#define  PCI_X_STATUS_SPL_ERR  0x20000000      /* Rcvd Split Completion Error Msg */
-#define  PCI_X_STATUS_266MHZ   0x40000000      /* 266 MHz capable */
-#define  PCI_X_STATUS_533MHZ   0x80000000      /* 533 MHz capable */
-
-/* PCI Express capability registers */
-
-#define PCI_EXP_FLAGS          2       /* Capabilities register */
-#define PCI_EXP_FLAGS_VERS     0x000f  /* Capability version */
-#define PCI_EXP_FLAGS_TYPE     0x00f0  /* Device/Port type */
-#define  PCI_EXP_TYPE_ENDPOINT 0x0     /* Express Endpoint */
-#define  PCI_EXP_TYPE_LEG_END  0x1     /* Legacy Endpoint */
-#define  PCI_EXP_TYPE_ROOT_PORT 0x4    /* Root Port */
-#define  PCI_EXP_TYPE_UPSTREAM 0x5     /* Upstream Port */
-#define  PCI_EXP_TYPE_DOWNSTREAM 0x6   /* Downstream Port */
-#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7   /* PCI/PCI-X Bridge */
-#define PCI_EXP_FLAGS_SLOT     0x0100  /* Slot implemented */
-#define PCI_EXP_FLAGS_IRQ      0x3e00  /* Interrupt message number */
-#define PCI_EXP_DEVCAP         4       /* Device capabilities */
-#define  PCI_EXP_DEVCAP_PAYLOAD        0x07    /* Max_Payload_Size */
-#define  PCI_EXP_DEVCAP_PHANTOM        0x18    /* Phantom functions */
-#define  PCI_EXP_DEVCAP_EXT_TAG        0x20    /* Extended tags */
-#define  PCI_EXP_DEVCAP_L0S    0x1c0   /* L0s Acceptable Latency */
-#define  PCI_EXP_DEVCAP_L1     0xe00   /* L1 Acceptable Latency */
-#define  PCI_EXP_DEVCAP_ATN_BUT        0x1000  /* Attention Button Present */
-#define  PCI_EXP_DEVCAP_ATN_IND        0x2000  /* Attention Indicator Present */
-#define  PCI_EXP_DEVCAP_PWR_IND        0x4000  /* Power Indicator Present */
-#define  PCI_EXP_DEVCAP_RBER   0x8000  /* Role-Based Error Reporting */
-#define  PCI_EXP_DEVCAP_PWR_VAL        0x3fc0000 /* Slot Power Limit Value */
-#define  PCI_EXP_DEVCAP_PWR_SCL        0xc000000 /* Slot Power Limit Scale */
-#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
-#define PCI_EXP_DEVCTL         8       /* Device Control */
-#define  PCI_EXP_DEVCTL_CERE   0x0001  /* Correctable Error Reporting En. */
-#define  PCI_EXP_DEVCTL_NFERE  0x0002  /* Non-Fatal Error Reporting Enable */
-#define  PCI_EXP_DEVCTL_FERE   0x0004  /* Fatal Error Reporting Enable */
-#define  PCI_EXP_DEVCTL_URRE   0x0008  /* Unsupported Request Reporting En. */
-#define  PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
-#define  PCI_EXP_DEVCTL_PAYLOAD        0x00e0  /* Max_Payload_Size */
-#define  PCI_EXP_DEVCTL_EXT_TAG        0x0100  /* Extended Tag Field Enable */
-#define  PCI_EXP_DEVCTL_PHANTOM        0x0200  /* Phantom Functions Enable */
-#define  PCI_EXP_DEVCTL_AUX_PME        0x0400  /* Auxiliary Power PM Enable */
-#define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
-#define  PCI_EXP_DEVCTL_READRQ 0x7000  /* Max_Read_Request_Size */
-#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
-#define PCI_EXP_DEVSTA         10      /* Device Status */
-#define  PCI_EXP_DEVSTA_CED    0x01    /* Correctable Error Detected */
-#define  PCI_EXP_DEVSTA_NFED   0x02    /* Non-Fatal Error Detected */
-#define  PCI_EXP_DEVSTA_FED    0x04    /* Fatal Error Detected */
-#define  PCI_EXP_DEVSTA_URD    0x08    /* Unsupported Request Detected */
-#define  PCI_EXP_DEVSTA_AUXPD  0x10    /* AUX Power Detected */
-#define  PCI_EXP_DEVSTA_TRPND  0x20    /* Transactions Pending */
-#define PCI_EXP_LNKCAP         12      /* Link Capabilities */
-#define  PCI_EXP_LNKCAP_ASPMS  0xc00   /* ASPM Support */
-#define  PCI_EXP_LNKCAP_L0SEL  0x7000  /* L0s Exit Latency */
-#define  PCI_EXP_LNKCAP_L1EL   0x38000 /* L1 Exit Latency */
-#define  PCI_EXP_LNKCAP_CLKPM  0x40000 /* L1 Clock Power Management */
-#define PCI_EXP_LNKCTL         16      /* Link Control */
-#define  PCI_EXP_LNKCTL_RL     0x20    /* Retrain Link */
-#define  PCI_EXP_LNKCTL_CCC    0x40    /* Common Clock COnfiguration */
-#define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100        /* Enable clkreq */
-#define PCI_EXP_LNKSTA         18      /* Link Status */
-#define  PCI_EXP_LNKSTA_LT     0x800   /* Link Training */
-#define  PCI_EXP_LNKSTA_SLC    0x1000  /* Slot Clock Configuration */
-#define PCI_EXP_SLTCAP         20      /* Slot Capabilities */
-#define PCI_EXP_SLTCTL         24      /* Slot Control */
-#define PCI_EXP_SLTSTA         26      /* Slot Status */
-#define PCI_EXP_RTCTL          28      /* Root Control */
-#define  PCI_EXP_RTCTL_SECEE   0x01    /* System Error on Correctable Error */
-#define  PCI_EXP_RTCTL_SENFEE  0x02    /* System Error on Non-Fatal Error */
-#define  PCI_EXP_RTCTL_SEFEE   0x04    /* System Error on Fatal Error */
-#define  PCI_EXP_RTCTL_PMEIE   0x08    /* PME Interrupt Enable */
-#define  PCI_EXP_RTCTL_CRSSVE  0x10    /* CRS Software Visibility Enable */
-#define PCI_EXP_RTCAP          30      /* Root Capabilities */
-#define PCI_EXP_RTSTA          32      /* Root Status */
-#define PCI_EXP_DEVCAP2                36      /* Device Capabilities 2 */
-#define  PCI_EXP_DEVCAP2_ARI   0x20    /* Alternative Routing-ID */
-#define PCI_EXP_DEVCTL2                40      /* Device Control 2 */
-#define  PCI_EXP_DEVCTL2_ARI   0x20    /* Alternative Routing-ID */
-
-/* Extended Capabilities (PCI-X 2.0 and Express) */
-#define PCI_EXT_CAP_ID(header)         (header & 0x0000ffff)
-#define PCI_EXT_CAP_VER(header)                ((header >> 16) & 0xf)
-#define PCI_EXT_CAP_NEXT(header)       ((header >> 20) & 0xffc)
-
-#define PCI_EXT_CAP_ID_ERR     1
-#define PCI_EXT_CAP_ID_VC      2
-#define PCI_EXT_CAP_ID_DSN     3
-#define PCI_EXT_CAP_ID_PWR     4
-#define PCI_EXT_CAP_ID_ARI     14
-
-/* Advanced Error Reporting */
-#define PCI_ERR_UNCOR_STATUS   4       /* Uncorrectable Error Status */
-#define  PCI_ERR_UNC_TRAIN     0x00000001      /* Training */
-#define  PCI_ERR_UNC_DLP       0x00000010      /* Data Link Protocol */
-#define  PCI_ERR_UNC_POISON_TLP        0x00001000      /* Poisoned TLP */
-#define  PCI_ERR_UNC_FCP       0x00002000      /* Flow Control Protocol */
-#define  PCI_ERR_UNC_COMP_TIME 0x00004000      /* Completion Timeout */
-#define  PCI_ERR_UNC_COMP_ABORT        0x00008000      /* Completer Abort */
-#define  PCI_ERR_UNC_UNX_COMP  0x00010000      /* Unexpected Completion */
-#define  PCI_ERR_UNC_RX_OVER   0x00020000      /* Receiver Overflow */
-#define  PCI_ERR_UNC_MALF_TLP  0x00040000      /* Malformed TLP */
-#define  PCI_ERR_UNC_ECRC      0x00080000      /* ECRC Error Status */
-#define  PCI_ERR_UNC_UNSUP     0x00100000      /* Unsupported Request */
-#define PCI_ERR_UNCOR_MASK     8       /* Uncorrectable Error Mask */
-       /* Same bits as above */
-#define PCI_ERR_UNCOR_SEVER    12      /* Uncorrectable Error Severity */
-       /* Same bits as above */
-#define PCI_ERR_COR_STATUS     16      /* Correctable Error Status */
-#define  PCI_ERR_COR_RCVR      0x00000001      /* Receiver Error Status */
-#define  PCI_ERR_COR_BAD_TLP   0x00000040      /* Bad TLP Status */
-#define  PCI_ERR_COR_BAD_DLLP  0x00000080      /* Bad DLLP Status */
-#define  PCI_ERR_COR_REP_ROLL  0x00000100      /* REPLAY_NUM Rollover */
-#define  PCI_ERR_COR_REP_TIMER 0x00001000      /* Replay Timer Timeout */
-#define PCI_ERR_COR_MASK       20      /* Correctable Error Mask */
-       /* Same bits as above */
-#define PCI_ERR_CAP            24      /* Advanced Error Capabilities */
-#define  PCI_ERR_CAP_FEP(x)    ((x) & 31)      /* First Error Pointer */
-#define  PCI_ERR_CAP_ECRC_GENC 0x00000020      /* ECRC Generation Capable */
-#define  PCI_ERR_CAP_ECRC_GENE 0x00000040      /* ECRC Generation Enable */
-#define  PCI_ERR_CAP_ECRC_CHKC 0x00000080      /* ECRC Check Capable */
-#define  PCI_ERR_CAP_ECRC_CHKE 0x00000100      /* ECRC Check Enable */
-#define PCI_ERR_HEADER_LOG     28      /* Header Log Register (16 bytes) */
-#define PCI_ERR_ROOT_COMMAND   44      /* Root Error Command */
-/* Correctable Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_COR_EN                0x00000001
-/* Non-fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_NONFATAL_EN   0x00000002
-/* Fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_FATAL_EN      0x00000004
-#define PCI_ERR_ROOT_STATUS    48
-#define PCI_ERR_ROOT_COR_RCV           0x00000001      /* ERR_COR Received */
-/* Multi ERR_COR Received */
-#define PCI_ERR_ROOT_MULTI_COR_RCV     0x00000002
-/* ERR_FATAL/NONFATAL Recevied */
-#define PCI_ERR_ROOT_UNCOR_RCV         0x00000004
-/* Multi ERR_FATAL/NONFATAL Recevied */
-#define PCI_ERR_ROOT_MULTI_UNCOR_RCV   0x00000008
-#define PCI_ERR_ROOT_FIRST_FATAL       0x00000010      /* First Fatal */
-#define PCI_ERR_ROOT_NONFATAL_RCV      0x00000020      /* Non-Fatal Received */
-#define PCI_ERR_ROOT_FATAL_RCV         0x00000040      /* Fatal Received */
-#define PCI_ERR_ROOT_COR_SRC   52
-#define PCI_ERR_ROOT_SRC       54
-
-/* Virtual Channel */
-#define PCI_VC_PORT_REG1       4
-#define PCI_VC_PORT_REG2       8
-#define PCI_VC_PORT_CTRL       12
-#define PCI_VC_PORT_STATUS     14
-#define PCI_VC_RES_CAP         16
-#define PCI_VC_RES_CTRL                20
-#define PCI_VC_RES_STATUS      26
-
-/* Power Budgeting */
-#define PCI_PWR_DSR            4       /* Data Select Register */
-#define PCI_PWR_DATA           8       /* Data Register */
-#define  PCI_PWR_DATA_BASE(x)  ((x) & 0xff)        /* Base Power */
-#define  PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3)    /* Data Scale */
-#define  PCI_PWR_DATA_PM_SUB(x)        (((x) >> 10) & 7)   /* PM Sub State */
-#define  PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
-#define  PCI_PWR_DATA_TYPE(x)  (((x) >> 15) & 7)   /* Type */
-#define  PCI_PWR_DATA_RAIL(x)  (((x) >> 18) & 7)   /* Power Rail */
-#define PCI_PWR_CAP            12      /* Capability */
-#define  PCI_PWR_CAP_BUDGET(x) ((x) & 1)       /* Included in system budget */
-
-/*
- * Hypertransport sub capability types
- *
- * Unfortunately there are both 3 bit and 5 bit capability types defined
- * in the HT spec, catering for that is a little messy. You probably don't
- * want to use these directly, just use pci_find_ht_capability() and it
- * will do the right thing for you.
- */
-#define HT_3BIT_CAP_MASK       0xE0
-#define HT_CAPTYPE_SLAVE       0x00    /* Slave/Primary link configuration */
-#define HT_CAPTYPE_HOST                0x20    /* Host/Secondary link configuration */
-
-#define HT_5BIT_CAP_MASK       0xF8
-#define HT_CAPTYPE_IRQ         0x80    /* IRQ Configuration */
-#define HT_CAPTYPE_REMAPPING_40        0xA0    /* 40 bit address remapping */
-#define HT_CAPTYPE_REMAPPING_64 0xA2   /* 64 bit address remapping */
-#define HT_CAPTYPE_UNITID_CLUMP        0x90    /* Unit ID clumping */
-#define HT_CAPTYPE_EXTCONF     0x98    /* Extended Configuration Space Access */
-#define HT_CAPTYPE_MSI_MAPPING 0xA8    /* MSI Mapping Capability */
-#define  HT_MSI_FLAGS          0x02            /* Offset to flags */
-#define  HT_MSI_FLAGS_ENABLE   0x1             /* Mapping enable */
-#define  HT_MSI_FLAGS_FIXED    0x2             /* Fixed mapping only */
-#define  HT_MSI_FIXED_ADDR     0x00000000FEE00000ULL   /* Fixed addr */
-#define  HT_MSI_ADDR_LO                0x04            /* Offset to low addr bits */
-#define  HT_MSI_ADDR_LO_MASK   0xFFF00000      /* Low address bit mask */
-#define  HT_MSI_ADDR_HI                0x08            /* Offset to high addr bits */
-#define HT_CAPTYPE_DIRECT_ROUTE        0xB0    /* Direct routing configuration */
-#define HT_CAPTYPE_VCSET       0xB8    /* Virtual Channel configuration */
-#define HT_CAPTYPE_ERROR_RETRY 0xC0    /* Retry on error configuration */
-#define HT_CAPTYPE_GEN3                0xD0    /* Generation 3 hypertransport configuration */
-#define HT_CAPTYPE_PM          0xE0    /* Hypertransport powermanagement configuration */
-
-/* Alternative Routing-ID Interpretation */
-#define PCI_ARI_CAP            0x04    /* ARI Capability Register */
-#define  PCI_ARI_CAP_MFVC      0x0001  /* MFVC Function Groups Capability */
-#define  PCI_ARI_CAP_ACS       0x0002  /* ACS Function Groups Capability */
-#define  PCI_ARI_CAP_NFN(x)    (((x) >> 8) & 0xff) /* Next Function Number */
-#define PCI_ARI_CTRL           0x06    /* ARI Control Register */
-#define  PCI_ARI_CTRL_MFVC     0x0001  /* MFVC Function Groups Enable */
-#define  PCI_ARI_CTRL_ACS      0x0002  /* ACS Function Groups Enable */
-#define  PCI_ARI_CTRL_FG(x)    (((x) >> 4) & 7) /* Function Group */
-
-#endif /* LINUX_PCI_REGS_H */
index 3c5f519fe1c6dc84be8838b06cafe7d899ccba27..43eb54716734a8f30631dee6c41e388b9429644d 100644 (file)
@@ -7,10 +7,10 @@
 
 #include "types.h" // u32
 #include "util.h" // handle_1ab1
-#include "pci.h" // pci_config_readl
+#include "hw/pci.h" // pci_config_readl
 #include "bregs.h" // struct bregs
 #include "biosvar.h" // GET_GLOBAL
-#include "pci_regs.h" // PCI_VENDOR_ID
+#include "hw/pci_regs.h" // PCI_VENDOR_ID
 
 // romlayout.S
 extern void entry_bios32(void);
index 5259853656230af379b8f213a35a6251df774c58..ca32d43127f4e89b3811d6d78edf5a8b8812c9f0 100644 (file)
@@ -6,9 +6,9 @@
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "util.h" // dprintf
-#include "pci.h" // pci_config_readl
-#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
-#include "pci_regs.h" // PCI_COMMAND
+#include "hw/pci.h" // pci_config_readl
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "hw/pci_regs.h" // PCI_COMMAND
 #include "ioport.h" // PORT_ATA1_CMD_BASE
 #include "config.h" // CONFIG_*
 #include "memmap.h" // add_e820
diff --git a/src/pic.c b/src/pic.c
deleted file mode 100644 (file)
index 9a3ea0b..0000000
--- a/src/pic.c
+++ /dev/null
@@ -1,101 +0,0 @@
-// Helpers for working with i8259 interrupt controller.
-//
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2002  MandrakeSoft S.A.
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "pic.h" // pic_*
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // SET_IVT
-
-u16
-pic_irqmask_read(void)
-{
-    return inb(PORT_PIC1_DATA) | (inb(PORT_PIC2_DATA) << 8);
-}
-
-void
-pic_irqmask_write(u16 mask)
-{
-    outb(mask, PORT_PIC1_DATA);
-    outb(mask >> 8, PORT_PIC2_DATA);
-}
-
-void
-pic_irqmask_mask(u16 off, u16 on)
-{
-    u8 pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8;
-    outb((inb(PORT_PIC1_DATA) & ~pic1off) | pic1on, PORT_PIC1_DATA);
-    outb((inb(PORT_PIC2_DATA) & ~pic2off) | pic2on, PORT_PIC2_DATA);
-}
-
-void
-pic_reset(u8 irq0, u8 irq8)
-{
-    // Send ICW1 (select OCW1 + will send ICW4)
-    outb(0x11, PORT_PIC1_CMD);
-    outb(0x11, PORT_PIC2_CMD);
-    // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15)
-    outb(irq0, PORT_PIC1_DATA);
-    outb(irq8, PORT_PIC2_DATA);
-    // Send ICW3 (cascaded pic ids)
-    outb(0x04, PORT_PIC1_DATA);
-    outb(0x02, PORT_PIC2_DATA);
-    // Send ICW4 (enable 8086 mode)
-    outb(0x01, PORT_PIC1_DATA);
-    outb(0x01, PORT_PIC2_DATA);
-    // Mask all irqs (except cascaded PIC2 irq)
-    pic_irqmask_write(PIC_IRQMASK_DEFAULT);
-}
-
-void
-pic_setup(void)
-{
-    dprintf(3, "init pic\n");
-    pic_reset(BIOS_HWIRQ0_VECTOR, BIOS_HWIRQ8_VECTOR);
-}
-
-void
-enable_hwirq(int hwirq, struct segoff_s func)
-{
-    pic_irqmask_mask(1 << hwirq, 0);
-    int vector;
-    if (hwirq < 8)
-        vector = BIOS_HWIRQ0_VECTOR + hwirq;
-    else
-        vector = BIOS_HWIRQ8_VECTOR + hwirq - 8;
-    SET_IVT(vector, func);
-}
-
-static u8
-pic_isr1_read(void)
-{
-    // 0x0b == select OCW1 + read ISR
-    outb(0x0b, PORT_PIC1_CMD);
-    return inb(PORT_PIC1_CMD);
-}
-
-static u8
-pic_isr2_read(void)
-{
-    // 0x0b == select OCW1 + read ISR
-    outb(0x0b, PORT_PIC2_CMD);
-    return inb(PORT_PIC2_CMD);
-}
-
-// Handler for otherwise unused hardware irqs.
-void VISIBLE16
-handle_hwpic1(struct bregs *regs)
-{
-    dprintf(DEBUG_ISR_hwpic1, "handle_hwpic1 irq=%x\n", pic_isr1_read());
-    pic_eoi1();
-}
-
-void VISIBLE16
-handle_hwpic2(struct bregs *regs)
-{
-    dprintf(DEBUG_ISR_hwpic2, "handle_hwpic2 irq=%x\n", pic_isr2_read());
-    pic_eoi2();
-}
diff --git a/src/pic.h b/src/pic.h
deleted file mode 100644 (file)
index 19aecba..0000000
--- a/src/pic.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Helpers for working with i8259 interrupt controller.
-//
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2002  MandrakeSoft S.A.
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-#ifndef __PIC_H
-#define __PIC_H
-
-#include "ioport.h" // PORT_PIC*
-#include "farptr.h" // struct segoff_s
-
-// PORT_PIC1 bitdefs
-#define PIC1_IRQ0  (1<<0)
-#define PIC1_IRQ1  (1<<1)
-#define PIC1_IRQ2  (1<<2)
-#define PIC1_IRQ5  (1<<5)
-#define PIC1_IRQ6  (1<<6)
-// PORT_PIC2 bitdefs
-#define PIC2_IRQ8  (1<<8)
-#define PIC2_IRQ12 (1<<12)
-#define PIC2_IRQ13 (1<<13)
-#define PIC2_IRQ14 (1<<14)
-
-#define PIC_IRQMASK_DEFAULT ((u16)~PIC1_IRQ2)
-
-#define BIOS_HWIRQ0_VECTOR 0x08
-#define BIOS_HWIRQ8_VECTOR 0x70
-
-static inline void
-pic_eoi1(void)
-{
-    // Send eoi (select OCW2 + eoi)
-    outb(0x20, PORT_PIC1_CMD);
-}
-
-static inline void
-pic_eoi2(void)
-{
-    // Send eoi (select OCW2 + eoi)
-    outb(0x20, PORT_PIC2_CMD);
-    pic_eoi1();
-}
-
-u16 pic_irqmask_read(void);
-void pic_irqmask_write(u16 mask);
-void pic_irqmask_mask(u16 off, u16 on);
-void pic_reset(u8 irq0, u8 irq8);
-void pic_setup(void);
-void enable_hwirq(int hwirq, struct segoff_s func);
-
-#endif // pic.h
index 02e2a678a6c479fef65e647ec1fc8bb7dc0d2835..57fb48f223edfc8368b5adc3aef920625471eda3 100644 (file)
@@ -5,7 +5,7 @@
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
-#include "pci.h" // struct pir_header
+#include "hw/pci.h" // struct pir_header
 #include "config.h" // CONFIG_*
 #include "util.h" // checksum
 
diff --git a/src/pit.h b/src/pit.h
deleted file mode 100644 (file)
index 098f270..0000000
--- a/src/pit.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Definitions for the Intel 8253 Programmable Interrupt Timer (PIT).
-#ifndef __PIT_H
-#define __PIT_H
-
-// Bits for PORT_PIT_MODE
-#define PM_SEL_TIMER0   (0<<6)
-#define PM_SEL_TIMER1   (1<<6)
-#define PM_SEL_TIMER2   (2<<6)
-#define PM_SEL_READBACK (3<<6)
-#define PM_ACCESS_LATCH  (0<<4)
-#define PM_ACCESS_LOBYTE (1<<4)
-#define PM_ACCESS_HIBYTE (2<<4)
-#define PM_ACCESS_WORD   (3<<4)
-#define PM_MODE0 (0<<1)
-#define PM_MODE1 (1<<1)
-#define PM_MODE2 (2<<1)
-#define PM_MODE3 (3<<1)
-#define PM_MODE4 (4<<1)
-#define PM_MODE5 (5<<1)
-#define PM_CNT_BINARY (0<<0)
-#define PM_CNT_BCD    (1<<0)
-#define PM_READ_COUNTER0 (1<<1)
-#define PM_READ_COUNTER1 (1<<2)
-#define PM_READ_COUNTER2 (1<<3)
-#define PM_READ_STATUSVALUE (0<<4)
-#define PM_READ_VALUE       (1<<4)
-#define PM_READ_STATUS      (2<<4)
-
-#endif // pit.h
index 27f5709d73660d136ebcfe57deee634a6b7e5375..9e61580a5b720436db5d2554a42891be980e905c 100644 (file)
@@ -6,25 +6,25 @@
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "config.h" // CONFIG_*
-#include "cmos.h" // CMOS_*
+#include "hw/cmos.h" // CMOS_*
 #include "util.h" // memset
 #include "biosvar.h" // struct bios_data_area_s
 #include "disk.h" // floppy_setup
-#include "ata.h" // ata_setup
-#include "ahci.h" // ahci_setup
+#include "hw/ata.h" // ata_setup
+#include "hw/ahci.h" // ahci_setup
 #include "memmap.h" // add_e820
-#include "pic.h" // pic_setup
+#include "hw/pic.h" // pic_setup
 #include "bregs.h" // struct bregs
 #include "boot.h" // boot_init
-#include "usb.h" // usb_setup
+#include "hw/usb.h" // usb_setup
 #include "paravirt.h" // qemu_cfg_preinit
 #include "xen.h" // xen_preinit
-#include "ps2port.h" // ps2port_setup
-#include "virtio-blk.h" // virtio_blk_setup
-#include "virtio-scsi.h" // virtio_scsi_setup
-#include "lsi-scsi.h" // lsi_scsi_setup
-#include "esp-scsi.h" // esp_scsi_setup
-#include "megasas.h" // megasas_setup
+#include "hw/ps2port.h" // ps2port_setup
+#include "hw/virtio-blk.h" // virtio_blk_setup
+#include "hw/virtio-scsi.h" // virtio_scsi_setup
+#include "hw/lsi-scsi.h" // lsi_scsi_setup
+#include "hw/esp-scsi.h" // esp_scsi_setup
+#include "hw/megasas.h" // megasas_setup
 #include "post.h" // interface_init
 
 
diff --git a/src/ps2port.c b/src/ps2port.c
deleted file mode 100644 (file)
index 4b6c5df..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-// Support for handling the PS/2 mouse/keyboard ports.
-//
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
-// Several ideas taken from code Copyright (c) 1999-2004 Vojtech Pavlik
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "ioport.h" // inb
-#include "util.h" // dprintf
-#include "biosvar.h" // GET_LOW
-#include "ps2port.h" // ps2_kbd_command
-#include "pic.h" // pic_eoi1
-
-
-/****************************************************************
- * Low level i8042 commands.
- ****************************************************************/
-
-// Timeout value.
-#define I8042_CTL_TIMEOUT       10000
-
-#define I8042_BUFFER_SIZE       16
-
-static int
-i8042_wait_read(void)
-{
-    dprintf(7, "i8042_wait_read\n");
-    int i;
-    for (i=0; i<I8042_CTL_TIMEOUT; i++) {
-        u8 status = inb(PORT_PS2_STATUS);
-        if (status & I8042_STR_OBF)
-            return 0;
-        udelay(50);
-    }
-    warn_timeout();
-    return -1;
-}
-
-static int
-i8042_wait_write(void)
-{
-    dprintf(7, "i8042_wait_write\n");
-    int i;
-    for (i=0; i<I8042_CTL_TIMEOUT; i++) {
-        u8 status = inb(PORT_PS2_STATUS);
-        if (! (status & I8042_STR_IBF))
-            return 0;
-        udelay(50);
-    }
-    warn_timeout();
-    return -1;
-}
-
-static int
-i8042_flush(void)
-{
-    dprintf(7, "i8042_flush\n");
-    int i;
-    for (i=0; i<I8042_BUFFER_SIZE; i++) {
-        u8 status = inb(PORT_PS2_STATUS);
-        if (! (status & I8042_STR_OBF))
-            return 0;
-        udelay(50);
-        u8 data = inb(PORT_PS2_DATA);
-        dprintf(7, "i8042 flushed %x (status=%x)\n", data, status);
-    }
-
-    warn_timeout();
-    return -1;
-}
-
-static int
-__i8042_command(int command, u8 *param)
-{
-    int receive = (command >> 8) & 0xf;
-    int send = (command >> 12) & 0xf;
-
-    // Send the command.
-    int ret = i8042_wait_write();
-    if (ret)
-        return ret;
-    outb(command, PORT_PS2_STATUS);
-
-    // Send parameters (if any).
-    int i;
-    for (i = 0; i < send; i++) {
-        ret = i8042_wait_write();
-        if (ret)
-            return ret;
-        outb(param[i], PORT_PS2_DATA);
-    }
-
-    // Receive parameters (if any).
-    for (i = 0; i < receive; i++) {
-        ret = i8042_wait_read();
-        if (ret)
-            return ret;
-        param[i] = inb(PORT_PS2_DATA);
-        dprintf(7, "i8042 param=%x\n", param[i]);
-    }
-
-    return 0;
-}
-
-static int
-i8042_command(int command, u8 *param)
-{
-    dprintf(7, "i8042_command cmd=%x\n", command);
-    int ret = __i8042_command(command, param);
-    if (ret)
-        dprintf(2, "i8042 command %x failed\n", command);
-    return ret;
-}
-
-static int
-i8042_kbd_write(u8 c)
-{
-    dprintf(7, "i8042_kbd_write c=%d\n", c);
-    int ret = i8042_wait_write();
-    if (! ret)
-        outb(c, PORT_PS2_DATA);
-    return ret;
-}
-
-static int
-i8042_aux_write(u8 c)
-{
-    return i8042_command(I8042_CMD_AUX_SEND, &c);
-}
-
-void
-i8042_reboot(void)
-{
-    if (! CONFIG_PS2PORT)
-       return;
-    int i;
-    for (i=0; i<10; i++) {
-        i8042_wait_write();
-        udelay(50);
-        outb(0xfe, PORT_PS2_STATUS); /* pulse reset low */
-        udelay(50);
-    }
-}
-
-
-/****************************************************************
- * Device commands.
- ****************************************************************/
-
-#define PS2_RET_ACK             0xfa
-#define PS2_RET_NAK             0xfe
-
-static int
-ps2_recvbyte(int aux, int needack, int timeout)
-{
-    u32 end = timer_calc(timeout);
-    for (;;) {
-        u8 status = inb(PORT_PS2_STATUS);
-        if (status & I8042_STR_OBF) {
-            u8 data = inb(PORT_PS2_DATA);
-            dprintf(7, "ps2 read %x\n", data);
-
-            if (!!(status & I8042_STR_AUXDATA) == aux) {
-                if (!needack)
-                    return data;
-                if (data == PS2_RET_ACK)
-                    return data;
-                if (data == PS2_RET_NAK) {
-                    dprintf(1, "Got ps2 nak (status=%x)\n", status);
-                    return data;
-                }
-            }
-
-            // This data not part of command - just discard it.
-            dprintf(1, "Discarding ps2 data %02x (status=%02x)\n", data, status);
-        }
-
-        if (timer_check(end)) {
-            // Don't warn on second byte of a reset
-            if (timeout > 100)
-                warn_timeout();
-            return -1;
-        }
-        yield();
-    }
-}
-
-static int
-ps2_sendbyte(int aux, u8 command, int timeout)
-{
-    dprintf(7, "ps2_sendbyte aux=%d cmd=%x\n", aux, command);
-    int ret;
-    if (aux)
-        ret = i8042_aux_write(command);
-    else
-        ret = i8042_kbd_write(command);
-    if (ret)
-        return ret;
-
-    // Read ack.
-    ret = ps2_recvbyte(aux, 1, timeout);
-    if (ret < 0)
-        return ret;
-    if (ret != PS2_RET_ACK)
-        return -1;
-
-    return 0;
-}
-
-u8 Ps2ctr VARLOW;
-
-static int
-__ps2_command(int aux, int command, u8 *param)
-{
-    int ret2;
-    int receive = (command >> 8) & 0xf;
-    int send = (command >> 12) & 0xf;
-
-    // Disable interrupts and keyboard/mouse.
-    u8 ps2ctr = GET_LOW(Ps2ctr);
-    u8 newctr = ((ps2ctr | I8042_CTR_AUXDIS | I8042_CTR_KBDDIS)
-                 & ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT));
-    dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr);
-    int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr);
-    if (ret)
-        return ret;
-
-    // Flush any interrupts already pending.
-    yield();
-
-    // Enable port command is being sent to.
-    if (aux)
-        newctr &= ~I8042_CTR_AUXDIS;
-    else
-        newctr &= ~I8042_CTR_KBDDIS;
-    ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr);
-    if (ret)
-        goto fail;
-
-    if (command == ATKBD_CMD_RESET_BAT) {
-        // Reset is special wrt timeouts and bytes received.
-
-        // Send command.
-        ret = ps2_sendbyte(aux, command, 1000);
-        if (ret)
-            goto fail;
-
-        // Receive parameters.
-        ret = ps2_recvbyte(aux, 0, 4000);
-        if (ret < 0)
-            goto fail;
-        param[0] = ret;
-        ret = ps2_recvbyte(aux, 0, 100);
-        if (ret < 0)
-            // Some devices only respond with one byte on reset.
-            ret = 0;
-        param[1] = ret;
-    } else if (command == ATKBD_CMD_GETID) {
-        // Getid is special wrt bytes received.
-
-        // Send command.
-        ret = ps2_sendbyte(aux, command, 200);
-        if (ret)
-            goto fail;
-
-        // Receive parameters.
-        ret = ps2_recvbyte(aux, 0, 500);
-        if (ret < 0)
-            goto fail;
-        param[0] = ret;
-        if (ret == 0xab || ret == 0xac || ret == 0x2b || ret == 0x5d
-            || ret == 0x60 || ret == 0x47) {
-            // These ids (keyboards) return two bytes.
-            ret = ps2_recvbyte(aux, 0, 500);
-            if (ret < 0)
-                goto fail;
-            param[1] = ret;
-        } else {
-            param[1] = 0;
-        }
-    } else {
-        // Send command.
-        ret = ps2_sendbyte(aux, command, 200);
-        if (ret)
-            goto fail;
-
-        // Send parameters (if any).
-        int i;
-        for (i = 0; i < send; i++) {
-            ret = ps2_sendbyte(aux, param[i], 200);
-            if (ret)
-                goto fail;
-        }
-
-        // Receive parameters (if any).
-        for (i = 0; i < receive; i++) {
-            ret = ps2_recvbyte(aux, 0, 500);
-            if (ret < 0)
-                goto fail;
-            param[i] = ret;
-        }
-    }
-
-    ret = 0;
-
-fail:
-    // Restore interrupts and keyboard/mouse.
-    ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr);
-    if (ret2)
-        return ret2;
-
-    return ret;
-}
-
-static int
-ps2_command(int aux, int command, u8 *param)
-{
-    dprintf(7, "ps2_command aux=%d cmd=%x\n", aux, command);
-    int ret = __ps2_command(aux, command, param);
-    if (ret)
-        dprintf(2, "ps2 command %x failed (aux=%d)\n", command, aux);
-    return ret;
-}
-
-int
-ps2_kbd_command(int command, u8 *param)
-{
-    if (! CONFIG_PS2PORT)
-        return -1;
-    return ps2_command(0, command, param);
-}
-
-int
-ps2_mouse_command(int command, u8 *param)
-{
-    if (! CONFIG_PS2PORT)
-        return -1;
-
-    // Update ps2ctr for mouse enable/disable.
-    if (command == PSMOUSE_CMD_ENABLE || command == PSMOUSE_CMD_DISABLE) {
-        u8 ps2ctr = GET_LOW(Ps2ctr);
-        if (command == PSMOUSE_CMD_ENABLE)
-            ps2ctr = (ps2ctr | I8042_CTR_AUXINT) & ~I8042_CTR_AUXDIS;
-        else
-            ps2ctr = (ps2ctr | I8042_CTR_AUXDIS) & ~I8042_CTR_AUXINT;
-        SET_LOW(Ps2ctr, ps2ctr);
-    }
-
-    return ps2_command(1, command, param);
-}
-
-
-/****************************************************************
- * IRQ handlers
- ****************************************************************/
-
-// INT74h : PS/2 mouse hardware interrupt
-void VISIBLE16
-handle_74(void)
-{
-    if (! CONFIG_PS2PORT)
-        return;
-
-    debug_isr(DEBUG_ISR_74);
-
-    u8 v = inb(PORT_PS2_STATUS);
-    if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA))
-        != (I8042_STR_OBF|I8042_STR_AUXDATA)) {
-        dprintf(1, "ps2 mouse irq but no mouse data.\n");
-        goto done;
-    }
-    v = inb(PORT_PS2_DATA);
-
-    if (!(GET_LOW(Ps2ctr) & I8042_CTR_AUXINT))
-        // Interrupts not enabled.
-        goto done;
-
-    process_mouse(v);
-
-done:
-    pic_eoi2();
-}
-
-// INT09h : Keyboard Hardware Service Entry Point
-void VISIBLE16
-handle_09(void)
-{
-    if (! CONFIG_PS2PORT)
-        return;
-
-    debug_isr(DEBUG_ISR_09);
-
-    // read key from keyboard controller
-    u8 v = inb(PORT_PS2_STATUS);
-    if (v & I8042_STR_AUXDATA) {
-        dprintf(1, "ps2 keyboard irq but found mouse data?!\n");
-        goto done;
-    }
-    v = inb(PORT_PS2_DATA);
-
-    if (!(GET_LOW(Ps2ctr) & I8042_CTR_KBDINT))
-        // Interrupts not enabled.
-        goto done;
-
-    process_key(v);
-
-    // Some old programs expect ISR to turn keyboard back on.
-    i8042_command(I8042_CMD_KBD_ENABLE, NULL);
-
-done:
-    pic_eoi1();
-}
-
-
-/****************************************************************
- * Setup
- ****************************************************************/
-
-static void
-ps2_keyboard_setup(void *data)
-{
-    /* flush incoming keys */
-    int ret = i8042_flush();
-    if (ret)
-        return;
-
-    // Controller self-test.
-    u8 param[2];
-    ret = i8042_command(I8042_CMD_CTL_TEST, param);
-    if (ret)
-        return;
-    if (param[0] != 0x55) {
-        dprintf(1, "i8042 self test failed (got %x not 0x55)\n", param[0]);
-        return;
-    }
-
-    // Controller keyboard test.
-    ret = i8042_command(I8042_CMD_KBD_TEST, param);
-    if (ret)
-        return;
-    if (param[0] != 0x00) {
-        dprintf(1, "i8042 keyboard test failed (got %x not 0x00)\n", param[0]);
-        return;
-    }
-
-    // Disable keyboard and mouse events.
-    SET_LOW(Ps2ctr, I8042_CTR_KBDDIS | I8042_CTR_AUXDIS);
-
-
-    /* ------------------- keyboard side ------------------------*/
-    /* reset keyboard and self test  (keyboard side) */
-    int spinupdelay = romfile_loadint("etc/ps2-keyboard-spinup", 0);
-    u32 end = timer_calc(spinupdelay);
-    for (;;) {
-        ret = ps2_kbd_command(ATKBD_CMD_RESET_BAT, param);
-        if (!ret)
-            break;
-        if (timer_check(end)) {
-            if (spinupdelay)
-                warn_timeout();
-            return;
-        }
-        yield();
-    }
-    if (param[0] != 0xaa) {
-        dprintf(1, "keyboard self test failed (got %x not 0xaa)\n", param[0]);
-        return;
-    }
-
-    /* Disable keyboard */
-    ret = ps2_kbd_command(ATKBD_CMD_RESET_DIS, NULL);
-    if (ret)
-        return;
-
-    // Set scancode command (mode 2)
-    param[0] = 0x02;
-    ret = ps2_kbd_command(ATKBD_CMD_SSCANSET, param);
-    if (ret)
-        return;
-
-    // Keyboard Mode: disable mouse, scan code convert, enable kbd IRQ
-    SET_LOW(Ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT);
-
-    /* Enable keyboard */
-    ret = ps2_kbd_command(ATKBD_CMD_ENABLE, NULL);
-    if (ret)
-        return;
-
-    dprintf(1, "PS2 keyboard initialized\n");
-}
-
-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(ps2_keyboard_setup, NULL);
-}
diff --git a/src/ps2port.h b/src/ps2port.h
deleted file mode 100644 (file)
index dcae391..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// Basic ps2 port (keyboard/mouse) command handling.
-#ifndef __PS2PORT_H
-#define __PS2PORT_H
-
-#include "types.h" // u8
-
-// Standard commands.
-#define I8042_CMD_CTL_RCTR      0x0120
-#define I8042_CMD_CTL_WCTR      0x1060
-#define I8042_CMD_CTL_TEST      0x01aa
-
-#define I8042_CMD_KBD_TEST      0x01ab
-#define I8042_CMD_KBD_DISABLE   0x00ad
-#define I8042_CMD_KBD_ENABLE    0x00ae
-
-#define I8042_CMD_AUX_DISABLE   0x00a7
-#define I8042_CMD_AUX_ENABLE    0x00a8
-#define I8042_CMD_AUX_SEND      0x10d4
-
-// Keyboard commands
-#define ATKBD_CMD_SETLEDS       0x10ed
-#define ATKBD_CMD_SSCANSET      0x10f0
-#define ATKBD_CMD_GETID         0x02f2
-#define ATKBD_CMD_ENABLE        0x00f4
-#define ATKBD_CMD_RESET_DIS     0x00f5
-#define ATKBD_CMD_RESET_BAT     0x02ff
-
-// Mouse commands
-#define PSMOUSE_CMD_SETSCALE11  0x00e6
-#define PSMOUSE_CMD_SETSCALE21  0x00e7
-#define PSMOUSE_CMD_SETRES      0x10e8
-#define PSMOUSE_CMD_GETINFO     0x03e9
-#define PSMOUSE_CMD_GETID       0x02f2
-#define PSMOUSE_CMD_SETRATE     0x10f3
-#define PSMOUSE_CMD_ENABLE      0x00f4
-#define PSMOUSE_CMD_DISABLE     0x00f5
-#define PSMOUSE_CMD_RESET_BAT   0x02ff
-
-// Status register bits.
-#define I8042_STR_PARITY        0x80
-#define I8042_STR_TIMEOUT       0x40
-#define I8042_STR_AUXDATA       0x20
-#define I8042_STR_KEYLOCK       0x10
-#define I8042_STR_CMDDAT        0x08
-#define I8042_STR_MUXERR        0x04
-#define I8042_STR_IBF           0x02
-#define I8042_STR_OBF           0x01
-
-// Control register bits.
-#define I8042_CTR_KBDINT        0x01
-#define I8042_CTR_AUXINT        0x02
-#define I8042_CTR_IGNKEYLOCK    0x08
-#define I8042_CTR_KBDDIS        0x10
-#define I8042_CTR_AUXDIS        0x20
-#define I8042_CTR_XLATE         0x40
-
-// functions
-void i8042_reboot(void);
-int ps2_kbd_command(int command, u8 *param);
-int ps2_mouse_command(int command, u8 *param);
-void ps2port_setup(void);
-
-#endif // ps2port.h
diff --git a/src/ramdisk.c b/src/ramdisk.c
deleted file mode 100644 (file)
index b9da2ad..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// Code for emulating a drive via high-memory accesses.
-//
-// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "disk.h" // process_ramdisk_op
-#include "util.h" // dprintf
-#include "memmap.h" // add_e820
-#include "biosvar.h" // GET_GLOBAL
-#include "bregs.h" // struct bregs
-#include "boot.h" // boot_add_floppy
-
-void
-ramdisk_setup(void)
-{
-    if (!CONFIG_FLASH_FLOPPY)
-        return;
-
-    // Find image.
-    struct romfile_s *file = romfile_findprefix("floppyimg/", NULL);
-    if (!file)
-        return;
-    const char *filename = file->name;
-    u32 size = file->size;
-    dprintf(3, "Found floppy file %s of size %d\n", filename, size);
-    int ftype = find_floppy_type(size);
-    if (ftype < 0) {
-        dprintf(3, "No floppy type found for ramdisk size\n");
-        return;
-    }
-
-    // Allocate ram for image.
-    void *pos = memalign_tmphigh(PAGE_SIZE, size);
-    if (!pos) {
-        warn_noalloc();
-        return;
-    }
-    add_e820((u32)pos, size, E820_RESERVED);
-
-    // Copy image into ram.
-    int ret = file->copy(file, pos, size);
-    if (ret < 0)
-        return;
-
-    // Setup driver.
-    struct drive_s *drive_g = init_floppy((u32)pos, ftype);
-    if (!drive_g)
-        return;
-    drive_g->type = DTYPE_RAMDISK;
-    dprintf(1, "Mapping CBFS floppy %s to addr %p\n", filename, pos);
-    char *desc = znprintf(MAXDESCSIZE, "Ramdisk [%s]", &filename[10]);
-    boot_add_floppy(drive_g, desc, bootprio_find_named_rom(filename, 0));
-}
-
-static int
-ramdisk_copy(struct disk_op_s *op, int iswrite)
-{
-    u32 offset = GET_GLOBAL(op->drive_g->cntl_id);
-    offset += (u32)op->lba * DISK_SECTOR_SIZE;
-    u64 opd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)op->buf_fl);
-    u64 ramd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE(offset);
-
-    u64 gdt[6];
-    if (iswrite) {
-        gdt[2] = opd;
-        gdt[3] = ramd;
-    } else {
-        gdt[2] = ramd;
-        gdt[3] = opd;
-    }
-
-    // Call int 1587 to copy data.
-    struct bregs br;
-    memset(&br, 0, sizeof(br));
-    br.flags = F_CF|F_IF;
-    br.ah = 0x87;
-    br.es = GET_SEG(SS);
-    br.si = (u32)gdt;
-    br.cx = op->count * DISK_SECTOR_SIZE / 2;
-    call16_int(0x15, &br);
-
-    if (br.flags & F_CF)
-        return DISK_RET_EBADTRACK;
-    return DISK_RET_SUCCESS;
-}
-
-int
-process_ramdisk_op(struct disk_op_s *op)
-{
-    if (!CONFIG_FLASH_FLOPPY)
-        return 0;
-
-    switch (op->command) {
-    case CMD_READ:
-        return ramdisk_copy(op, 0);
-    case CMD_WRITE:
-        return ramdisk_copy(op, 1);
-    case CMD_VERIFY:
-    case CMD_FORMAT:
-    case CMD_RESET:
-        return DISK_RET_SUCCESS;
-    default:
-        op->count = 0;
-        return DISK_RET_EPARAM;
-    }
-}
index 48e1bd88bea12f02f7bf571d01df362acff2b122..8ec6e37ba499e76d045dfb638d884c6a28acb1ee 100644 (file)
@@ -6,13 +6,13 @@
 
 #include "util.h" // dprintf
 #include "ioport.h" // outb
-#include "pic.h" // pic_eoi2
+#include "hw/pic.h" // pic_eoi2
 #include "biosvar.h" // struct bios_data_area_s
 #include "bregs.h" // struct bregs
 #include "acpi.h" // find_resume_vector
-#include "ps2port.h" // i8042_reboot
-#include "pci.h" // pci_reboot
-#include "cmos.h" // inb_cmos
+#include "hw/ps2port.h" // i8042_reboot
+#include "hw/pci.h" // pci_reboot
+#include "hw/cmos.h" // inb_cmos
 
 // Indicator if POST phase has been run.
 int HaveRunPost VARFSEG;
index 291b7980a1e65b542c4ac4e5fdd708d8c7f14b46..cc97f9a9f85e19475b3b914b158a643c034c1844 100644 (file)
@@ -8,7 +8,7 @@
 #include "config.h" // CONFIG_*
 #include "ioport.h" // PORT_A20
 #include "bregs.h" // CR0_*
-#include "cmos.h" // CMOS_RESET_CODE
+#include "hw/cmos.h" // CMOS_RESET_CODE
 #include "asm-offsets.h" // BREGS_*
 #include "entryfuncs.S" // ENTRY_*
 
index 966e88d227f0e291b8f763aed19f690f30caefe6..67e943f2d12c0d86ad9c8b6e12035ba76f7ae758 100644 (file)
@@ -6,10 +6,10 @@
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "util.h" // memcpy
-#include "pci.h" // pci_config_writeb
+#include "hw/pci.h" // pci_config_writeb
 #include "config.h" // CONFIG_*
-#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
-#include "pci_regs.h" // PCI_VENDOR_ID
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "hw/pci_regs.h" // PCI_VENDOR_ID
 #include "paravirt.h" // runningOnXen
 #include "dev-q35.h" // PCI_VENDOR_ID_INTEL
 
index 8abf15bfcbc0a9c695d6a691f00e17576334d15e..3f01207e170ee366a5cb7011ef074a71cb9ddb33 100644 (file)
--- a/src/smm.c
+++ b/src/smm.c
@@ -5,12 +5,12 @@
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
-#include "pci.h" // pci_config_writel
-#include "pci_regs.h" // PCI_DEVICE_ID
+#include "hw/pci.h" // pci_config_writel
+#include "hw/pci_regs.h" // PCI_DEVICE_ID
 #include "util.h" // wbinvd
 #include "config.h" // CONFIG_*
 #include "ioport.h" // outb
-#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "dev-q35.h"
 
 extern u8 smm_relocation_start, smm_relocation_end;
index 0b31573fb01a1256b426e183810385f80bde3e58..6379d364296a9d3fb65cf706f4246dcef52d5b7e 100644 (file)
--- a/src/smp.c
+++ b/src/smp.c
@@ -7,7 +7,7 @@
 
 #include "util.h" // dprintf
 #include "config.h" // CONFIG_*
-#include "cmos.h" // CMOS_BIOS_SMP_COUNT
+#include "hw/cmos.h" // CMOS_BIOS_SMP_COUNT
 
 #define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300)
 #define APIC_SVR     ((u8*)BUILD_APIC_ADDR + 0x0F0)
index 3c815b38dd99ea82c4a85b0d2b842940ec9cb9c7..5269ccf97cbe247c5f9537cfc9dc06aab0547ef1 100644 (file)
@@ -9,7 +9,7 @@
 #include "biosvar.h" // BIOS_CONFIG_TABLE
 #include "ioport.h" // inb
 #include "memmap.h" // E820_RAM
-#include "pic.h" // pic_reset
+#include "hw/pic.h" // pic_reset
 #include "bregs.h" // struct bregs
 
 // Use PS2 System Control port A to set A20 enable
diff --git a/src/timer.c b/src/timer.c
deleted file mode 100644 (file)
index b368362..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-// Internal timer support.
-//
-// Copyright (C) 2008-2013  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pit.h" // PM_SEL_TIMER0
-#include "ioport.h" // PORT_PIT_MODE
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // GET_LOW
-
-// Bits for PORT_PS2_CTRLB
-#define PPCB_T2GATE (1<<0)
-#define PPCB_SPKR   (1<<1)
-#define PPCB_T2OUT  (1<<5)
-
-#define PMTIMER_HZ 3579545      // Underlying Hz of the PM Timer
-#define PMTIMER_TO_PIT 3        // Ratio of pmtimer rate to pit rate
-
-u32 TimerKHz VARFSEG;
-u16 TimerPort VARFSEG;
-u8 ShiftTSC VARFSEG;
-
-
-/****************************************************************
- * Timer setup
- ****************************************************************/
-
-#define CALIBRATE_COUNT 0x800   // Approx 1.7ms
-
-// Calibrate the CPU time-stamp-counter
-static void
-tsctimer_setup(void)
-{
-    // Setup "timer2"
-    u8 orig = inb(PORT_PS2_CTRLB);
-    outb((orig & ~PPCB_SPKR) | PPCB_T2GATE, PORT_PS2_CTRLB);
-    /* binary, mode 0, LSB/MSB, Ch 2 */
-    outb(PM_SEL_TIMER2|PM_ACCESS_WORD|PM_MODE0|PM_CNT_BINARY, PORT_PIT_MODE);
-    /* LSB of ticks */
-    outb(CALIBRATE_COUNT & 0xFF, PORT_PIT_COUNTER2);
-    /* MSB of ticks */
-    outb(CALIBRATE_COUNT >> 8, PORT_PIT_COUNTER2);
-
-    u64 start = rdtscll();
-    while ((inb(PORT_PS2_CTRLB) & PPCB_T2OUT) == 0)
-        ;
-    u64 end = rdtscll();
-
-    // Restore PORT_PS2_CTRLB
-    outb(orig, PORT_PS2_CTRLB);
-
-    // Store calibrated cpu khz.
-    u64 diff = end - start;
-    dprintf(6, "tsc calibrate start=%u end=%u diff=%u\n"
-            , (u32)start, (u32)end, (u32)diff);
-    u64 t = DIV_ROUND_UP(diff * PMTIMER_HZ, CALIBRATE_COUNT);
-    while (t >= (1<<24)) {
-        ShiftTSC++;
-        t = (t + 1) >> 1;
-    }
-    TimerKHz = DIV_ROUND_UP((u32)t, 1000 * PMTIMER_TO_PIT);
-
-    dprintf(1, "CPU Mhz=%u\n", (TimerKHz << ShiftTSC) / 1000);
-}
-
-// Setup internal timers.
-void
-timer_setup(void)
-{
-    if (CONFIG_PMTIMER && TimerPort) {
-        dprintf(3, "pmtimer already configured; will not calibrate TSC\n");
-        return;
-    }
-
-    u32 eax, ebx, ecx, edx, cpuid_features = 0;
-    cpuid(0, &eax, &ebx, &ecx, &edx);
-    if (eax > 0)
-        cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
-
-    if (!(cpuid_features & CPUID_TSC)) {
-        TimerPort = PORT_PIT_COUNTER0;
-        TimerKHz = DIV_ROUND_UP(PMTIMER_HZ, 1000 * PMTIMER_TO_PIT);
-        dprintf(3, "386/486 class CPU. Using TSC emulation\n");
-        return;
-    }
-
-    tsctimer_setup();
-}
-
-void
-pmtimer_setup(u16 ioport)
-{
-    if (!CONFIG_PMTIMER)
-        return;
-    dprintf(1, "Using pmtimer, ioport 0x%x\n", ioport);
-    TimerPort = ioport;
-    TimerKHz = DIV_ROUND_UP(PMTIMER_HZ, 1000);
-}
-
-
-/****************************************************************
- * Internal timer reading
- ****************************************************************/
-
-u32 TimerLast VARLOW;
-
-// Add extra high bits to timers that have less than 32bits of precision.
-static u32
-timer_adjust_bits(u32 value, u32 validbits)
-{
-    u32 last = GET_LOW(TimerLast);
-    value = (last & ~validbits) | (value & validbits);
-    if (value < last)
-        value += validbits + 1;
-    SET_LOW(TimerLast, value);
-    return value;
-}
-
-// Sample the current timer value.
-static u32
-timer_read(void)
-{
-    u16 port = GET_GLOBAL(TimerPort);
-    if (!port)
-        // Read from CPU TSC
-        return rdtscll() >> GET_GLOBAL(ShiftTSC);
-    if (CONFIG_PMTIMER && port != PORT_PIT_COUNTER0)
-        // Read from PMTIMER
-        return timer_adjust_bits(inl(port), 0xffffff);
-    // Read from PIT.
-    outb(PM_SEL_READBACK | PM_READ_VALUE | PM_READ_COUNTER0, PORT_PIT_MODE);
-    u16 v = inb(PORT_PIT_COUNTER0) | (inb(PORT_PIT_COUNTER0) << 8);
-    return timer_adjust_bits(v, 0xffff);
-}
-
-// Check if the current time is past a previously calculated end time.
-int
-timer_check(u32 end)
-{
-    return (s32)(timer_read() - end) > 0;
-}
-
-static void
-timer_delay(u32 diff)
-{
-    u32 start = timer_read();
-    u32 end = start + diff;
-    while (!timer_check(end))
-        cpu_relax();
-}
-
-static void
-timer_sleep(u32 diff)
-{
-    u32 start = timer_read();
-    u32 end = start + diff;
-    while (!timer_check(end))
-        yield();
-}
-
-void ndelay(u32 count) {
-    timer_delay(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000000));
-}
-void udelay(u32 count) {
-    timer_delay(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000));
-}
-void mdelay(u32 count) {
-    timer_delay(count * GET_GLOBAL(TimerKHz));
-}
-
-void nsleep(u32 count) {
-    timer_sleep(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000000));
-}
-void usleep(u32 count) {
-    timer_sleep(DIV_ROUND_UP(count * GET_GLOBAL(TimerKHz), 1000));
-}
-void msleep(u32 count) {
-    timer_sleep(count * GET_GLOBAL(TimerKHz));
-}
-
-// Return the TSC value that is 'msecs' time in the future.
-u32
-timer_calc(u32 msecs)
-{
-    return timer_read() + (GET_GLOBAL(TimerKHz) * msecs);
-}
-u32
-timer_calc_usec(u32 usecs)
-{
-    return timer_read() + DIV_ROUND_UP(GET_GLOBAL(TimerKHz) * usecs, 1000);
-}
-
-
-/****************************************************************
- * IRQ based timer
- ****************************************************************/
-
-#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer
-
-// Return the number of milliseconds in 'ticks' number of timer irqs.
-u32
-ticks_to_ms(u32 ticks)
-{
-    u32 t = PIT_TICK_INTERVAL * 1000 * PMTIMER_TO_PIT * ticks;
-    return DIV_ROUND_UP(t, PMTIMER_HZ);
-}
-
-// Return the number of timer irqs in 'ms' number of milliseconds.
-u32
-ticks_from_ms(u32 ms)
-{
-    u32 t = DIV_ROUND_UP((u64)ms * PMTIMER_HZ, PIT_TICK_INTERVAL);
-    return DIV_ROUND_UP(t, 1000 * PMTIMER_TO_PIT);
-}
-
-// Calculate the timer value at 'count' number of full timer ticks in
-// the future.
-u32
-irqtimer_calc_ticks(u32 count)
-{
-    return (GET_BDA(timer_counter) + count + 1) % TICKS_PER_DAY;
-}
-
-// Return the timer value that is 'msecs' time in the future.
-u32
-irqtimer_calc(u32 msecs)
-{
-    if (!msecs)
-        return GET_BDA(timer_counter);
-    return irqtimer_calc_ticks(ticks_from_ms(msecs));
-}
-
-// Check if the given timer value has passed.
-int
-irqtimer_check(u32 end)
-{
-    return (((GET_BDA(timer_counter) + TICKS_PER_DAY - end) % TICKS_PER_DAY)
-            < (TICKS_PER_DAY/2));
-}
diff --git a/src/usb-ehci.c b/src/usb-ehci.c
deleted file mode 100644 (file)
index 978ca68..0000000
+++ /dev/null
@@ -1,723 +0,0 @@
-// Code for handling EHCI USB controllers.
-//
-// Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // pci_bdf_to_bus
-#include "config.h" // CONFIG_*
-#include "ioport.h" // outw
-#include "usb-ehci.h" // struct ehci_qh
-#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI
-#include "pci_regs.h" // PCI_BASE_ADDRESS_0
-#include "usb.h" // struct usb_s
-#include "biosvar.h" // GET_LOWFLAT
-#include "usb-uhci.h" // uhci_setup
-#include "usb-ohci.h" // ohci_setup
-
-struct usb_ehci_s {
-    struct usb_s usb;
-    struct ehci_caps *caps;
-    struct ehci_regs *regs;
-    struct ehci_qh *async_qh;
-    struct pci_device *companion[8];
-    int checkports;
-    int legacycount;
-};
-
-struct ehci_pipe {
-    struct ehci_qh qh;
-    struct ehci_qtd *next_td, *tds;
-    void *data;
-    struct usb_pipe pipe;
-};
-
-
-/****************************************************************
- * Root hub
- ****************************************************************/
-
-#define EHCI_TIME_POSTPOWER 20
-#define EHCI_TIME_POSTRESET 2
-
-// Check if need companion controllers for full/low speed devices
-static void
-ehci_note_port(struct usb_ehci_s *cntl)
-{
-    if (--cntl->checkports)
-        // Ports still being detected.
-        return;
-    if (! cntl->legacycount)
-        // No full/low speed devices found.
-        return;
-    // Start companion controllers.
-    int i;
-    for (i=0; i<ARRAY_SIZE(cntl->companion); i++) {
-        struct pci_device *pci = cntl->companion[i];
-        if (!pci)
-            break;
-
-        // ohci/uhci_setup call pci_config_X - don't run from irq handler.
-        wait_preempt();
-
-        if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI)
-            uhci_setup(pci, cntl->usb.busid + i);
-        else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI)
-            ohci_setup(pci, cntl->usb.busid + i);
-    }
-}
-
-// Check if device attached to port
-static int
-ehci_hub_detect(struct usbhub_s *hub, u32 port)
-{
-    struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
-    u32 *portreg = &cntl->regs->portsc[port];
-    u32 portsc = readl(portreg);
-
-    // Power up port.
-    if (!(portsc & PORT_POWER)) {
-        portsc |= PORT_POWER;
-        writel(portreg, portsc);
-        msleep(EHCI_TIME_POSTPOWER);
-    } else {
-        // Port is already powered up, but we don't know how long it
-        // has been powered up, so wait the 20ms.
-        msleep(EHCI_TIME_POSTPOWER);
-    }
-    portsc = readl(portreg);
-
-    if (!(portsc & PORT_CONNECT))
-        // No device present
-        goto doneearly;
-
-    if ((portsc & PORT_LINESTATUS_MASK) == PORT_LINESTATUS_KSTATE) {
-        // low speed device
-        cntl->legacycount++;
-        writel(portreg, portsc | PORT_OWNER);
-        goto doneearly;
-    }
-
-    // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
-
-    // Begin reset on port
-    portsc = (portsc & ~PORT_PE) | PORT_RESET;
-    writel(portreg, portsc);
-    msleep(USB_TIME_DRSTR);
-    return 0;
-
-doneearly:
-    ehci_note_port(cntl);
-    return -1;
-}
-
-// Reset device on port
-static int
-ehci_hub_reset(struct usbhub_s *hub, u32 port)
-{
-    struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
-    u32 *portreg = &cntl->regs->portsc[port];
-    u32 portsc = readl(portreg);
-
-    // Finish reset on port
-    portsc &= ~PORT_RESET;
-    writel(portreg, portsc);
-    msleep(EHCI_TIME_POSTRESET);
-
-    int rv = -1;
-    portsc = readl(portreg);
-    if (!(portsc & PORT_CONNECT))
-        // No longer connected
-        goto resetfail;
-    if (!(portsc & PORT_PE)) {
-        // full speed device
-        cntl->legacycount++;
-        writel(portreg, portsc | PORT_OWNER);
-        goto resetfail;
-    }
-
-    rv = USB_HIGHSPEED;
-resetfail:
-    ehci_note_port(cntl);
-    return rv;
-}
-
-// Disable port
-static void
-ehci_hub_disconnect(struct usbhub_s *hub, u32 port)
-{
-    struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
-    u32 *portreg = &cntl->regs->portsc[port];
-    u32 portsc = readl(portreg);
-    writel(portreg, portsc & ~PORT_PE);
-}
-
-static struct usbhub_op_s ehci_HubOp = {
-    .detect = ehci_hub_detect,
-    .reset = ehci_hub_reset,
-    .disconnect = ehci_hub_disconnect,
-};
-
-// 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;
-}
-
-
-/****************************************************************
- * Setup
- ****************************************************************/
-
-// Wait for next USB async frame to start - for ensuring safe memory release.
-static void
-ehci_waittick(struct usb_ehci_s *cntl)
-{
-    if (MODE16) {
-        msleep(10);
-        return;
-    }
-    // Wait for access to "doorbell"
-    barrier();
-    u32 cmd, sts;
-    u32 end = timer_calc(100);
-    for (;;) {
-        sts = readl(&cntl->regs->usbsts);
-        if (!(sts & STS_IAA)) {
-            cmd = readl(&cntl->regs->usbcmd);
-            if (!(cmd & CMD_IAAD))
-                break;
-        }
-        if (timer_check(end)) {
-            warn_timeout();
-            return;
-        }
-        yield();
-    }
-    // Ring "doorbell"
-    writel(&cntl->regs->usbcmd, cmd | CMD_IAAD);
-    // Wait for completion
-    for (;;) {
-        sts = readl(&cntl->regs->usbsts);
-        if (sts & STS_IAA)
-            break;
-        if (timer_check(end)) {
-            warn_timeout();
-            return;
-        }
-        yield();
-    }
-    // Ack completion
-    writel(&cntl->regs->usbsts, STS_IAA);
-}
-
-static void
-ehci_free_pipes(struct usb_ehci_s *cntl)
-{
-    dprintf(7, "ehci_free_pipes %p\n", cntl);
-
-    struct ehci_qh *start = cntl->async_qh;
-    struct ehci_qh *pos = start;
-    for (;;) {
-        struct ehci_qh *next = (void*)(pos->next & ~EHCI_PTR_BITS);
-        if (next == start)
-            break;
-        struct ehci_pipe *pipe = container_of(next, struct ehci_pipe, qh);
-        if (pipe->pipe.cntl != &cntl->usb)
-            pos->next = next->next;
-        else
-            pos = next;
-    }
-    ehci_waittick(cntl);
-    for (;;) {
-        struct usb_pipe *usbpipe = cntl->usb.freelist;
-        if (!usbpipe)
-            break;
-        cntl->usb.freelist = usbpipe->freenext;
-        struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe);
-        free(pipe);
-    }
-}
-
-static void
-configure_ehci(void *data)
-{
-    struct usb_ehci_s *cntl = data;
-
-    // Allocate ram for schedule storage
-    struct ehci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl));
-    struct ehci_qh *intr_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*intr_qh));
-    struct ehci_qh *async_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*async_qh));
-    if (!fl || !intr_qh || !async_qh) {
-        warn_noalloc();
-        goto fail;
-    }
-
-    // XXX - check for halted?
-
-    // Reset the HC
-    u32 cmd = readl(&cntl->regs->usbcmd);
-    writel(&cntl->regs->usbcmd, (cmd & ~(CMD_ASE | CMD_PSE)) | CMD_HCRESET);
-    u32 end = timer_calc(250);
-    for (;;) {
-        cmd = readl(&cntl->regs->usbcmd);
-        if (!(cmd & CMD_HCRESET))
-            break;
-        if (timer_check(end)) {
-            warn_timeout();
-            goto fail;
-        }
-        yield();
-    }
-
-    // Disable interrupts (just to be safe).
-    writel(&cntl->regs->usbintr, 0);
-
-    // Set schedule to point to primary intr queue head
-    memset(intr_qh, 0, sizeof(*intr_qh));
-    intr_qh->next = EHCI_PTR_TERM;
-    intr_qh->info2 = (0x01 << QH_SMASK_SHIFT);
-    intr_qh->token = QTD_STS_HALT;
-    intr_qh->qtd_next = intr_qh->alt_next = EHCI_PTR_TERM;
-    int i;
-    for (i=0; i<ARRAY_SIZE(fl->links); i++)
-        fl->links[i] = (u32)intr_qh | EHCI_PTR_QH;
-    writel(&cntl->regs->periodiclistbase, (u32)fl);
-
-    // Set async list to point to primary async queue head
-    memset(async_qh, 0, sizeof(*async_qh));
-    async_qh->next = (u32)async_qh | EHCI_PTR_QH;
-    async_qh->info1 = QH_HEAD;
-    async_qh->token = QTD_STS_HALT;
-    async_qh->qtd_next = async_qh->alt_next = EHCI_PTR_TERM;
-    cntl->async_qh = async_qh;
-    writel(&cntl->regs->asynclistbase, (u32)async_qh);
-
-    // Enable queues
-    writel(&cntl->regs->usbcmd, cmd | CMD_ASE | CMD_PSE | CMD_RUN);
-
-    // Set default of high speed for root hub.
-    writel(&cntl->regs->configflag, 1);
-    cntl->checkports = readl(&cntl->caps->hcsparams) & HCS_N_PORTS_MASK;
-
-    // Find devices
-    int count = check_ehci_ports(cntl);
-    ehci_free_pipes(cntl);
-    if (count)
-        // Success
-        return;
-
-    // No devices found - shutdown and free controller.
-    writel(&cntl->regs->usbcmd, cmd & ~CMD_RUN);
-    msleep(4);  // 2ms to stop reading memory - XXX
-fail:
-    free(fl);
-    free(intr_qh);
-    free(async_qh);
-    free(cntl);
-}
-
-int
-ehci_setup(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);
-
-    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);
-    if (hcc_params & HCC_64BIT_ADDR)
-        cntl->regs->ctrldssegment = 0;
-
-    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 = container_of(comppci->node.next, struct pci_device, node);
-    }
-
-    run_thread(configure_ehci, cntl);
-    return 0;
-}
-
-
-/****************************************************************
- * End point communication
- ****************************************************************/
-
-// Setup fields in qh
-static void
-ehci_desc2pipe(struct ehci_pipe *pipe, struct usbdevice_s *usbdev
-               , struct usb_endpoint_descriptor *epdesc)
-{
-    usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
-
-    pipe->qh.info1 = ((pipe->pipe.maxpacket << QH_MAXPACKET_SHIFT)
-                      | (pipe->pipe.speed << QH_SPEED_SHIFT)
-                      | (pipe->pipe.ep << QH_EP_SHIFT)
-                      | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT));
-
-    pipe->qh.info2 = (1 << QH_MULT_SHIFT);
-    struct usbdevice_s *hubdev = usbdev->hub->usbdev;
-    if (hubdev) {
-        struct ehci_pipe *hpipe = container_of(
-            hubdev->defpipe, struct ehci_pipe, pipe);
-        if (hpipe->pipe.speed == USB_HIGHSPEED)
-            pipe->qh.info2 |= ((usbdev->port << QH_HUBPORT_SHIFT)
-                               | (hpipe->pipe.devaddr << QH_HUBADDR_SHIFT));
-        else
-            pipe->qh.info2 = hpipe->qh.info2;
-    }
-
-    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-    if (eptype == USB_ENDPOINT_XFER_CONTROL)
-        pipe->qh.info1 |= ((pipe->pipe.speed != USB_HIGHSPEED ? QH_CONTROL : 0)
-                           | QH_TOGGLECONTROL);
-    else if (eptype == USB_ENDPOINT_XFER_INT)
-        pipe->qh.info2 |= (0x01 << QH_SMASK_SHIFT) | (0x1c << QH_CMASK_SHIFT);
-}
-
-static struct usb_pipe *
-ehci_alloc_intr_pipe(struct usbdevice_s *usbdev
-                     , struct usb_endpoint_descriptor *epdesc)
-{
-    struct usb_ehci_s *cntl = container_of(
-        usbdev->hub->cntl, struct usb_ehci_s, usb);
-    int frameexp = usb_getFrameExp(usbdev, epdesc);
-    dprintf(7, "ehci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
-
-    if (frameexp > 10)
-        frameexp = 10;
-    int maxpacket = epdesc->wMaxPacketSize;
-    // Determine number of entries needed for 2 timer ticks.
-    int ms = 1<<frameexp;
-    int count = DIV_ROUND_UP(ticks_to_ms(2), ms);
-    struct ehci_pipe *pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe));
-    struct ehci_qtd *tds = memalign_low(EHCI_QTD_ALIGN, sizeof(*tds) * count);
-    void *data = malloc_low(maxpacket * count);
-    if (!pipe || !tds || !data) {
-        warn_noalloc();
-        goto fail;
-    }
-    memset(pipe, 0, sizeof(*pipe));
-    ehci_desc2pipe(pipe, usbdev, epdesc);
-    pipe->next_td = pipe->tds = tds;
-    pipe->data = data;
-    pipe->qh.qtd_next = (u32)tds;
-
-    int i;
-    for (i=0; i<count; i++) {
-        struct ehci_qtd *td = &tds[i];
-        td->qtd_next = (i==count-1 ? (u32)tds : (u32)&td[1]);
-        td->alt_next = EHCI_PTR_TERM;
-        td->token = (ehci_explen(maxpacket) | QTD_STS_ACTIVE
-                     | QTD_PID_IN | ehci_maxerr(3));
-        td->buf[0] = (u32)data + maxpacket * i;
-    }
-
-    // Add to interrupt schedule.
-    struct ehci_framelist *fl = (void*)readl(&cntl->regs->periodiclistbase);
-    if (frameexp == 0) {
-        // Add to existing interrupt entry.
-        struct ehci_qh *intr_qh = (void*)(fl->links[0] & ~EHCI_PTR_BITS);
-        pipe->qh.next = intr_qh->next;
-        barrier();
-        intr_qh->next = (u32)&pipe->qh | EHCI_PTR_QH;
-    } else {
-        int startpos = 1<<(frameexp-1);
-        pipe->qh.next = fl->links[startpos];
-        barrier();
-        for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms)
-            fl->links[i] = (u32)&pipe->qh | EHCI_PTR_QH;
-    }
-
-    return &pipe->pipe;
-fail:
-    free(pipe);
-    free(tds);
-    free(data);
-    return NULL;
-}
-
-struct usb_pipe *
-ehci_alloc_pipe(struct usbdevice_s *usbdev
-                , struct usb_endpoint_descriptor *epdesc)
-{
-    if (! CONFIG_USB_EHCI)
-        return NULL;
-    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-    if (eptype == USB_ENDPOINT_XFER_INT)
-        return ehci_alloc_intr_pipe(usbdev, epdesc);
-    struct usb_ehci_s *cntl = container_of(
-        usbdev->hub->cntl, struct usb_ehci_s, usb);
-    dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);
-
-    struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
-    if (usbpipe) {
-        // Use previously allocated pipe.
-        struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe);
-        ehci_desc2pipe(pipe, usbdev, epdesc);
-        return usbpipe;
-    }
-
-    // Allocate a new queue head.
-    struct ehci_pipe *pipe;
-    if (eptype == USB_ENDPOINT_XFER_CONTROL)
-        pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe));
-    else
-        pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe));
-    if (!pipe) {
-        warn_noalloc();
-        return NULL;
-    }
-    memset(pipe, 0, sizeof(*pipe));
-    ehci_desc2pipe(pipe, usbdev, epdesc);
-    pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;
-
-    // Add queue head to controller list.
-    struct ehci_qh *async_qh = cntl->async_qh;
-    pipe->qh.next = async_qh->next;
-    barrier();
-    async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH;
-    return &pipe->pipe;
-}
-
-static void
-ehci_reset_pipe(struct ehci_pipe *pipe)
-{
-    SET_LOWFLAT(pipe->qh.qtd_next, EHCI_PTR_TERM);
-    SET_LOWFLAT(pipe->qh.alt_next, EHCI_PTR_TERM);
-    barrier();
-    SET_LOWFLAT(pipe->qh.token, GET_LOWFLAT(pipe->qh.token) & QTD_TOGGLE);
-}
-
-static int
-ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout)
-{
-    u32 end = timer_calc(timeout);
-    u32 status;
-    for (;;) {
-        status = td->token;
-        if (!(status & QTD_STS_ACTIVE))
-            break;
-        if (timer_check(end)) {
-            u32 cur = GET_LOWFLAT(pipe->qh.current);
-            u32 tok = GET_LOWFLAT(pipe->qh.token);
-            u32 next = GET_LOWFLAT(pipe->qh.qtd_next);
-            warn_timeout();
-            dprintf(1, "ehci pipe=%p cur=%08x tok=%08x next=%x td=%p status=%x\n"
-                    , pipe, cur, tok, next, td, status);
-            ehci_reset_pipe(pipe);
-            struct usb_ehci_s *cntl = container_of(
-                GET_LOWFLAT(pipe->pipe.cntl), struct usb_ehci_s, usb);
-            ehci_waittick(cntl);
-            return -1;
-        }
-        yield();
-    }
-    if (status & QTD_STS_HALT) {
-        dprintf(1, "ehci_wait_td error - status=%x\n", status);
-        ehci_reset_pipe(pipe);
-        return -2;
-    }
-    return 0;
-}
-
-static int
-fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes)
-{
-    u32 dest = (u32)buf;
-    u32 *pos = td->buf;
-    while (bytes) {
-        if (pos >= &td->buf[ARRAY_SIZE(td->buf)])
-            // More data than can transfer in a single qtd - only use
-            // full packets to prevent a babble error.
-            return ALIGN_DOWN(dest - (u32)buf, maxpacket);
-        u32 count = bytes;
-        u32 max = 0x1000 - (dest & 0xfff);
-        if (count > max)
-            count = max;
-        *pos = dest;
-        bytes -= count;
-        dest += count;
-        pos++;
-    }
-    return dest - (u32)buf;
-}
-
-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;
-}
-
-#define STACKQTDS 4
-
-int
-ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
-{
-    if (! CONFIG_USB_EHCI)
-        return -1;
-    struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);
-    dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n"
-            , &pipe->qh, dir, data, datasize);
-
-    // Allocate 4 tds on stack (with required alignment)
-    u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1];
-    struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN);
-    memset(tds, 0, sizeof(*tds) * STACKQTDS);
-    barrier();
-    SET_LOWFLAT(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
-
-    u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
-    int tdpos = 0;
-    while (datasize) {
-        struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS];
-        int ret = ehci_wait_td(pipe, td, 5000);
-        if (ret)
-            return -1;
-
-        struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
-                                                 , &tds[tdpos % STACKQTDS]);
-
-        int transfer = fillTDbuffer(td, maxpacket, data, datasize);
-        td->qtd_next = (transfer==datasize ? EHCI_PTR_TERM : (u32)nexttd_fl);
-        td->alt_next = EHCI_PTR_TERM;
-        barrier();
-        td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE
-                     | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3));
-
-        data += transfer;
-        datasize -= transfer;
-    }
-    int i;
-    for (i=0; i<STACKQTDS; i++) {
-        struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS];
-        int ret = ehci_wait_td(pipe, td, 5000);
-        if (ret)
-            return -1;
-    }
-
-    return 0;
-}
-
-int
-ehci_poll_intr(struct usb_pipe *p, void *data)
-{
-    ASSERT16();
-    if (! CONFIG_USB_EHCI)
-        return -1;
-    struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);
-    struct ehci_qtd *td = GET_LOWFLAT(pipe->next_td);
-    u32 token = GET_LOWFLAT(td->token);
-    if (token & QTD_STS_ACTIVE)
-        // No intrs found.
-        return -1;
-    // XXX - check for errors.
-
-    // Copy data.
-    int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
-    int pos = td - GET_LOWFLAT(pipe->tds);
-    void *tddata = GET_LOWFLAT(pipe->data) + maxpacket * pos;
-    memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata), maxpacket);
-
-    // Reenable this td.
-    struct ehci_qtd *next = (void*)(GET_LOWFLAT(td->qtd_next) & ~EHCI_PTR_BITS);
-    SET_LOWFLAT(pipe->next_td, next);
-    SET_LOWFLAT(td->buf[0], (u32)tddata);
-    barrier();
-    SET_LOWFLAT(td->token, (ehci_explen(maxpacket) | QTD_STS_ACTIVE
-                            | QTD_PID_IN | ehci_maxerr(3)));
-
-    return 0;
-}
diff --git a/src/usb-ehci.h b/src/usb-ehci.h
deleted file mode 100644 (file)
index 5672033..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-#ifndef __USB_EHCI_H
-#define __USB_EHCI_H
-
-// usb-ehci.c
-int ehci_setup(struct pci_device *pci, int busid, struct pci_device *comppci);
-struct usbdevice_s;
-struct usb_endpoint_descriptor;
-struct usb_pipe *ehci_alloc_pipe(struct usbdevice_s *usbdev
-                                 , struct usb_endpoint_descriptor *epdesc);
-struct usb_pipe;
-int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
-                 , void *data, int datasize);
-int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
-int ehci_poll_intr(struct usb_pipe *p, void *data);
-
-
-/****************************************************************
- * ehci structs and flags
- ****************************************************************/
-
-struct ehci_caps {
-    u8 caplength;
-    u8 reserved_01;
-    u16 hciversion;
-    u32 hcsparams;
-    u32 hccparams;
-    u64 portroute;
-} PACKED;
-
-#define HCC_64BIT_ADDR 1
-
-#define HCS_N_PORTS_MASK 0xf
-
-struct ehci_regs {
-    u32 usbcmd;
-    u32 usbsts;
-    u32 usbintr;
-    u32 frindex;
-    u32 ctrldssegment;
-    u32 periodiclistbase;
-    u32 asynclistbase;
-    u32 reserved[9];
-    u32 configflag;
-    u32 portsc[0];
-} PACKED;
-
-#define CMD_PARK        (1<<11)
-#define CMD_PARK_CNT(c) (((c)>>8)&3)
-#define CMD_LRESET      (1<<7)
-#define CMD_IAAD        (1<<6)
-#define CMD_ASE         (1<<5)
-#define CMD_PSE         (1<<4)
-#define CMD_HCRESET     (1<<1)
-#define CMD_RUN         (1<<0)
-
-#define STS_ASS         (1<<15)
-#define STS_PSS         (1<<14)
-#define STS_RECL        (1<<13)
-#define STS_HALT        (1<<12)
-#define STS_IAA         (1<<5)
-#define STS_FATAL       (1<<4)
-#define STS_FLR         (1<<3)
-#define STS_PCD         (1<<2)
-#define STS_ERR         (1<<1)
-#define STS_INT         (1<<0)
-
-#define FLAG_CF         (1<<0)
-
-#define PORT_WKOC_E     (1<<22)
-#define PORT_WKDISC_E   (1<<21)
-#define PORT_WKCONN_E   (1<<20)
-#define PORT_TEST_PKT   (0x4<<16)
-#define PORT_LED_OFF    (0<<14)
-#define PORT_LED_AMBER  (1<<14)
-#define PORT_LED_GREEN  (2<<14)
-#define PORT_LED_MASK   (3<<14)
-#define PORT_OWNER      (1<<13)
-#define PORT_POWER      (1<<12)
-#define PORT_LINESTATUS_MASK   (3<<10)
-#define PORT_LINESTATUS_KSTATE (1<<10)
-#define PORT_RESET      (1<<8)
-#define PORT_SUSPEND    (1<<7)
-#define PORT_RESUME     (1<<6)
-#define PORT_OCC        (1<<5)
-#define PORT_OC         (1<<4)
-#define PORT_PEC        (1<<3)
-#define PORT_PE         (1<<2)
-#define PORT_CSC        (1<<1)
-#define PORT_CONNECT    (1<<0)
-#define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
-
-
-#define EHCI_QH_ALIGN 128 // Can't span a 4K boundary, so increase from 32
-
-struct ehci_qh {
-    u32 next;
-    u32 info1;
-    u32 info2;
-    u32 current;
-
-    u32 qtd_next;
-    u32 alt_next;
-    u32 token;
-    u32 buf[5];
-    u32 buf_hi[5];
-} PACKED;
-
-#define QH_CONTROL       (1 << 27)
-#define QH_MAXPACKET_SHIFT 16
-#define QH_MAXPACKET_MASK  (0x7ff << QH_MAXPACKET_SHIFT)
-#define QH_HEAD          (1 << 15)
-#define QH_TOGGLECONTROL (1 << 14)
-#define QH_SPEED_SHIFT   12
-#define QH_SPEED_MASK    (0x3 << QH_SPEED_SHIFT)
-#define QH_EP_SHIFT      8
-#define QH_EP_MASK       (0xf << QH_EP_SHIFT)
-#define QH_DEVADDR_SHIFT 0
-#define QH_DEVADDR_MASK  (0x7f << QH_DEVADDR_SHIFT)
-
-#define QH_SMASK_SHIFT   0
-#define QH_SMASK_MASK    (0xff << QH_SMASK_SHIFT)
-#define QH_CMASK_SHIFT   8
-#define QH_CMASK_MASK    (0xff << QH_CMASK_SHIFT)
-#define QH_HUBADDR_SHIFT 16
-#define QH_HUBADDR_MASK  (0x7f << QH_HUBADDR_SHIFT)
-#define QH_HUBPORT_SHIFT 23
-#define QH_HUBPORT_MASK  (0x7f << QH_HUBPORT_SHIFT)
-#define QH_MULT_SHIFT    30
-#define QH_MULT_MASK     (0x3 << QH_MULT_SHIFT)
-
-#define EHCI_PTR_BITS           0x001F
-#define EHCI_PTR_TERM           0x0001
-#define EHCI_PTR_QH             0x0002
-
-
-#define EHCI_QTD_ALIGN 64 // Can't span a 4K boundary, so increase from 32
-
-struct ehci_qtd {
-    u32 qtd_next;
-    u32 alt_next;
-    u32 token;
-    u32 buf[5];
-    u32 buf_hi[5];
-    /* keep struct size a multiple of 64 bytes, as we're allocating
-       arrays. Without this padding, the second qtd could have the
-       wrong alignment. */
-} PACKED __aligned(EHCI_QTD_ALIGN);
-
-#define QTD_TOGGLE      (1 << 31)
-#define QTD_LENGTH_SHIFT 16
-#define QTD_LENGTH_MASK (0x7fff << QTD_LENGTH_SHIFT)
-#define QTD_CERR_SHIFT  10
-#define QTD_CERR_MASK   (0x3 << QTD_CERR_SHIFT)
-#define QTD_IOC         (1 << 15)
-#define QTD_PID_OUT     (0x0 << 8)
-#define QTD_PID_IN      (0x1 << 8)
-#define QTD_PID_SETUP   (0x2 << 8)
-#define QTD_STS_ACTIVE  (1 << 7)
-#define QTD_STS_HALT    (1 << 6)
-#define QTD_STS_DBE     (1 << 5)
-#define QTD_STS_BABBLE  (1 << 4)
-#define QTD_STS_XACT    (1 << 3)
-#define QTD_STS_MMF     (1 << 2)
-#define QTD_STS_STS     (1 << 1)
-#define QTD_STS_PING    (1 << 0)
-
-#define ehci_explen(len) (((len) << QTD_LENGTH_SHIFT) & QTD_LENGTH_MASK)
-
-#define ehci_maxerr(err) (((err) << QTD_CERR_SHIFT) & QTD_CERR_MASK)
-
-
-struct ehci_framelist {
-    u32 links[1024];
-} PACKED;
-
-#endif // usb-ehci.h
diff --git a/src/usb-hid.c b/src/usb-hid.c
deleted file mode 100644 (file)
index deb3ea5..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-// Code for handling USB Human Interface Devices (HID).
-//
-// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "usb-hid.h" // usb_keyboard_setup
-#include "config.h" // CONFIG_*
-#include "usb.h" // usb_ctrlrequest
-#include "biosvar.h" // GET_GLOBAL
-#include "ps2port.h" // ATKBD_CMD_GETID
-
-struct usb_pipe *keyboard_pipe VARFSEG;
-struct usb_pipe *mouse_pipe VARFSEG;
-
-
-/****************************************************************
- * Setup
- ****************************************************************/
-
-// Send USB HID protocol message.
-static int
-set_protocol(struct usb_pipe *pipe, u16 val)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-    req.bRequest = HID_REQ_SET_PROTOCOL;
-    req.wValue = val;
-    req.wIndex = 0;
-    req.wLength = 0;
-    return send_default_control(pipe, &req, NULL);
-}
-
-// Send USB HID SetIdle request.
-static int
-set_idle(struct usb_pipe *pipe, int ms)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-    req.bRequest = HID_REQ_SET_IDLE;
-    req.wValue = (ms/4)<<8;
-    req.wIndex = 0;
-    req.wLength = 0;
-    return send_default_control(pipe, &req, NULL);
-}
-
-#define KEYREPEATWAITMS 500
-#define KEYREPEATMS 33
-
-static int
-usb_kbd_setup(struct usbdevice_s *usbdev
-              , struct usb_endpoint_descriptor *epdesc)
-{
-    if (! CONFIG_USB_KEYBOARD)
-        return -1;
-    if (keyboard_pipe)
-        // XXX - this enables the first found keyboard (could be random)
-        return -1;
-
-    if (epdesc->wMaxPacketSize != 8)
-        return -1;
-
-    // Enable "boot" protocol.
-    int ret = set_protocol(usbdev->defpipe, 0);
-    if (ret)
-        return -1;
-    // Periodically send reports to enable key repeat.
-    ret = set_idle(usbdev->defpipe, KEYREPEATMS);
-    if (ret)
-        return -1;
-
-    keyboard_pipe = usb_alloc_pipe(usbdev, epdesc);
-    if (!keyboard_pipe)
-        return -1;
-
-    dprintf(1, "USB keyboard initialized\n");
-    return 0;
-}
-
-static int
-usb_mouse_setup(struct usbdevice_s *usbdev
-                , struct usb_endpoint_descriptor *epdesc)
-{
-    if (! CONFIG_USB_MOUSE)
-        return -1;
-    if (mouse_pipe)
-        // XXX - this enables the first found mouse (could be random)
-        return -1;
-
-    if (epdesc->wMaxPacketSize < 3 || epdesc->wMaxPacketSize > 8)
-        return -1;
-
-    // Enable "boot" protocol.
-    int ret = set_protocol(usbdev->defpipe, 0);
-    if (ret)
-        return -1;
-
-    mouse_pipe = usb_alloc_pipe(usbdev, epdesc);
-    if (!mouse_pipe)
-        return -1;
-
-    dprintf(1, "USB mouse initialized\n");
-    return 0;
-}
-
-// Initialize a found USB HID device (if applicable).
-int
-usb_hid_setup(struct usbdevice_s *usbdev)
-{
-    if (! CONFIG_USB_KEYBOARD || ! CONFIG_USB_MOUSE)
-        return -1;
-    dprintf(2, "usb_hid_setup %p\n", usbdev->defpipe);
-
-    struct usb_interface_descriptor *iface = usbdev->iface;
-    if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT)
-        // Doesn't support boot protocol.
-        return -1;
-
-    // Find intr in endpoint.
-    struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
-        usbdev, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
-    if (!epdesc) {
-        dprintf(1, "No usb hid intr in?\n");
-        return -1;
-    }
-
-    if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD)
-        return usb_kbd_setup(usbdev, epdesc);
-    if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
-        return usb_mouse_setup(usbdev, epdesc);
-    return -1;
-}
-
-
-/****************************************************************
- * Keyboard events
- ****************************************************************/
-
-// Mapping from USB key id to ps2 key sequence.
-static u16 KeyToScanCode[] VAR16 = {
-    0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
-    0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
-    0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
-    0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
-    0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
-    0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
-    0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
-    0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
-    0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
-    0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
-    0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
-    0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
-    0x0048, 0x0049, 0x0052, 0x0053
-};
-
-// Mapping from USB modifier id to ps2 key sequence.
-static u16 ModifierToScanCode[] VAR16 = {
-    //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
-    0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
-};
-
-#define RELEASEBIT 0x80
-
-// Format of USB keyboard event data
-struct keyevent {
-    u8 modifiers;
-    u8 reserved;
-    u8 keys[6];
-};
-
-// Translate data from KeyToScanCode[] to calls to process_key().
-static void
-prockeys(u16 keys)
-{
-    if (keys > 0xff) {
-        u8 key = keys>>8;
-        if (key == 0xe1) {
-            // Pause key
-            process_key(0xe1);
-            process_key(0x1d | (keys & RELEASEBIT));
-            process_key(0x45 | (keys & RELEASEBIT));
-            return;
-        }
-        process_key(key);
-    }
-    process_key(keys);
-}
-
-// Handle a USB key press/release event.
-static void
-procscankey(u8 key, u8 flags)
-{
-    if (key >= ARRAY_SIZE(KeyToScanCode))
-        return;
-    u16 keys = GET_GLOBAL(KeyToScanCode[key]);
-    if (keys)
-        prockeys(keys | flags);
-}
-
-// Handle a USB modifier press/release event.
-static void
-procmodkey(u8 mods, u8 flags)
-{
-    int i;
-    for (i=0; mods; i++)
-        if (mods & (1<<i)) {
-            // Modifier key change.
-            prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
-            mods &= ~(1<<i);
-        }
-}
-
-struct usbkeyinfo {
-    union {
-        struct {
-            u8 modifiers;
-            u8 repeatcount;
-            u8 keys[6];
-        };
-        u64 data;
-    };
-};
-struct usbkeyinfo LastUSBkey VARLOW;
-
-// Process USB keyboard data.
-static void
-handle_key(struct keyevent *data)
-{
-    dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
-
-    // Load old keys.
-    struct usbkeyinfo old;
-    old.data = GET_LOW(LastUSBkey.data);
-
-    // Check for keys no longer pressed.
-    int addpos = 0;
-    int i;
-    for (i=0; i<ARRAY_SIZE(old.keys); i++) {
-        u8 key = old.keys[i];
-        if (!key)
-            break;
-        int j;
-        for (j=0;; j++) {
-            if (j>=ARRAY_SIZE(data->keys)) {
-                // Key released.
-                procscankey(key, RELEASEBIT);
-                if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
-                    // Last pressed key released - disable repeat.
-                    old.repeatcount = 0xff;
-                break;
-            }
-            if (data->keys[j] == key) {
-                // Key still pressed.
-                data->keys[j] = 0;
-                old.keys[addpos++] = key;
-                break;
-            }
-        }
-    }
-    procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
-
-    // Process new keys
-    procmodkey(data->modifiers & ~old.modifiers, 0);
-    old.modifiers = data->modifiers;
-    for (i=0; i<ARRAY_SIZE(data->keys); i++) {
-        u8 key = data->keys[i];
-        if (!key)
-            continue;
-        // New key pressed.
-        procscankey(key, 0);
-        old.keys[addpos++] = key;
-        old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
-    }
-    if (addpos < ARRAY_SIZE(old.keys))
-        old.keys[addpos] = 0;
-
-    // Check for key repeat event.
-    if (addpos) {
-        if (!old.repeatcount)
-            procscankey(old.keys[addpos-1], 0);
-        else if (old.repeatcount != 0xff)
-            old.repeatcount--;
-    }
-
-    // Update old keys
-    SET_LOW(LastUSBkey.data, old.data);
-}
-
-// Check if a USB keyboard event is pending and process it if so.
-static void
-usb_check_key(void)
-{
-    if (! CONFIG_USB_KEYBOARD)
-        return;
-    struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
-    if (!pipe)
-        return;
-
-    for (;;) {
-        struct keyevent data;
-        int ret = usb_poll_intr(pipe, &data);
-        if (ret)
-            break;
-        handle_key(&data);
-    }
-}
-
-// Test if USB keyboard is active.
-inline int
-usb_kbd_active(void)
-{
-    if (! CONFIG_USB_KEYBOARD)
-        return 0;
-    return GET_GLOBAL(keyboard_pipe) != NULL;
-}
-
-// Handle a ps2 style keyboard command.
-inline int
-usb_kbd_command(int command, u8 *param)
-{
-    if (! CONFIG_USB_KEYBOARD)
-        return -1;
-    dprintf(9, "usb keyboard cmd=%x\n", command);
-    switch (command) {
-    case ATKBD_CMD_GETID:
-        // Return the id of a standard AT keyboard.
-        param[0] = 0xab;
-        param[1] = 0x83;
-        return 0;
-    default:
-        return -1;
-    }
-}
-
-
-/****************************************************************
- * Mouse events
- ****************************************************************/
-
-// Format of USB mouse event data
-struct mouseevent {
-    u8 buttons;
-    u8 x, y;
-    u8 reserved[5];
-};
-
-// Process USB mouse data.
-static void
-handle_mouse(struct mouseevent *data)
-{
-    dprintf(9, "Got mouse b=%x x=%x y=%x\n", data->buttons, data->x, data->y);
-
-    s8 x = data->x, y = -data->y;
-    u8 flag = ((data->buttons & 0x7) | (1<<3)
-               | (x & 0x80 ? (1<<4) : 0) | (y & 0x80 ? (1<<5) : 0));
-    process_mouse(flag);
-    process_mouse(x);
-    process_mouse(y);
-}
-
-// Check if a USB mouse event is pending and process it if so.
-static void
-usb_check_mouse(void)
-{
-    if (! CONFIG_USB_MOUSE)
-        return;
-    struct usb_pipe *pipe = GET_GLOBAL(mouse_pipe);
-    if (!pipe)
-        return;
-
-    for (;;) {
-        struct mouseevent data;
-        int ret = usb_poll_intr(pipe, &data);
-        if (ret)
-            break;
-        handle_mouse(&data);
-    }
-}
-
-// Test if USB mouse is active.
-inline int
-usb_mouse_active(void)
-{
-    if (! CONFIG_USB_MOUSE)
-        return 0;
-    return GET_GLOBAL(mouse_pipe) != NULL;
-}
-
-// Handle a ps2 style mouse command.
-inline int
-usb_mouse_command(int command, u8 *param)
-{
-    if (! CONFIG_USB_MOUSE)
-        return -1;
-    dprintf(9, "usb mouse cmd=%x\n", command);
-    switch (command) {
-    case PSMOUSE_CMD_ENABLE:
-    case PSMOUSE_CMD_DISABLE:
-    case PSMOUSE_CMD_SETSCALE11:
-        return 0;
-    case PSMOUSE_CMD_SETSCALE21:
-    case PSMOUSE_CMD_SETRATE:
-    case PSMOUSE_CMD_SETRES:
-        // XXX
-        return 0;
-    case PSMOUSE_CMD_RESET_BAT:
-    case PSMOUSE_CMD_GETID:
-        // Return the id of a standard AT mouse.
-        param[0] = 0xaa;
-        param[1] = 0x00;
-        return 0;
-
-    case PSMOUSE_CMD_GETINFO:
-        param[0] = 0x00;
-        param[1] = 4;
-        param[2] = 100;
-        return 0;
-
-    default:
-        return -1;
-    }
-}
-
-// Check for USB events pending - called periodically from timer interrupt.
-void
-usb_check_event(void)
-{
-    usb_check_key();
-    usb_check_mouse();
-}
diff --git a/src/usb-hid.h b/src/usb-hid.h
deleted file mode 100644 (file)
index ef34e79..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __USB_HID_H
-#define __USB_HID_H
-
-// usb-hid.c
-struct usbdevice_s;
-int usb_hid_setup(struct usbdevice_s *usbdev);
-inline int usb_kbd_active(void);
-inline int usb_kbd_command(int command, u8 *param);
-inline int usb_mouse_active(void);
-inline int usb_mouse_command(int command, u8 *param);
-void usb_check_event(void);
-
-
-/****************************************************************
- * hid flags
- ****************************************************************/
-
-#define USB_INTERFACE_SUBCLASS_BOOT     1
-#define USB_INTERFACE_PROTOCOL_KEYBOARD 1
-#define USB_INTERFACE_PROTOCOL_MOUSE    2
-
-#define HID_REQ_GET_REPORT              0x01
-#define HID_REQ_GET_IDLE                0x02
-#define HID_REQ_GET_PROTOCOL            0x03
-#define HID_REQ_SET_REPORT              0x09
-#define HID_REQ_SET_IDLE                0x0A
-#define HID_REQ_SET_PROTOCOL            0x0B
-
-#endif // ush-hid.h
diff --git a/src/usb-hub.c b/src/usb-hub.c
deleted file mode 100644 (file)
index 0b55d15..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-// Code for handling standard USB hubs.
-//
-// Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_USB_HUB
-#include "usb-hub.h" // struct usb_hub_descriptor
-#include "usb.h" // struct usb_s
-
-static int
-get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE;
-    req.bRequest = USB_REQ_GET_DESCRIPTOR;
-    req.wValue = USB_DT_HUB<<8;
-    req.wIndex = 0;
-    req.wLength = sizeof(*desc);
-    return send_default_control(pipe, &req, desc);
-}
-
-static int
-set_port_feature(struct usbhub_s *hub, int port, int feature)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
-    req.bRequest = USB_REQ_SET_FEATURE;
-    req.wValue = feature;
-    req.wIndex = port + 1;
-    req.wLength = 0;
-    mutex_lock(&hub->lock);
-    int ret = send_default_control(hub->usbdev->defpipe, &req, NULL);
-    mutex_unlock(&hub->lock);
-    return ret;
-}
-
-static int
-clear_port_feature(struct usbhub_s *hub, int port, int feature)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
-    req.bRequest = USB_REQ_CLEAR_FEATURE;
-    req.wValue = feature;
-    req.wIndex = port + 1;
-    req.wLength = 0;
-    mutex_lock(&hub->lock);
-    int ret = send_default_control(hub->usbdev->defpipe, &req, NULL);
-    mutex_unlock(&hub->lock);
-    return ret;
-}
-
-static int
-get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER;
-    req.bRequest = USB_REQ_GET_STATUS;
-    req.wValue = 0;
-    req.wIndex = port + 1;
-    req.wLength = sizeof(*sts);
-    mutex_lock(&hub->lock);
-    int ret = send_default_control(hub->usbdev->defpipe, &req, sts);
-    mutex_unlock(&hub->lock);
-    return ret;
-}
-
-// Check if device attached to port
-static int
-usb_hub_detect(struct usbhub_s *hub, u32 port)
-{
-    // Turn on power to port.
-    int ret = set_port_feature(hub, port, USB_PORT_FEAT_POWER);
-    if (ret)
-        goto fail;
-
-    // Wait for port power to stabilize.
-    msleep(hub->powerwait);
-
-    // Check periodically for a device connect.
-    struct usb_port_status sts;
-    u32 end = timer_calc(USB_TIME_SIGATT);
-    for (;;) {
-        ret = get_port_status(hub, port, &sts);
-        if (ret)
-            goto fail;
-        if (sts.wPortStatus & USB_PORT_STAT_CONNECTION)
-            // Device connected.
-            break;
-        if (timer_check(end))
-            // No device found.
-            return -1;
-        msleep(5);
-    }
-
-    // XXX - wait USB_TIME_ATTDB time?
-
-    return 0;
-
-fail:
-    dprintf(1, "Failure on hub port %d detect\n", port);
-    return -1;
-}
-
-// Disable port
-static void
-usb_hub_disconnect(struct usbhub_s *hub, u32 port)
-{
-    int ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
-    if (ret)
-        dprintf(1, "Failure on hub port %d disconnect\n", port);
-}
-
-// Reset device on port
-static int
-usb_hub_reset(struct usbhub_s *hub, u32 port)
-{
-    int ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET);
-    if (ret)
-        goto fail;
-
-    // Wait for reset to complete.
-    struct usb_port_status sts;
-    u32 end = timer_calc(USB_TIME_DRST * 2);
-    for (;;) {
-        ret = get_port_status(hub, port, &sts);
-        if (ret)
-            goto fail;
-        if (!(sts.wPortStatus & USB_PORT_STAT_RESET))
-            break;
-        if (timer_check(end)) {
-            warn_timeout();
-            goto fail;
-        }
-        msleep(5);
-    }
-
-    // Reset complete.
-    if (!(sts.wPortStatus & USB_PORT_STAT_CONNECTION))
-        // Device no longer present
-        return -1;
-
-    return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK)
-            >> USB_PORT_STAT_SPEED_SHIFT);
-
-fail:
-    dprintf(1, "Failure on hub port %d reset\n", port);
-    usb_hub_disconnect(hub, port);
-    return -1;
-}
-
-static struct usbhub_op_s HubOp = {
-    .detect = usb_hub_detect,
-    .reset = usb_hub_reset,
-    .disconnect = usb_hub_disconnect,
-};
-
-// 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;
-}
diff --git a/src/usb-hub.h b/src/usb-hub.h
deleted file mode 100644 (file)
index 5b09947..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef __USB_HUB_H
-#define __USB_HUB_H
-
-// usb-hub.c
-struct usbdevice_s;
-int usb_hub_setup(struct usbdevice_s *usbdev);
-
-
-/****************************************************************
- * hub flags
- ****************************************************************/
-
-#define USB_DT_HUB                      (USB_TYPE_CLASS | 0x09)
-
-struct usb_hub_descriptor {
-    u8  bDescLength;
-    u8  bDescriptorType;
-    u8  bNbrPorts;
-    u16 wHubCharacteristics;
-    u8  bPwrOn2PwrGood;
-    u8  bHubContrCurrent;
-    // Variable length fields for DeviceRemovable[], PortPwrCtrlMask[] follow.
-} PACKED;
-
-#define USB_PORT_FEAT_CONNECTION        0
-#define USB_PORT_FEAT_ENABLE            1
-#define USB_PORT_FEAT_SUSPEND           2
-#define USB_PORT_FEAT_OVER_CURRENT      3
-#define USB_PORT_FEAT_RESET             4
-#define USB_PORT_FEAT_POWER             8
-#define USB_PORT_FEAT_LOWSPEED          9
-#define USB_PORT_FEAT_C_CONNECTION      16
-#define USB_PORT_FEAT_C_ENABLE          17
-#define USB_PORT_FEAT_C_SUSPEND         18
-#define USB_PORT_FEAT_C_OVER_CURRENT    19
-#define USB_PORT_FEAT_C_RESET           20
-#define USB_PORT_FEAT_TEST              21
-#define USB_PORT_FEAT_INDICATOR         22
-#define USB_PORT_FEAT_C_PORT_L1         23
-
-struct usb_port_status {
-    u16 wPortStatus;
-    u16 wPortChange;
-} PACKED;
-
-#define USB_PORT_STAT_CONNECTION        0x0001
-#define USB_PORT_STAT_ENABLE            0x0002
-#define USB_PORT_STAT_SUSPEND           0x0004
-#define USB_PORT_STAT_OVERCURRENT       0x0008
-#define USB_PORT_STAT_RESET             0x0010
-#define USB_PORT_STAT_L1                0x0020
-#define USB_PORT_STAT_POWER             0x0100
-#define USB_PORT_STAT_SPEED_SHIFT       9
-#define USB_PORT_STAT_SPEED_MASK        (0x3 << USB_PORT_STAT_SPEED_SHIFT)
-#define USB_PORT_STAT_LOW_SPEED         0x0200
-#define USB_PORT_STAT_HIGH_SPEED        0x0400
-#define USB_PORT_STAT_TEST              0x0800
-#define USB_PORT_STAT_INDICATOR         0x1000
-
-#endif // ush-hid.h
diff --git a/src/usb-msc.c b/src/usb-msc.c
deleted file mode 100644 (file)
index 7b2524d..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-// Code for handling USB Mass Storage Controller devices.
-//
-// Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_USB_MSC
-#include "usb-msc.h" // usb_msc_setup
-#include "usb.h" // struct usb_s
-#include "biosvar.h" // GET_GLOBAL
-#include "blockcmd.h" // cdb_read
-#include "disk.h" // DTYPE_USB
-#include "boot.h" // bootprio_find_usb
-
-struct usbdrive_s {
-    struct drive_s drive;
-    struct usb_pipe *bulkin, *bulkout;
-    int lun;
-};
-
-
-/****************************************************************
- * Bulk-only drive command processing
- ****************************************************************/
-
-#define USB_CDB_SIZE 12
-
-#define CBW_SIGNATURE 0x43425355 // USBC
-
-struct cbw_s {
-    u32 dCBWSignature;
-    u32 dCBWTag;
-    u32 dCBWDataTransferLength;
-    u8 bmCBWFlags;
-    u8 bCBWLUN;
-    u8 bCBWCBLength;
-    u8 CBWCB[16];
-} PACKED;
-
-#define CSW_SIGNATURE 0x53425355 // USBS
-
-struct csw_s {
-    u32 dCSWSignature;
-    u32 dCSWTag;
-    u32 dCSWDataResidue;
-    u8 bCSWStatus;
-} PACKED;
-
-static int
-usb_msc_send(struct usbdrive_s *udrive_g, int dir, void *buf, u32 bytes)
-{
-    struct usb_pipe *pipe;
-    if (dir == USB_DIR_OUT)
-        pipe = GET_GLOBAL(udrive_g->bulkout);
-    else
-        pipe = GET_GLOBAL(udrive_g->bulkin);
-    return usb_send_bulk(pipe, dir, buf, bytes);
-}
-
-// Low-level usb command transmit function.
-int
-usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    if (!CONFIG_USB_MSC)
-        return 0;
-
-    dprintf(16, "usb_cmd_data id=%p write=%d count=%d bs=%d buf=%p\n"
-            , op->drive_g, 0, op->count, blocksize, op->buf_fl);
-    struct usbdrive_s *udrive_g = container_of(
-        op->drive_g, struct usbdrive_s, drive);
-
-    // Setup command block wrapper.
-    u32 bytes = blocksize * op->count;
-    struct cbw_s cbw;
-    memset(&cbw, 0, sizeof(cbw));
-    memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE);
-    cbw.dCBWSignature = CBW_SIGNATURE;
-    cbw.dCBWTag = 999; // XXX
-    cbw.dCBWDataTransferLength = bytes;
-    cbw.bmCBWFlags = cdb_is_read(cdbcmd, blocksize) ? USB_DIR_IN : USB_DIR_OUT;
-    cbw.bCBWLUN = GET_GLOBAL(udrive_g->lun);
-    cbw.bCBWCBLength = USB_CDB_SIZE;
-
-    // Transfer cbw to device.
-    int ret = usb_msc_send(udrive_g, USB_DIR_OUT
-                           , MAKE_FLATPTR(GET_SEG(SS), &cbw), sizeof(cbw));
-    if (ret)
-        goto fail;
-
-    // Transfer data to/from device.
-    if (bytes) {
-        ret = usb_msc_send(udrive_g, cbw.bmCBWFlags, op->buf_fl, bytes);
-        if (ret)
-            goto fail;
-    }
-
-    // Transfer csw info.
-    struct csw_s csw;
-    ret = usb_msc_send(udrive_g, USB_DIR_IN
-                        , MAKE_FLATPTR(GET_SEG(SS), &csw), sizeof(csw));
-    if (ret)
-        goto fail;
-
-    if (!csw.bCSWStatus)
-        return DISK_RET_SUCCESS;
-    if (csw.bCSWStatus == 2)
-        goto fail;
-
-    if (blocksize)
-        op->count -= csw.dCSWDataResidue / blocksize;
-    return DISK_RET_EBADTRACK;
-
-fail:
-    // XXX - reset connection
-    dprintf(1, "USB transmission failed\n");
-    op->count = 0;
-    return DISK_RET_EBADTRACK;
-}
-
-static int
-usb_msc_maxlun(struct usb_pipe *pipe)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-    req.bRequest = 0xfe;
-    req.wValue = 0;
-    req.wIndex = 0;
-    req.wLength = 1;
-    unsigned char maxlun;
-    int ret = send_default_control(pipe, &req, &maxlun);
-    if (ret)
-        return 0;
-    return maxlun;
-}
-
-static int
-usb_msc_lun_setup(struct usb_pipe *inpipe, struct usb_pipe *outpipe,
-                  struct usbdevice_s *usbdev, int lun)
-{
-    // Allocate drive structure.
-    struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g));
-    if (!udrive_g) {
-        warn_noalloc();
-        return -1;
-    }
-    memset(udrive_g, 0, sizeof(*udrive_g));
-    udrive_g->drive.type = DTYPE_USB;
-    udrive_g->bulkin = inpipe;
-    udrive_g->bulkout = outpipe;
-    udrive_g->lun = lun;
-
-    int prio = bootprio_find_usb(usbdev, lun);
-    int ret = scsi_drive_setup(&udrive_g->drive, "USB MSC", prio);
-    if (ret) {
-        dprintf(1, "Unable to configure USB MSC drive.\n");
-        free(udrive_g);
-        return -1;
-    }
-    return 0;
-}
-
-/****************************************************************
- * Setup
- ****************************************************************/
-
-// Configure a usb msc device.
-int
-usb_msc_setup(struct usbdevice_s *usbdev)
-{
-    if (!CONFIG_USB_MSC)
-        return -1;
-
-    // Verify right kind of device
-    struct usb_interface_descriptor *iface = usbdev->iface;
-    if ((iface->bInterfaceSubClass != US_SC_SCSI &&
-         iface->bInterfaceSubClass != US_SC_ATAPI_8070 &&
-         iface->bInterfaceSubClass != US_SC_ATAPI_8020)
-        || iface->bInterfaceProtocol != US_PR_BULK) {
-        dprintf(1, "Unsupported MSC USB device (subclass=%02x proto=%02x)\n"
-                , iface->bInterfaceSubClass, iface->bInterfaceProtocol);
-        return -1;
-    }
-
-    // Find bulk in and bulk out endpoints.
-    struct usb_pipe *inpipe = NULL, *outpipe = NULL;
-    struct usb_endpoint_descriptor *indesc = findEndPointDesc(
-        usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
-    struct usb_endpoint_descriptor *outdesc = findEndPointDesc(
-        usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
-    if (!indesc || !outdesc)
-        goto fail;
-    inpipe = usb_alloc_pipe(usbdev, indesc);
-    outpipe = usb_alloc_pipe(usbdev, outdesc);
-    if (!inpipe || !outpipe)
-        goto fail;
-
-    int maxlun = usb_msc_maxlun(usbdev->defpipe);
-    int lun, pipesused = 0;
-    for (lun = 0; lun < maxlun + 1; lun++) {
-        int ret = usb_msc_lun_setup(inpipe, outpipe, usbdev, lun);
-        if (!ret)
-            pipesused = 1;
-    }
-
-    if (!pipesused)
-        goto fail;
-
-    return 0;
-fail:
-    dprintf(1, "Unable to configure USB MSC device.\n");
-    free_pipe(inpipe);
-    free_pipe(outpipe);
-    return -1;
-}
diff --git a/src/usb-msc.h b/src/usb-msc.h
deleted file mode 100644 (file)
index c40d755..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __USB_MSC_H
-#define __USB_MSC_H
-
-// usb-msc.c
-struct disk_op_s;
-int usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
-struct usbdevice_s;
-int usb_msc_setup(struct usbdevice_s *usbdev);
-
-#endif // ush-msc.h
diff --git a/src/usb-ohci.c b/src/usb-ohci.c
deleted file mode 100644 (file)
index e5c9fa5..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-// Code for handling OHCI USB controllers.
-//
-// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // pci_bdf_to_bus
-#include "config.h" // CONFIG_*
-#include "usb-ohci.h" // struct ohci_hcca
-#include "pci_regs.h" // PCI_BASE_ADDRESS_0
-#include "usb.h" // struct usb_s
-#include "biosvar.h" // GET_LOWFLAT
-
-#define FIT                     (1 << 31)
-
-struct usb_ohci_s {
-    struct usb_s usb;
-    struct ohci_regs *regs;
-};
-
-struct ohci_pipe {
-    struct ohci_ed ed;
-    struct usb_pipe pipe;
-    void *data;
-    int count;
-    struct ohci_td *tds;
-};
-
-
-/****************************************************************
- * Root hub
- ****************************************************************/
-
-// Check if device attached to port
-static int
-ohci_hub_detect(struct usbhub_s *hub, u32 port)
-{
-    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
-    u32 sts = readl(&cntl->regs->roothub_portstatus[port]);
-    if (!(sts & RH_PS_CCS))
-        // No device.
-        return -1;
-
-    // XXX - need to wait for USB_TIME_ATTDB if just powered up?
-
-    return 0;
-}
-
-// Disable port
-static void
-ohci_hub_disconnect(struct usbhub_s *hub, u32 port)
-{
-    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
-    writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
-}
-
-// Reset device on port
-static int
-ohci_hub_reset(struct usbhub_s *hub, u32 port)
-{
-    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
-    writel(&cntl->regs->roothub_portstatus[port], RH_PS_PRS);
-    u32 sts;
-    u32 end = timer_calc(USB_TIME_DRSTR * 2);
-    for (;;) {
-        sts = readl(&cntl->regs->roothub_portstatus[port]);
-        if (!(sts & RH_PS_PRS))
-            // XXX - need to ensure USB_TIME_DRSTR time in reset?
-            break;
-        if (timer_check(end)) {
-            // Timeout.
-            warn_timeout();
-            ohci_hub_disconnect(hub, port);
-            return -1;
-        }
-        yield();
-    }
-
-    if ((sts & (RH_PS_CCS|RH_PS_PES)) != (RH_PS_CCS|RH_PS_PES))
-        // Device no longer present
-        return -1;
-
-    return !!(sts & RH_PS_LSDA);
-}
-
-static struct usbhub_op_s ohci_HubOp = {
-    .detect = ohci_hub_detect,
-    .reset = ohci_hub_reset,
-    .disconnect = ohci_hub_disconnect,
-};
-
-// Find any devices connected to the root hub.
-static int
-check_ohci_ports(struct usb_ohci_s *cntl)
-{
-    ASSERT32FLAT();
-    // Turn on power for all devices on roothub.
-    u32 rha = readl(&cntl->regs->roothub_a);
-    rha &= ~(RH_A_PSM | RH_A_OCPM);
-    writel(&cntl->regs->roothub_status, RH_HS_LPSC);
-    writel(&cntl->regs->roothub_b, RH_B_PPCM);
-    msleep((rha >> 24) * 2);
-    // XXX - need to sleep for USB_TIME_SIGATT if just powered up?
-
-    struct usbhub_s hub;
-    memset(&hub, 0, sizeof(hub));
-    hub.cntl = &cntl->usb;
-    hub.portcount = rha & RH_A_NDP;
-    hub.op = &ohci_HubOp;
-    usb_enumerate(&hub);
-    return hub.devcount;
-}
-
-
-/****************************************************************
- * Setup
- ****************************************************************/
-
-// Wait for next USB frame to start - for ensuring safe memory release.
-static void
-ohci_waittick(struct usb_ohci_s *cntl)
-{
-    barrier();
-    struct ohci_hcca *hcca = (void*)cntl->regs->hcca;
-    u32 startframe = hcca->frame_no;
-    u32 end = timer_calc(1000 * 5);
-    for (;;) {
-        if (hcca->frame_no != startframe)
-            break;
-        if (timer_check(end)) {
-            warn_timeout();
-            return;
-        }
-        yield();
-    }
-}
-
-static void
-ohci_free_pipes(struct usb_ohci_s *cntl)
-{
-    dprintf(7, "ohci_free_pipes %p\n", cntl);
-
-    u32 creg = readl(&cntl->regs->control);
-    if (creg & (OHCI_CTRL_CLE|OHCI_CTRL_BLE)) {
-        writel(&cntl->regs->control, creg & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE));
-        ohci_waittick(cntl);
-    }
-
-    u32 *pos = &cntl->regs->ed_controlhead;
-    for (;;) {
-        struct ohci_ed *next = (void*)*pos;
-        if (!next)
-            break;
-        struct ohci_pipe *pipe = container_of(next, struct ohci_pipe, ed);
-        if (pipe->pipe.cntl != &cntl->usb) {
-            *pos = next->hwNextED;
-            free(pipe);
-        } else {
-            pos = &next->hwNextED;
-        }
-    }
-
-    writel(&cntl->regs->ed_controlcurrent, 0);
-    writel(&cntl->regs->ed_bulkcurrent, 0);
-    writel(&cntl->regs->control, creg);
-    cntl->usb.freelist = NULL;
-}
-
-static int
-start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca)
-{
-    u32 oldfminterval = readl(&cntl->regs->fminterval);
-    u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC;
-
-    // XXX - check if already running?
-
-    // Do reset
-    writel(&cntl->regs->control, OHCI_USB_RESET | oldrwc);
-    readl(&cntl->regs->control); // flush writes
-    msleep(USB_TIME_DRSTR);
-
-    // Do software init (min 10us, max 2ms)
-    u32 end = timer_calc_usec(10);
-    writel(&cntl->regs->cmdstatus, OHCI_HCR);
-    for (;;) {
-        u32 status = readl(&cntl->regs->cmdstatus);
-        if (! status & OHCI_HCR)
-            break;
-        if (timer_check(end)) {
-            warn_timeout();
-            return -1;
-        }
-    }
-
-    // Init memory
-    writel(&cntl->regs->ed_controlhead, 0);
-    writel(&cntl->regs->ed_bulkhead, 0);
-    writel(&cntl->regs->hcca, (u32)hcca);
-
-    // Init fminterval
-    u32 fi = oldfminterval & 0x3fff;
-    writel(&cntl->regs->fminterval
-           , (((oldfminterval & FIT) ^ FIT)
-              | fi | (((6 * (fi - 210)) / 7) << 16)));
-    writel(&cntl->regs->periodicstart, ((9 * fi) / 10) & 0x3fff);
-    readl(&cntl->regs->control); // flush writes
-
-    // XXX - verify that fminterval was setup correctly.
-
-    // Go into operational state
-    writel(&cntl->regs->control
-           , (OHCI_CTRL_CBSR | OHCI_CTRL_CLE | OHCI_CTRL_PLE
-              | OHCI_USB_OPER | oldrwc));
-    readl(&cntl->regs->control); // flush writes
-
-    return 0;
-}
-
-static void
-stop_ohci(struct usb_ohci_s *cntl)
-{
-    u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC;
-    writel(&cntl->regs->control, oldrwc);
-    readl(&cntl->regs->control); // flush writes
-}
-
-static void
-configure_ohci(void *data)
-{
-    struct usb_ohci_s *cntl = data;
-
-    // Allocate memory
-    struct ohci_hcca *hcca = memalign_high(256, sizeof(*hcca));
-    struct ohci_ed *intr_ed = malloc_high(sizeof(*intr_ed));
-    if (!hcca || !intr_ed) {
-        warn_noalloc();
-        goto free;
-    }
-    memset(hcca, 0, sizeof(*hcca));
-    memset(intr_ed, 0, sizeof(*intr_ed));
-    intr_ed->hwINFO = ED_SKIP;
-    int i;
-    for (i=0; i<ARRAY_SIZE(hcca->int_table); i++)
-        hcca->int_table[i] = (u32)intr_ed;
-
-    int ret = start_ohci(cntl, hcca);
-    if (ret)
-        goto err;
-
-    int count = check_ohci_ports(cntl);
-    ohci_free_pipes(cntl);
-    if (! count)
-        goto err;
-    return;
-
-err:
-    stop_ohci(cntl);
-free:
-    free(hcca);
-    free(intr_ed);
-}
-
-void
-ohci_setup(struct pci_device *pci, int busid)
-{
-    if (! CONFIG_USB_OHCI)
-        return;
-    struct usb_ohci_s *cntl = malloc_tmphigh(sizeof(*cntl));
-    if (!cntl) {
-        warn_noalloc();
-        return;
-    }
-    memset(cntl, 0, sizeof(*cntl));
-    cntl->usb.busid = busid;
-    cntl->usb.pci = pci;
-    cntl->usb.type = USB_TYPE_OHCI;
-
-    u16 bdf = pci->bdf;
-    u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0);
-    cntl->regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK);
-
-    dprintf(1, "OHCI 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);
-
-    // Enable bus mastering and memory access.
-    pci_config_maskw(bdf, PCI_COMMAND
-                     , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY);
-
-    // XXX - check for and disable SMM control?
-
-    // Disable interrupts
-    writel(&cntl->regs->intrdisable, ~0);
-    writel(&cntl->regs->intrstatus, ~0);
-
-    run_thread(configure_ohci, cntl);
-}
-
-
-/****************************************************************
- * End point communication
- ****************************************************************/
-
-// Setup fields in ed
-static void
-ohci_desc2pipe(struct ohci_pipe *pipe, struct usbdevice_s *usbdev
-               , struct usb_endpoint_descriptor *epdesc)
-{
-    usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
-    pipe->ed.hwINFO = (ED_SKIP | usbdev->devaddr | (pipe->pipe.ep << 7)
-                       | (epdesc->wMaxPacketSize << 16)
-                       | (usbdev->speed ? ED_LOWSPEED : 0));
-}
-
-static struct usb_pipe *
-ohci_alloc_intr_pipe(struct usbdevice_s *usbdev
-                     , struct usb_endpoint_descriptor *epdesc)
-{
-    struct usb_ohci_s *cntl = container_of(
-        usbdev->hub->cntl, struct usb_ohci_s, usb);
-    int frameexp = usb_getFrameExp(usbdev, epdesc);
-    dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
-
-    if (frameexp > 5)
-        frameexp = 5;
-    int maxpacket = epdesc->wMaxPacketSize;
-    // Determine number of entries needed for 2 timer ticks.
-    int ms = 1<<frameexp;
-    int count = DIV_ROUND_UP(ticks_to_ms(2), ms) + 1;
-    struct ohci_pipe *pipe = malloc_low(sizeof(*pipe));
-    struct ohci_td *tds = malloc_low(sizeof(*tds) * count);
-    void *data = malloc_low(maxpacket * count);
-    if (!pipe || !tds || !data)
-        goto err;
-    memset(pipe, 0, sizeof(*pipe));
-    ohci_desc2pipe(pipe, usbdev, epdesc);
-    pipe->ed.hwINFO &= ~ED_SKIP;
-    pipe->data = data;
-    pipe->count = count;
-    pipe->tds = tds;
-
-    struct ohci_ed *ed = &pipe->ed;
-    ed->hwHeadP = (u32)&tds[0];
-    ed->hwTailP = (u32)&tds[count-1];
-
-    int i;
-    for (i=0; i<count-1; i++) {
-        tds[i].hwINFO = TD_DP_IN | TD_T_TOGGLE | TD_CC;
-        tds[i].hwCBP = (u32)data + maxpacket * i;
-        tds[i].hwNextTD = (u32)&tds[i+1];
-        tds[i].hwBE = tds[i].hwCBP + maxpacket - 1;
-    }
-
-    // Add to interrupt schedule.
-    struct ohci_hcca *hcca = (void*)cntl->regs->hcca;
-    if (frameexp == 0) {
-        // Add to existing interrupt entry.
-        struct ohci_ed *intr_ed = (void*)hcca->int_table[0];
-        ed->hwNextED = intr_ed->hwNextED;
-        barrier();
-        intr_ed->hwNextED = (u32)ed;
-    } else {
-        int startpos = 1<<(frameexp-1);
-        ed->hwNextED = hcca->int_table[startpos];
-        barrier();
-        for (i=startpos; i<ARRAY_SIZE(hcca->int_table); i+=ms)
-            hcca->int_table[i] = (u32)ed;
-    }
-
-    return &pipe->pipe;
-
-err:
-    free(pipe);
-    free(tds);
-    free(data);
-    return NULL;
-}
-
-struct usb_pipe *
-ohci_alloc_pipe(struct usbdevice_s *usbdev
-                , struct usb_endpoint_descriptor *epdesc)
-{
-    if (! CONFIG_USB_OHCI)
-        return NULL;
-    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-    if (eptype == USB_ENDPOINT_XFER_INT)
-        return ohci_alloc_intr_pipe(usbdev, epdesc);
-    if (eptype != USB_ENDPOINT_XFER_CONTROL) {
-        dprintf(1, "OHCI Bulk transfers not supported.\n");
-        return NULL;
-    }
-    struct usb_ohci_s *cntl = container_of(
-        usbdev->hub->cntl, struct usb_ohci_s, usb);
-    dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb);
-
-    struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
-    if (usbpipe) {
-        // Use previously allocated pipe.
-        struct ohci_pipe *pipe = container_of(usbpipe, struct ohci_pipe, pipe);
-        ohci_desc2pipe(pipe, usbdev, epdesc);
-        return usbpipe;
-    }
-
-    // Allocate a new queue head.
-    struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
-    if (!pipe) {
-        warn_noalloc();
-        return NULL;
-    }
-    memset(pipe, 0, sizeof(*pipe));
-    ohci_desc2pipe(pipe, usbdev, epdesc);
-
-    // Add queue head to controller list.
-    pipe->ed.hwNextED = cntl->regs->ed_controlhead;
-    barrier();
-    cntl->regs->ed_controlhead = (u32)&pipe->ed;
-    return &pipe->pipe;
-}
-
-static int
-wait_ed(struct ohci_ed *ed)
-{
-    // XXX - 500ms just a guess
-    u32 end = timer_calc(500);
-    for (;;) {
-        if (ed->hwHeadP == ed->hwTailP)
-            return 0;
-        if (timer_check(end)) {
-            warn_timeout();
-            return -1;
-        }
-        yield();
-    }
-}
-
-int
-ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
-             , void *data, int datasize)
-{
-    if (! CONFIG_USB_OHCI)
-        return -1;
-    dprintf(5, "ohci_control %p\n", p);
-    if (datasize > 4096) {
-        // XXX - should support larger sizes.
-        warn_noalloc();
-        return -1;
-    }
-    struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
-    struct usb_ohci_s *cntl = container_of(
-        pipe->pipe.cntl, struct usb_ohci_s, usb);
-
-    // Setup transfer descriptors
-    struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3);
-    if (!tds) {
-        warn_noalloc();
-        return -1;
-    }
-    struct ohci_td *td = tds;
-    td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC;
-    td->hwCBP = (u32)cmd;
-    td->hwNextTD = (u32)&td[1];
-    td->hwBE = (u32)cmd + cmdsize - 1;
-    td++;
-    if (datasize) {
-        td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC;
-        td->hwCBP = (u32)data;
-        td->hwNextTD = (u32)&td[1];
-        td->hwBE = (u32)data + datasize - 1;
-        td++;
-    }
-    td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC;
-    td->hwCBP = 0;
-    td->hwNextTD = (u32)&td[1];
-    td->hwBE = 0;
-    td++;
-
-    // Transfer data
-    pipe->ed.hwHeadP = (u32)tds;
-    pipe->ed.hwTailP = (u32)td;
-    barrier();
-    pipe->ed.hwINFO &= ~ED_SKIP;
-    writel(&cntl->regs->cmdstatus, OHCI_CLF);
-
-    int ret = wait_ed(&pipe->ed);
-    pipe->ed.hwINFO |= ED_SKIP;
-    if (ret)
-        ohci_waittick(cntl);
-    free(tds);
-    return ret;
-}
-
-int
-ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
-{
-    return -1;
-}
-
-int
-ohci_poll_intr(struct usb_pipe *p, void *data)
-{
-    ASSERT16();
-    if (! CONFIG_USB_OHCI)
-        return -1;
-
-    struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
-    struct ohci_td *tds = GET_LOWFLAT(pipe->tds);
-    struct ohci_td *head = (void*)(GET_LOWFLAT(pipe->ed.hwHeadP) & ~(ED_C|ED_H));
-    struct ohci_td *tail = (void*)GET_LOWFLAT(pipe->ed.hwTailP);
-    int count = GET_LOWFLAT(pipe->count);
-    int pos = (tail - tds + 1) % count;
-    struct ohci_td *next = &tds[pos];
-    if (head == next)
-        // No intrs found.
-        return -1;
-    // XXX - check for errors.
-
-    // Copy data.
-    int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
-    void *pipedata = GET_LOWFLAT((pipe->data));
-    void *intrdata = pipedata + maxpacket * pos;
-    memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(intrdata), maxpacket);
-
-    // Reenable this td.
-    SET_LOWFLAT(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC);
-    intrdata = pipedata + maxpacket * (tail-tds);
-    SET_LOWFLAT(tail->hwCBP, (u32)intrdata);
-    SET_LOWFLAT(tail->hwNextTD, (u32)next);
-    SET_LOWFLAT(tail->hwBE, (u32)intrdata + maxpacket - 1);
-    barrier();
-    SET_LOWFLAT(pipe->ed.hwTailP, (u32)next);
-
-    return 0;
-}
diff --git a/src/usb-ohci.h b/src/usb-ohci.h
deleted file mode 100644 (file)
index ad0ffec..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-#ifndef __USB_OHCI_H
-#define __USB_OHCI_H
-
-// usb-ohci.c
-void ohci_setup(struct pci_device *pci, int busid);
-struct usbdevice_s;
-struct usb_endpoint_descriptor;
-struct usb_pipe *ohci_alloc_pipe(struct usbdevice_s *usbdev
-                                 , struct usb_endpoint_descriptor *epdesc);
-struct usb_pipe;
-int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
-                 , void *data, int datasize);
-int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
-int ohci_poll_intr(struct usb_pipe *p, void *data);
-
-
-/****************************************************************
- * ohci structs and flags
- ****************************************************************/
-
-struct ohci_ed {
-    u32 hwINFO;
-    u32 hwTailP;
-    u32 hwHeadP;
-    u32 hwNextED;
-} PACKED;
-
-#define ED_ISO          (1 << 15)
-#define ED_SKIP         (1 << 14)
-#define ED_LOWSPEED     (1 << 13)
-#define ED_OUT          (0x01 << 11)
-#define ED_IN           (0x02 << 11)
-
-#define ED_C            (0x02)
-#define ED_H            (0x01)
-
-struct ohci_td {
-    u32 hwINFO;
-    u32 hwCBP;
-    u32 hwNextTD;
-    u32 hwBE;
-} PACKED;
-
-#define TD_CC       0xf0000000
-#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
-#define TD_DI       0x00E00000
-
-#define TD_DONE     0x00020000
-#define TD_ISO      0x00010000
-
-#define TD_EC       0x0C000000
-#define TD_T        0x03000000
-#define TD_T_DATA0  0x02000000
-#define TD_T_DATA1  0x03000000
-#define TD_T_TOGGLE 0x00000000
-#define TD_DP       0x00180000
-#define TD_DP_SETUP 0x00000000
-#define TD_DP_IN    0x00100000
-#define TD_DP_OUT   0x00080000
-
-#define TD_R        0x00040000
-
-struct ohci_hcca {
-    u32  int_table[32];
-    u32  frame_no;
-    u32  done_head;
-    u8   reserved[120];
-} PACKED;
-
-struct ohci_regs {
-    u32  revision;
-    u32  control;
-    u32  cmdstatus;
-    u32  intrstatus;
-    u32  intrenable;
-    u32  intrdisable;
-
-    u32  hcca;
-    u32  ed_periodcurrent;
-    u32  ed_controlhead;
-    u32  ed_controlcurrent;
-    u32  ed_bulkhead;
-    u32  ed_bulkcurrent;
-    u32  donehead;
-
-    u32  fminterval;
-    u32  fmremaining;
-    u32  fmnumber;
-    u32  periodicstart;
-    u32  lsthresh;
-
-    u32  roothub_a;
-    u32  roothub_b;
-    u32  roothub_status;
-    u32  roothub_portstatus[15];
-} PACKED;
-
-#define OHCI_CTRL_CBSR  (3 << 0)
-#define OHCI_CTRL_PLE   (1 << 2)
-#define OHCI_CTRL_CLE   (1 << 4)
-#define OHCI_CTRL_BLE   (1 << 5)
-#define OHCI_CTRL_HCFS  (3 << 6)
-#       define OHCI_USB_RESET   (0 << 6)
-#       define OHCI_USB_OPER    (2 << 6)
-#define OHCI_CTRL_RWC   (1 << 9)
-
-#define OHCI_HCR        (1 << 0)
-#define OHCI_CLF        (1 << 1)
-
-#define OHCI_INTR_MIE   (1 << 31)
-
-#define RH_PS_CCS            0x00000001
-#define RH_PS_PES            0x00000002
-#define RH_PS_PSS            0x00000004
-#define RH_PS_POCI           0x00000008
-#define RH_PS_PRS            0x00000010
-#define RH_PS_PPS            0x00000100
-#define RH_PS_LSDA           0x00000200
-#define RH_PS_CSC            0x00010000
-#define RH_PS_PESC           0x00020000
-#define RH_PS_PSSC           0x00040000
-#define RH_PS_OCIC           0x00080000
-#define RH_PS_PRSC           0x00100000
-
-#define RH_HS_LPS            0x00000001
-#define RH_HS_OCI            0x00000002
-#define RH_HS_DRWE           0x00008000
-#define RH_HS_LPSC           0x00010000
-#define RH_HS_OCIC           0x00020000
-#define RH_HS_CRWE           0x80000000
-
-#define RH_B_DR         0x0000ffff
-#define RH_B_PPCM       0xffff0000
-
-#define RH_A_NDP        (0xff << 0)
-#define RH_A_PSM        (1 << 8)
-#define RH_A_NPS        (1 << 9)
-#define RH_A_DT         (1 << 10)
-#define RH_A_OCPM       (1 << 11)
-#define RH_A_NOCP       (1 << 12)
-#define RH_A_POTPGT     (0xff << 24)
-
-#endif // usb-ohci.h
diff --git a/src/usb-uas.c b/src/usb-uas.c
deleted file mode 100644 (file)
index 3169389..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-// Code for handling usb attached scsi devices.
-//
-// only usb 2.0 for now.
-//
-// once we have xhci driver with usb 3.0 support this must
-// be updated to use usb3 streams so booting from usb3
-// devices actually works.
-//
-// Authors:
-//  Gerd Hoffmann <kraxel@redhat.com>
-//
-// based on usb-msc.c which is written by:
-//  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_USB_UAS
-#include "usb.h" // struct usb_s
-#include "biosvar.h" // GET_GLOBAL
-#include "blockcmd.h" // cdb_read
-#include "disk.h" // DTYPE_UAS
-#include "boot.h" // bootprio_find_usb
-#include "usb-uas.h" // usb_uas_init
-
-#define UAS_UI_COMMAND              0x01
-#define UAS_UI_SENSE                0x03
-#define UAS_UI_RESPONSE             0x04
-#define UAS_UI_TASK_MGMT            0x05
-#define UAS_UI_READ_READY           0x06
-#define UAS_UI_WRITE_READY          0x07
-
-#define UAS_PIPE_ID_COMMAND         0x01
-#define UAS_PIPE_ID_STATUS          0x02
-#define UAS_PIPE_ID_DATA_IN         0x03
-#define UAS_PIPE_ID_DATA_OUT        0x04
-
-typedef struct {
-    u8    id;
-    u8    reserved;
-    u16   tag;
-} PACKED  uas_ui_header;
-
-typedef struct {
-    u8    prio_taskattr;   /* 6:3 priority, 2:0 task attribute   */
-    u8    reserved_1;
-    u8    add_cdb_length;  /* 7:2 additional adb length (dwords) */
-    u8    reserved_2;
-    u8    lun[8];
-    u8    cdb[16];
-    u8    add_cdb[];
-} PACKED  uas_ui_command;
-
-typedef struct {
-    u16   status_qualifier;
-    u8    status;
-    u8    reserved[7];
-    u16   sense_length;
-    u8    sense_data[18];
-} PACKED  uas_ui_sense;
-
-typedef struct {
-    u16   add_response_info;
-    u8    response_code;
-} PACKED  uas_ui_response;
-
-typedef struct {
-    u8    function;
-    u8    reserved;
-    u16   task_tag;
-    u8    lun[8];
-} PACKED  uas_ui_task_mgmt;
-
-typedef struct {
-    uas_ui_header  hdr;
-    union {
-        uas_ui_command   command;
-        uas_ui_sense     sense;
-        uas_ui_task_mgmt task;
-        uas_ui_response  response;
-    };
-} PACKED  uas_ui;
-
-struct uasdrive_s {
-    struct drive_s drive;
-    struct usb_pipe *command, *status, *data_in, *data_out;
-    int lun;
-};
-
-int
-uas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    if (!CONFIG_USB_UAS)
-        return DISK_RET_EBADTRACK;
-
-    struct uasdrive_s *drive = container_of(
-        op->drive_g, struct uasdrive_s, drive);
-
-    uas_ui ui;
-    memset(&ui, 0, sizeof(ui));
-    ui.hdr.id = UAS_UI_COMMAND;
-    ui.hdr.tag = 0xdead;
-    ui.command.lun[1] = drive->lun;
-    memcpy(ui.command.cdb, cdbcmd, sizeof(ui.command.cdb));
-    int ret = usb_send_bulk(GET_GLOBAL(drive->command),
-                            USB_DIR_OUT, MAKE_FLATPTR(GET_SEG(SS), &ui),
-                            sizeof(ui.hdr) + sizeof(ui.command));
-    if (ret) {
-        dprintf(1, "uas: command send fail");
-        goto fail;
-    }
-
-    memset(&ui, 0xff, sizeof(ui));
-    ret = usb_send_bulk(GET_GLOBAL(drive->status),
-                        USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui));
-    if (ret) {
-        dprintf(1, "uas: status recv fail");
-        goto fail;
-    }
-
-    switch (ui.hdr.id) {
-    case UAS_UI_SENSE:
-        goto have_sense;
-    case UAS_UI_READ_READY:
-        ret = usb_send_bulk(GET_GLOBAL(drive->data_in),
-                            USB_DIR_IN, op->buf_fl, op->count * blocksize);
-        if (ret) {
-            dprintf(1, "uas: data read fail");
-            goto fail;
-        }
-        break;
-    case UAS_UI_WRITE_READY:
-        ret = usb_send_bulk(GET_GLOBAL(drive->data_out),
-                            USB_DIR_OUT, op->buf_fl, op->count * blocksize);
-        if (ret) {
-            dprintf(1, "uas: data write fail");
-            goto fail;
-        }
-        break;
-    default:
-        dprintf(1, "uas: unknown status ui id %d", ui.hdr.id);
-        goto fail;
-    }
-
-    memset(&ui, 0xff, sizeof(ui));
-    ret = usb_send_bulk(GET_GLOBAL(drive->status),
-                        USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui));
-    if (ret) {
-        dprintf(1, "uas: status recv fail");
-        goto fail;
-    }
-    if (ui.hdr.id != UAS_UI_SENSE) {
-        dprintf(1, "uas: expected sense ui, got ui id %d", ui.hdr.id);
-        goto fail;
-    }
-
-have_sense:
-    if (ui.sense.status == 0) {
-        return DISK_RET_SUCCESS;
-    }
-
-fail:
-    return DISK_RET_EBADTRACK;
-}
-
-static int
-uas_lun_setup(struct usbdevice_s *usbdev,
-              struct usb_pipe *command, struct usb_pipe *status,
-              struct usb_pipe *data_in, struct usb_pipe *data_out,
-              int lun)
-{
-    // Allocate drive structure.
-    struct uasdrive_s *drive = malloc_fseg(sizeof(*drive));
-    if (!drive) {
-        warn_noalloc();
-        return -1;
-    }
-    memset(drive, 0, sizeof(*drive));
-    drive->drive.type = DTYPE_UAS;
-    drive->command = command;
-    drive->status = status;
-    drive->data_in = data_in;
-    drive->data_out = data_out;
-    drive->lun = lun;
-
-    int prio = bootprio_find_usb(usbdev, lun);
-    int ret = scsi_drive_setup(&drive->drive, "USB UAS", prio);
-    if (ret) {
-        free(drive);
-        return -1;
-    }
-    return 0;
-}
-
-int
-usb_uas_setup(struct usbdevice_s *usbdev)
-{
-    if (!CONFIG_USB_UAS)
-        return -1;
-
-    // Verify right kind of device
-    struct usb_interface_descriptor *iface = usbdev->iface;
-    if (iface->bInterfaceSubClass != US_SC_SCSI ||
-        iface->bInterfaceProtocol != US_PR_UAS) {
-        dprintf(1, "Unsupported UAS device (subclass=%02x proto=%02x)\n"
-                , iface->bInterfaceSubClass, iface->bInterfaceProtocol);
-        return -1;
-    }
-
-    /* find & allocate pipes */
-    struct usb_endpoint_descriptor *ep = NULL;
-    struct usb_pipe *command = NULL;
-    struct usb_pipe *status = NULL;
-    struct usb_pipe *data_in = NULL;
-    struct usb_pipe *data_out = NULL;
-    u8 *desc = (u8*)iface;
-    while (desc) {
-        desc += desc[0];
-        switch (desc[1]) {
-        case USB_DT_ENDPOINT:
-            ep = (void*)desc;
-            break;
-        case 0x24:
-            switch (desc[2]) {
-            case UAS_PIPE_ID_COMMAND:
-                command = usb_alloc_pipe(usbdev, ep);
-                break;
-            case UAS_PIPE_ID_STATUS:
-                status = usb_alloc_pipe(usbdev, ep);
-                break;
-            case UAS_PIPE_ID_DATA_IN:
-                data_in = usb_alloc_pipe(usbdev, ep);
-                break;
-            case UAS_PIPE_ID_DATA_OUT:
-                data_out = usb_alloc_pipe(usbdev, ep);
-                break;
-            default:
-                goto fail;
-            }
-            break;
-        default:
-            desc = NULL;
-            break;
-        }
-    }
-    if (!command || !status || !data_in || !data_out)
-        goto fail;
-
-    /* TODO: send REPORT LUNS.  For now, only LUN 0 is recognized.  */
-    int ret = uas_lun_setup(usbdev, command, status, data_in, data_out, 0);
-    if (ret < 0) {
-        dprintf(1, "Unable to configure UAS drive.\n");
-        goto fail;
-    }
-
-    return 0;
-
-fail:
-    free_pipe(command);
-    free_pipe(status);
-    free_pipe(data_in);
-    free_pipe(data_out);
-    return -1;
-}
diff --git a/src/usb-uas.h b/src/usb-uas.h
deleted file mode 100644 (file)
index ad91c5f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __USB_UAS_H
-#define __USB_UAS_H
-
-struct disk_op_s;
-int uas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
-struct usbdevice_s;
-int usb_uas_setup(struct usbdevice_s *usbdev);
-
-#endif /* __USB_UAS_H */
diff --git a/src/usb-uhci.c b/src/usb-uhci.c
deleted file mode 100644 (file)
index d8f9b1e..0000000
+++ /dev/null
@@ -1,578 +0,0 @@
-// Code for handling UHCI USB controllers.
-//
-// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // pci_bdf_to_bus
-#include "config.h" // CONFIG_*
-#include "ioport.h" // outw
-#include "usb-uhci.h" // USBLEGSUP
-#include "pci_regs.h" // PCI_BASE_ADDRESS_4
-#include "usb.h" // struct usb_s
-#include "biosvar.h" // GET_LOWFLAT
-
-struct usb_uhci_s {
-    struct usb_s usb;
-    u16 iobase;
-    struct uhci_qh *control_qh;
-    struct uhci_framelist *framelist;
-};
-
-struct uhci_pipe {
-    struct uhci_qh qh;
-    struct uhci_td *next_td;
-    struct usb_pipe pipe;
-    u16 iobase;
-    u8 toggle;
-};
-
-
-/****************************************************************
- * Root hub
- ****************************************************************/
-
-// Check if device attached to a given port
-static int
-uhci_hub_detect(struct usbhub_s *hub, u32 port)
-{
-    struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
-    u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
-
-    u16 status = inw(ioport);
-    if (!(status & USBPORTSC_CCS))
-        // No device
-        return -1;
-
-    // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
-
-    // Begin reset on port
-    outw(USBPORTSC_PR, ioport);
-    msleep(USB_TIME_DRSTR);
-    return 0;
-}
-
-// Reset device on port
-static int
-uhci_hub_reset(struct usbhub_s *hub, u32 port)
-{
-    struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
-    u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
-
-    // Finish reset on port
-    outw(0, ioport);
-    udelay(6); // 64 high-speed bit times
-    u16 status = inw(ioport);
-    if (!(status & USBPORTSC_CCS))
-        // No longer connected
-        return -1;
-    outw(USBPORTSC_PE, ioport);
-    return !!(status & USBPORTSC_LSDA);
-}
-
-// Disable port
-static void
-uhci_hub_disconnect(struct usbhub_s *hub, u32 port)
-{
-    struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
-    u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
-    outw(0, ioport);
-}
-
-static struct usbhub_op_s uhci_HubOp = {
-    .detect = uhci_hub_detect,
-    .reset = uhci_hub_reset,
-    .disconnect = uhci_hub_disconnect,
-};
-
-// Find any devices connected to the root hub.
-static int
-check_uhci_ports(struct usb_uhci_s *cntl)
-{
-    ASSERT32FLAT();
-    struct usbhub_s hub;
-    memset(&hub, 0, sizeof(hub));
-    hub.cntl = &cntl->usb;
-    hub.portcount = 2;
-    hub.op = &uhci_HubOp;
-    usb_enumerate(&hub);
-    return hub.devcount;
-}
-
-
-/****************************************************************
- * Setup
- ****************************************************************/
-
-// Wait for next USB frame to start - for ensuring safe memory release.
-static void
-uhci_waittick(u16 iobase)
-{
-    barrier();
-    u16 startframe = inw(iobase + USBFRNUM);
-    u32 end = timer_calc(1000 * 5);
-    for (;;) {
-        if (inw(iobase + USBFRNUM) != startframe)
-            break;
-        if (timer_check(end)) {
-            warn_timeout();
-            return;
-        }
-        yield();
-    }
-}
-
-static void
-uhci_free_pipes(struct usb_uhci_s *cntl)
-{
-    dprintf(7, "uhci_free_pipes %p\n", cntl);
-
-    struct uhci_qh *pos = (void*)(cntl->framelist->links[0] & ~UHCI_PTR_BITS);
-    for (;;) {
-        u32 link = pos->link;
-        if (link == UHCI_PTR_TERM)
-            break;
-        struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS);
-        struct uhci_pipe *pipe = container_of(next, struct uhci_pipe, qh);
-        if (pipe->pipe.cntl != &cntl->usb)
-            pos->link = next->link;
-        else
-            pos = next;
-    }
-    uhci_waittick(cntl->iobase);
-    for (;;) {
-        struct usb_pipe *usbpipe = cntl->usb.freelist;
-        if (!usbpipe)
-            break;
-        cntl->usb.freelist = usbpipe->freenext;
-        struct uhci_pipe *pipe = container_of(usbpipe, struct uhci_pipe, pipe);
-        free(pipe);
-    }
-}
-
-static void
-reset_uhci(struct usb_uhci_s *cntl, u16 bdf)
-{
-    // XXX - don't reset if not needed.
-
-    // Reset PIRQ and SMI
-    pci_config_writew(bdf, USBLEGSUP, USBLEGSUP_RWC);
-
-    // Reset the HC
-    outw(USBCMD_HCRESET, cntl->iobase + USBCMD);
-    udelay(5);
-
-    // Disable interrupts and commands (just to be safe).
-    outw(0, cntl->iobase + USBINTR);
-    outw(0, cntl->iobase + USBCMD);
-}
-
-static void
-configure_uhci(void *data)
-{
-    struct usb_uhci_s *cntl = data;
-
-    // Allocate ram for schedule storage
-    struct uhci_td *term_td = malloc_high(sizeof(*term_td));
-    struct uhci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl));
-    struct uhci_pipe *intr_pipe = malloc_high(sizeof(*intr_pipe));
-    struct uhci_pipe *term_pipe = malloc_high(sizeof(*term_pipe));
-    if (!term_td || !fl || !intr_pipe || !term_pipe) {
-        warn_noalloc();
-        goto fail;
-    }
-
-    // Work around for PIIX errata
-    memset(term_td, 0, sizeof(*term_td));
-    term_td->link = UHCI_PTR_TERM;
-    term_td->token = (uhci_explen(0) | (0x7f << TD_TOKEN_DEVADDR_SHIFT)
-                      | USB_PID_IN);
-    memset(term_pipe, 0, sizeof(*term_pipe));
-    term_pipe->qh.element = (u32)term_td;
-    term_pipe->qh.link = UHCI_PTR_TERM;
-    term_pipe->pipe.cntl = &cntl->usb;
-
-    // Set schedule to point to primary intr queue head
-    memset(intr_pipe, 0, sizeof(*intr_pipe));
-    intr_pipe->qh.element = UHCI_PTR_TERM;
-    intr_pipe->qh.link = (u32)&term_pipe->qh | UHCI_PTR_QH;
-    intr_pipe->pipe.cntl = &cntl->usb;
-    int i;
-    for (i=0; i<ARRAY_SIZE(fl->links); i++)
-        fl->links[i] = (u32)&intr_pipe->qh | UHCI_PTR_QH;
-    cntl->framelist = fl;
-    cntl->control_qh = &intr_pipe->qh;
-    barrier();
-
-    // Set the frame length to the default: 1 ms exactly
-    outb(USBSOF_DEFAULT, cntl->iobase + USBSOF);
-
-    // Store the frame list base address
-    outl((u32)fl->links, cntl->iobase + USBFLBASEADD);
-
-    // Set the current frame number
-    outw(0, cntl->iobase + USBFRNUM);
-
-    // Mark as configured and running with a 64-byte max packet.
-    outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->iobase + USBCMD);
-
-    // Find devices
-    int count = check_uhci_ports(cntl);
-    uhci_free_pipes(cntl);
-    if (count)
-        // Success
-        return;
-
-    // No devices found - shutdown and free controller.
-    outw(0, cntl->iobase + USBCMD);
-fail:
-    free(term_td);
-    free(fl);
-    free(intr_pipe);
-    free(term_pipe);
-    free(cntl);
-}
-
-void
-uhci_setup(struct pci_device *pci, int busid)
-{
-    if (! CONFIG_USB_UHCI)
-        return;
-    u16 bdf = pci->bdf;
-    struct usb_uhci_s *cntl = malloc_tmphigh(sizeof(*cntl));
-    if (!cntl) {
-        warn_noalloc();
-        return;
-    }
-    memset(cntl, 0, sizeof(*cntl));
-    cntl->usb.busid = busid;
-    cntl->usb.pci = pci;
-    cntl->usb.type = USB_TYPE_UHCI;
-    cntl->iobase = (pci_config_readl(bdf, PCI_BASE_ADDRESS_4)
-                    & PCI_BASE_ADDRESS_IO_MASK);
-
-    dprintf(1, "UHCI init on dev %02x:%02x.%x (io=%x)\n"
-            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)
-            , pci_bdf_to_fn(bdf), cntl->iobase);
-
-    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
-
-    reset_uhci(cntl, bdf);
-
-    run_thread(configure_uhci, cntl);
-}
-
-
-/****************************************************************
- * End point communication
- ****************************************************************/
-
-static struct usb_pipe *
-uhci_alloc_intr_pipe(struct usbdevice_s *usbdev
-                     , struct usb_endpoint_descriptor *epdesc)
-{
-    struct usb_uhci_s *cntl = container_of(
-        usbdev->hub->cntl, struct usb_uhci_s, usb);
-    int frameexp = usb_getFrameExp(usbdev, epdesc);
-    dprintf(7, "uhci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
-
-    if (frameexp > 10)
-        frameexp = 10;
-    int maxpacket = epdesc->wMaxPacketSize;
-    // Determine number of entries needed for 2 timer ticks.
-    int ms = 1<<frameexp;
-    int count = DIV_ROUND_UP(ticks_to_ms(2), ms);
-    count = ALIGN(count, 2);
-    struct uhci_pipe *pipe = malloc_low(sizeof(*pipe));
-    struct uhci_td *tds = malloc_low(sizeof(*tds) * count);
-    void *data = malloc_low(maxpacket * count);
-    if (!pipe || !tds || !data) {
-        warn_noalloc();
-        goto fail;
-    }
-    memset(pipe, 0, sizeof(*pipe));
-    usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
-    int lowspeed = pipe->pipe.speed;
-    int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7);
-    pipe->qh.element = (u32)tds;
-    pipe->next_td = &tds[0];
-    pipe->iobase = cntl->iobase;
-
-    int toggle = 0;
-    int i;
-    for (i=0; i<count; i++) {
-        tds[i].link = (i==count-1 ? (u32)&tds[0] : (u32)&tds[i+1]);
-        tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
-                         | TD_CTRL_ACTIVE);
-        tds[i].token = (uhci_explen(maxpacket) | toggle
-                        | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
-                        | USB_PID_IN);
-        tds[i].buffer = data + maxpacket * i;
-        toggle ^= TD_TOKEN_TOGGLE;
-    }
-
-    // Add to interrupt schedule.
-    struct uhci_framelist *fl = cntl->framelist;
-    if (frameexp == 0) {
-        // Add to existing interrupt entry.
-        struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS);
-        pipe->qh.link = intr_qh->link;
-        barrier();
-        intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
-        if (cntl->control_qh == intr_qh)
-            cntl->control_qh = &pipe->qh;
-    } else {
-        int startpos = 1<<(frameexp-1);
-        pipe->qh.link = fl->links[startpos];
-        barrier();
-        for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms)
-            fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH;
-    }
-
-    return &pipe->pipe;
-fail:
-    free(pipe);
-    free(tds);
-    free(data);
-    return NULL;
-}
-
-struct usb_pipe *
-uhci_alloc_pipe(struct usbdevice_s *usbdev
-                , struct usb_endpoint_descriptor *epdesc)
-{
-    if (! CONFIG_USB_UHCI)
-        return NULL;
-    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-    if (eptype == USB_ENDPOINT_XFER_INT)
-        return uhci_alloc_intr_pipe(usbdev, epdesc);
-    struct usb_uhci_s *cntl = container_of(
-        usbdev->hub->cntl, struct usb_uhci_s, usb);
-    dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);
-
-    struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
-    if (usbpipe) {
-        // Use previously allocated pipe.
-        usb_desc2pipe(usbpipe, usbdev, epdesc);
-        return usbpipe;
-    }
-
-    // Allocate a new queue head.
-    struct uhci_pipe *pipe;
-    if (eptype == USB_ENDPOINT_XFER_CONTROL)
-        pipe = malloc_tmphigh(sizeof(*pipe));
-    else
-        pipe = malloc_low(sizeof(*pipe));
-    if (!pipe) {
-        warn_noalloc();
-        return NULL;
-    }
-    memset(pipe, 0, sizeof(*pipe));
-    usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
-    pipe->qh.element = UHCI_PTR_TERM;
-    pipe->iobase = cntl->iobase;
-
-    // Add queue head to controller list.
-    struct uhci_qh *control_qh = cntl->control_qh;
-    pipe->qh.link = control_qh->link;
-    barrier();
-    control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
-    if (eptype == USB_ENDPOINT_XFER_CONTROL)
-        cntl->control_qh = &pipe->qh;
-    return &pipe->pipe;
-}
-
-static int
-wait_pipe(struct uhci_pipe *pipe, int timeout)
-{
-    u32 end = timer_calc(timeout);
-    for (;;) {
-        u32 el_link = GET_LOWFLAT(pipe->qh.element);
-        if (el_link & UHCI_PTR_TERM)
-            return 0;
-        if (timer_check(end)) {
-            warn_timeout();
-            u16 iobase = GET_LOWFLAT(pipe->iobase);
-            struct uhci_td *td = (void*)(el_link & ~UHCI_PTR_BITS);
-            dprintf(1, "Timeout on wait_pipe %p (td=%p s=%x c=%x/%x)\n"
-                    , pipe, (void*)el_link, GET_LOWFLAT(td->status)
-                    , inw(iobase + USBCMD)
-                    , inw(iobase + USBSTS));
-            SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM);
-            uhci_waittick(iobase);
-            return -1;
-        }
-        yield();
-    }
-}
-
-static int
-wait_td(struct uhci_td *td)
-{
-    u32 end = timer_calc(5000); // XXX - lookup real time.
-    u32 status;
-    for (;;) {
-        status = td->status;
-        if (!(status & TD_CTRL_ACTIVE))
-            break;
-        if (timer_check(end)) {
-            warn_timeout();
-            return -1;
-        }
-        yield();
-    }
-    if (status & TD_CTRL_ANY_ERROR) {
-        dprintf(1, "wait_td error - status=%x\n", status);
-        return -2;
-    }
-    return 0;
-}
-
-int
-uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
-             , void *data, int datasize)
-{
-    ASSERT32FLAT();
-    if (! CONFIG_USB_UHCI)
-        return -1;
-    dprintf(5, "uhci_control %p\n", p);
-    struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
-
-    int maxpacket = pipe->pipe.maxpacket;
-    int lowspeed = pipe->pipe.speed;
-    int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7);
-
-    // Setup transfer descriptors
-    int count = 2 + DIV_ROUND_UP(datasize, maxpacket);
-    struct uhci_td *tds = malloc_tmphigh(sizeof(*tds) * count);
-    if (!tds) {
-        warn_noalloc();
-        return -1;
-    }
-
-    tds[0].link = (u32)&tds[1] | UHCI_PTR_DEPTH;
-    tds[0].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
-                     | TD_CTRL_ACTIVE);
-    tds[0].token = (uhci_explen(cmdsize) | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
-                    | USB_PID_SETUP);
-    tds[0].buffer = (void*)cmd;
-    int toggle = TD_TOKEN_TOGGLE;
-    int i;
-    for (i=1; i<count-1; i++) {
-        tds[i].link = (u32)&tds[i+1] | UHCI_PTR_DEPTH;
-        tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
-                         | TD_CTRL_ACTIVE);
-        int len = (i == count-2 ? (datasize - (i-1)*maxpacket) : maxpacket);
-        tds[i].token = (uhci_explen(len) | toggle
-                        | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
-                        | (dir ? USB_PID_IN : USB_PID_OUT));
-        tds[i].buffer = data + (i-1) * maxpacket;
-        toggle ^= TD_TOKEN_TOGGLE;
-    }
-    tds[i].link = UHCI_PTR_TERM;
-    tds[i].status = (uhci_maxerr(0) | (lowspeed ? TD_CTRL_LS : 0)
-                     | TD_CTRL_ACTIVE);
-    tds[i].token = (uhci_explen(0) | TD_TOKEN_TOGGLE
-                    | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
-                    | (dir ? USB_PID_OUT : USB_PID_IN));
-    tds[i].buffer = 0;
-
-    // Transfer data
-    barrier();
-    pipe->qh.element = (u32)&tds[0];
-    int ret = wait_pipe(pipe, 500);
-    free(tds);
-    return ret;
-}
-
-#define STACKTDS 4
-#define TDALIGN 16
-
-int
-uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
-{
-    if (! CONFIG_USB_UHCI)
-        return -1;
-    struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
-    dprintf(7, "uhci_send_bulk qh=%p dir=%d data=%p size=%d\n"
-            , &pipe->qh, dir, data, datasize);
-    int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
-    int lowspeed = GET_LOWFLAT(pipe->pipe.speed);
-    int devaddr = (GET_LOWFLAT(pipe->pipe.devaddr)
-                   | (GET_LOWFLAT(pipe->pipe.ep) << 7));
-    int toggle = GET_LOWFLAT(pipe->toggle) ? TD_TOKEN_TOGGLE : 0;
-
-    // Allocate 4 tds on stack (16byte aligned)
-    u8 tdsbuf[sizeof(struct uhci_td) * STACKTDS + TDALIGN - 1];
-    struct uhci_td *tds = (void*)ALIGN((u32)tdsbuf, TDALIGN);
-    memset(tds, 0, sizeof(*tds) * STACKTDS);
-
-    // Enable tds
-    barrier();
-    SET_LOWFLAT(pipe->qh.element, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
-
-    int tdpos = 0;
-    while (datasize) {
-        struct uhci_td *td = &tds[tdpos++ % STACKTDS];
-        int ret = wait_td(td);
-        if (ret)
-            goto fail;
-
-        int transfer = datasize;
-        if (transfer > maxpacket)
-            transfer = maxpacket;
-        struct uhci_td *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
-                                                 , &tds[tdpos % STACKTDS]);
-        td->link = (transfer==datasize ? UHCI_PTR_TERM : (u32)nexttd_fl);
-        td->token = (uhci_explen(transfer) | toggle
-                     | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
-                     | (dir ? USB_PID_IN : USB_PID_OUT));
-        td->buffer = data;
-        barrier();
-        td->status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
-                      | TD_CTRL_ACTIVE);
-        toggle ^= TD_TOKEN_TOGGLE;
-
-        data += transfer;
-        datasize -= transfer;
-    }
-    SET_LOWFLAT(pipe->toggle, !!toggle);
-    return wait_pipe(pipe, 5000);
-fail:
-    dprintf(1, "uhci_send_bulk failed\n");
-    SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM);
-    uhci_waittick(GET_LOWFLAT(pipe->iobase));
-    return -1;
-}
-
-int
-uhci_poll_intr(struct usb_pipe *p, void *data)
-{
-    ASSERT16();
-    if (! CONFIG_USB_UHCI)
-        return -1;
-
-    struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
-    struct uhci_td *td = GET_LOWFLAT(pipe->next_td);
-    u32 status = GET_LOWFLAT(td->status);
-    u32 token = GET_LOWFLAT(td->token);
-    if (status & TD_CTRL_ACTIVE)
-        // No intrs found.
-        return -1;
-    // XXX - check for errors.
-
-    // Copy data.
-    void *tddata = GET_LOWFLAT(td->buffer);
-    memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata)
-               , uhci_expected_length(token));
-
-    // Reenable this td.
-    struct uhci_td *next = (void*)(GET_LOWFLAT(td->link) & ~UHCI_PTR_BITS);
-    SET_LOWFLAT(pipe->next_td, next);
-    barrier();
-    SET_LOWFLAT(td->status, (uhci_maxerr(0) | (status & TD_CTRL_LS)
-                             | TD_CTRL_ACTIVE));
-
-    return 0;
-}
diff --git a/src/usb-uhci.h b/src/usb-uhci.h
deleted file mode 100644 (file)
index b83c487..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifndef __USB_UHCI_H
-#define __USB_UHCI_H
-
-// usb-uhci.c
-void uhci_setup(struct pci_device *pci, int busid);
-struct usbdevice_s;
-struct usb_endpoint_descriptor;
-struct usb_pipe *uhci_alloc_pipe(struct usbdevice_s *usbdev
-                                 , struct usb_endpoint_descriptor *epdesc);
-struct usb_pipe;
-int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
-                 , void *data, int datasize);
-int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
-int uhci_poll_intr(struct usb_pipe *p, void *data);
-
-
-/****************************************************************
- * uhci structs and flags
- ****************************************************************/
-
-/* USB port status and control registers */
-#define USBPORTSC1      16
-#define USBPORTSC2      18
-#define   USBPORTSC_CCS         0x0001  /* Current Connect Status
-                                         * ("device present") */
-#define   USBPORTSC_CSC         0x0002  /* Connect Status Change */
-#define   USBPORTSC_PE          0x0004  /* Port Enable */
-#define   USBPORTSC_PEC         0x0008  /* Port Enable Change */
-#define   USBPORTSC_DPLUS       0x0010  /* D+ high (line status) */
-#define   USBPORTSC_DMINUS      0x0020  /* D- high (line status) */
-#define   USBPORTSC_RD          0x0040  /* Resume Detect */
-#define   USBPORTSC_RES1        0x0080  /* reserved, always 1 */
-#define   USBPORTSC_LSDA        0x0100  /* Low Speed Device Attached */
-#define   USBPORTSC_PR          0x0200  /* Port Reset */
-
-/* Legacy support register */
-#define USBLEGSUP               0xc0
-#define   USBLEGSUP_RWC         0x8f00  /* the R/WC bits */
-
-/* Command register */
-#define USBCMD          0
-#define   USBCMD_RS             0x0001  /* Run/Stop */
-#define   USBCMD_HCRESET        0x0002  /* Host reset */
-#define   USBCMD_GRESET         0x0004  /* Global reset */
-#define   USBCMD_EGSM           0x0008  /* Global Suspend Mode */
-#define   USBCMD_FGR            0x0010  /* Force Global Resume */
-#define   USBCMD_SWDBG          0x0020  /* SW Debug mode */
-#define   USBCMD_CF             0x0040  /* Config Flag (sw only) */
-#define   USBCMD_MAXP           0x0080  /* Max Packet (0 = 32, 1 = 64) */
-
-/* Status register */
-#define USBSTS          2
-#define   USBSTS_USBINT         0x0001  /* Interrupt due to IOC */
-#define   USBSTS_ERROR          0x0002  /* Interrupt due to error */
-#define   USBSTS_RD             0x0004  /* Resume Detect */
-#define   USBSTS_HSE            0x0008  /* Host System Error: PCI problems */
-#define   USBSTS_HCPE           0x0010  /* Host Controller Process Error:
-                                         * the schedule is buggy */
-#define   USBSTS_HCH            0x0020  /* HC Halted */
-
-/* Interrupt enable register */
-#define USBINTR         4
-#define   USBINTR_TIMEOUT       0x0001  /* Timeout/CRC error enable */
-#define   USBINTR_RESUME        0x0002  /* Resume interrupt enable */
-#define   USBINTR_IOC           0x0004  /* Interrupt On Complete enable */
-#define   USBINTR_SP            0x0008  /* Short packet interrupt enable */
-
-#define USBFRNUM        6
-#define USBFLBASEADD    8
-#define USBSOF          12
-#define   USBSOF_DEFAULT        64      /* Frame length is exactly 1 ms */
-
-struct uhci_framelist {
-    u32 links[1024];
-} PACKED;
-
-#define TD_CTRL_SPD             (1 << 29)       /* Short Packet Detect */
-#define TD_CTRL_C_ERR_MASK      (3 << 27)       /* Error Counter bits */
-#define TD_CTRL_C_ERR_SHIFT     27
-#define TD_CTRL_LS              (1 << 26)       /* Low Speed Device */
-#define TD_CTRL_IOS             (1 << 25)       /* Isochronous Select */
-#define TD_CTRL_IOC             (1 << 24)       /* Interrupt on Complete */
-#define TD_CTRL_ACTIVE          (1 << 23)       /* TD Active */
-#define TD_CTRL_STALLED         (1 << 22)       /* TD Stalled */
-#define TD_CTRL_DBUFERR         (1 << 21)       /* Data Buffer Error */
-#define TD_CTRL_BABBLE          (1 << 20)       /* Babble Detected */
-#define TD_CTRL_NAK             (1 << 19)       /* NAK Received */
-#define TD_CTRL_CRCTIMEO        (1 << 18)       /* CRC/Time Out Error */
-#define TD_CTRL_BITSTUFF        (1 << 17)       /* Bit Stuff Error */
-#define TD_CTRL_ACTLEN_MASK     0x7FF   /* actual length, encoded as n - 1 */
-
-#define TD_CTRL_ANY_ERROR       (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
-                                 TD_CTRL_BABBLE | TD_CTRL_CRCTIMEO | \
-                                 TD_CTRL_BITSTUFF)
-#define uhci_maxerr(err)                ((err) << TD_CTRL_C_ERR_SHIFT)
-
-#define TD_TOKEN_DEVADDR_SHIFT  8
-#define TD_TOKEN_TOGGLE_SHIFT   19
-#define TD_TOKEN_TOGGLE         (1 << 19)
-#define TD_TOKEN_EXPLEN_SHIFT   21
-#define TD_TOKEN_EXPLEN_MASK    0x7FF   /* expected length, encoded as n-1 */
-#define TD_TOKEN_PID_MASK       0xFF
-
-#define uhci_explen(len)        ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
-                                        TD_TOKEN_EXPLEN_SHIFT)
-
-#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
-                                        1) & TD_TOKEN_EXPLEN_MASK)
-
-struct uhci_td {
-    u32 link;
-    u32 status;
-    u32 token;
-    void *buffer;
-} PACKED;
-
-struct uhci_qh {
-    u32 link;
-    u32 element;
-} PACKED;
-
-#define UHCI_PTR_BITS           0x000F
-#define UHCI_PTR_TERM           0x0001
-#define UHCI_PTR_QH             0x0002
-#define UHCI_PTR_DEPTH          0x0004
-#define UHCI_PTR_BREADTH        0x0000
-
-#endif // usb-uhci.h
diff --git a/src/usb.c b/src/usb.c
deleted file mode 100644 (file)
index 42541ff..0000000
--- a/src/usb.c
+++ /dev/null
@@ -1,461 +0,0 @@
-// Main code for handling USB controllers and devices.
-//
-// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // foreachpci
-#include "config.h" // CONFIG_*
-#include "pci_regs.h" // PCI_CLASS_REVISION
-#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI
-#include "usb-uhci.h" // uhci_setup
-#include "usb-ohci.h" // ohci_setup
-#include "usb-ehci.h" // ehci_setup
-#include "usb-hid.h" // usb_keyboard_setup
-#include "usb-hub.h" // usb_hub_setup
-#include "usb-msc.h" // usb_msc_setup
-#include "usb-uas.h" // usb_uas_setup
-#include "usb.h" // struct usb_s
-#include "biosvar.h" // GET_GLOBAL
-
-
-/****************************************************************
- * Controller function wrappers
- ****************************************************************/
-
-// Allocate an async pipe (control or bulk).
-struct usb_pipe *
-usb_alloc_pipe(struct usbdevice_s *usbdev
-               , struct usb_endpoint_descriptor *epdesc)
-{
-    switch (usbdev->hub->cntl->type) {
-    default:
-    case USB_TYPE_UHCI:
-        return uhci_alloc_pipe(usbdev, epdesc);
-    case USB_TYPE_OHCI:
-        return ohci_alloc_pipe(usbdev, epdesc);
-    case USB_TYPE_EHCI:
-        return ehci_alloc_pipe(usbdev, epdesc);
-    }
-}
-
-// Send a message on a control pipe using the default control descriptor.
-static int
-send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize
-             , void *data, int datasize)
-{
-    ASSERT32FLAT();
-    switch (pipe->type) {
-    default:
-    case USB_TYPE_UHCI:
-        return uhci_control(pipe, dir, cmd, cmdsize, data, datasize);
-    case USB_TYPE_OHCI:
-        return ohci_control(pipe, dir, cmd, cmdsize, data, datasize);
-    case USB_TYPE_EHCI:
-        return ehci_control(pipe, dir, cmd, cmdsize, data, datasize);
-    }
-}
-
-int
-usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize)
-{
-    switch (GET_LOWFLAT(pipe_fl->type)) {
-    default:
-    case USB_TYPE_UHCI:
-        return uhci_send_bulk(pipe_fl, dir, data, datasize);
-    case USB_TYPE_OHCI:
-        return ohci_send_bulk(pipe_fl, dir, data, datasize);
-    case USB_TYPE_EHCI:
-        return ehci_send_bulk(pipe_fl, dir, data, datasize);
-    }
-}
-
-int
-usb_poll_intr(struct usb_pipe *pipe_fl, void *data)
-{
-    switch (GET_LOWFLAT(pipe_fl->type)) {
-    default:
-    case USB_TYPE_UHCI:
-        return uhci_poll_intr(pipe_fl, data);
-    case USB_TYPE_OHCI:
-        return ohci_poll_intr(pipe_fl, data);
-    case USB_TYPE_EHCI:
-        return ehci_poll_intr(pipe_fl, data);
-    }
-}
-
-
-/****************************************************************
- * Helper functions
- ****************************************************************/
-
-// Send a message to the default control pipe of a device.
-int
-send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req
-                     , void *data)
-{
-    return send_control(pipe, req->bRequestType & USB_DIR_IN
-                        , req, sizeof(*req), data, req->wLength);
-}
-
-// Free an allocated control or bulk pipe.
-void
-free_pipe(struct usb_pipe *pipe)
-{
-    ASSERT32FLAT();
-    if (!pipe)
-        return;
-    // Add to controller's free list.
-    struct usb_s *cntl = pipe->cntl;
-    pipe->freenext = cntl->freelist;
-    cntl->freelist = pipe;
-}
-
-// Check for an available pipe on the freelist.
-struct usb_pipe *
-usb_getFreePipe(struct usb_s *cntl, u8 eptype)
-{
-    struct usb_pipe **pfree = &cntl->freelist;
-    for (;;) {
-        struct usb_pipe *pipe = *pfree;
-        if (!pipe)
-            return NULL;
-        if (pipe->eptype == eptype) {
-            *pfree = pipe->freenext;
-            return pipe;
-        }
-        pfree = &pipe->freenext;
-    }
-}
-
-// Fill "pipe" endpoint info from an endpoint descriptor.
-void
-usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev
-              , struct usb_endpoint_descriptor *epdesc)
-{
-    pipe->cntl = usbdev->hub->cntl;
-    pipe->type = usbdev->hub->cntl->type;
-    pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-    pipe->devaddr = usbdev->devaddr;
-    pipe->speed = usbdev->speed;
-    pipe->maxpacket = epdesc->wMaxPacketSize;
-    pipe->eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-}
-
-// Find the exponential period of the requested interrupt end point.
-int
-usb_getFrameExp(struct usbdevice_s *usbdev
-                , struct usb_endpoint_descriptor *epdesc)
-{
-    int period = epdesc->bInterval;
-    if (usbdev->speed != USB_HIGHSPEED)
-        return (period <= 0) ? 0 : __fls(period);
-    return (period <= 4) ? 0 : period - 4;
-}
-
-// Find the first endpoing of a given type in an interface description.
-struct usb_endpoint_descriptor *
-findEndPointDesc(struct usbdevice_s *usbdev, int type, int dir)
-{
-    struct usb_endpoint_descriptor *epdesc = (void*)&usbdev->iface[1];
-    for (;;) {
-        if ((void*)epdesc >= (void*)usbdev->iface + usbdev->imax
-            || epdesc->bDescriptorType == USB_DT_INTERFACE) {
-            return NULL;
-        }
-        if (epdesc->bDescriptorType == USB_DT_ENDPOINT
-            && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir
-            && (epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == type)
-            return epdesc;
-        epdesc = (void*)epdesc + epdesc->bLength;
-    }
-}
-
-// Get the first 8 bytes of the device descriptor.
-static int
-get_device_info8(struct usb_pipe *pipe, struct usb_device_descriptor *dinfo)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
-    req.bRequest = USB_REQ_GET_DESCRIPTOR;
-    req.wValue = USB_DT_DEVICE<<8;
-    req.wIndex = 0;
-    req.wLength = 8;
-    return send_default_control(pipe, &req, dinfo);
-}
-
-static struct usb_config_descriptor *
-get_device_config(struct usb_pipe *pipe)
-{
-    struct usb_config_descriptor cfg;
-
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
-    req.bRequest = USB_REQ_GET_DESCRIPTOR;
-    req.wValue = USB_DT_CONFIG<<8;
-    req.wIndex = 0;
-    req.wLength = sizeof(cfg);
-    int ret = send_default_control(pipe, &req, &cfg);
-    if (ret)
-        return NULL;
-
-    void *config = malloc_tmphigh(cfg.wTotalLength);
-    if (!config)
-        return NULL;
-    req.wLength = cfg.wTotalLength;
-    ret = send_default_control(pipe, &req, config);
-    if (ret)
-        return NULL;
-    //hexdump(config, cfg.wTotalLength);
-    return config;
-}
-
-static int
-set_configuration(struct usb_pipe *pipe, u16 val)
-{
-    struct usb_ctrlrequest req;
-    req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
-    req.bRequest = USB_REQ_SET_CONFIGURATION;
-    req.wValue = val;
-    req.wIndex = 0;
-    req.wLength = 0;
-    return send_default_control(pipe, &req, NULL);
-}
-
-
-/****************************************************************
- * Initialization and enumeration
- ****************************************************************/
-
-// 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;
-
-    // Create a pipe for the default address.
-    struct usb_endpoint_descriptor epdesc = {
-        .wMaxPacketSize = 8,
-        .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
-    };
-    usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc);
-    if (!usbdev->defpipe)
-        return -1;
-
-    msleep(USB_TIME_RSTRCY);
-
-    // 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 = send_default_control(usbdev->defpipe, &req, NULL);
-    free_pipe(usbdev->defpipe);
-    if (ret)
-        return -1;
-
-    msleep(USB_TIME_SETADDR_RECOVERY);
-
-    cntl->maxaddr++;
-    usbdev->devaddr = cntl->maxaddr;
-    usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc);
-    if (!usbdev->defpipe)
-        return -1;
-    return 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;
-    dprintf(3, "device rev=%04x cls=%02x sub=%02x proto=%02x size=%02x\n"
-            , dinfo.bcdUSB, dinfo.bDeviceClass, dinfo.bDeviceSubClass
-            , dinfo.bDeviceProtocol, dinfo.bMaxPacketSize0);
-    if (dinfo.bMaxPacketSize0 < 8 || dinfo.bMaxPacketSize0 > 64)
-        return 0;
-    free_pipe(usbdev->defpipe);
-    struct usb_endpoint_descriptor epdesc = {
-        .wMaxPacketSize = dinfo.bMaxPacketSize0,
-        .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
-    };
-    usbdev->defpipe = usb_alloc_pipe(usbdev, &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;
-}
-
-static void
-usb_hub_port_setup(void *data)
-{
-    struct usbdevice_s *usbdev = data;
-    struct usbhub_s *hub = usbdev->hub;
-    u32 port = usbdev->port;
-
-    // Detect if device present (and possibly start reset)
-    int ret = hub->op->detect(hub, port);
-    if (ret)
-        // No device present
-        goto done;
-
-    // Reset port and determine device speed
-    mutex_lock(&hub->cntl->resetlock);
-    ret = hub->op->reset(hub, port);
-    if (ret < 0)
-        // Reset failed
-        goto resetfail;
-    usbdev->speed = ret;
-
-    // Set address of port
-    ret = usb_set_address(usbdev);
-    if (ret) {
-        hub->op->disconnect(hub, port);
-        goto resetfail;
-    }
-    mutex_unlock(&hub->cntl->resetlock);
-
-    // Configure the device
-    int count = configure_usb_device(usbdev);
-    free_pipe(usbdev->defpipe);
-    if (!count)
-        hub->op->disconnect(hub, port);
-    hub->devcount += count;
-done:
-    hub->threads--;
-    free(usbdev);
-    return;
-
-resetfail:
-    mutex_unlock(&hub->cntl->resetlock);
-    goto done;
-}
-
-void
-usb_enumerate(struct usbhub_s *hub)
-{
-    u32 portcount = hub->portcount;
-    hub->threads = portcount;
-
-    // Launch a thread for every port.
-    int i;
-    for (i=0; i<portcount; i++) {
-        struct usbdevice_s *usbdev = malloc_tmphigh(sizeof(*usbdev));
-        if (!usbdev) {
-            warn_noalloc();
-            continue;
-        }
-        memset(usbdev, 0, sizeof(*usbdev));
-        usbdev->hub = hub;
-        usbdev->port = i;
-        run_thread(usb_hub_port_setup, usbdev);
-    }
-
-    // Wait for threads to complete.
-    while (hub->threads)
-        yield();
-}
-
-void
-usb_setup(void)
-{
-    ASSERT32FLAT();
-    if (! CONFIG_USB)
-        return;
-
-    dprintf(3, "init usb\n");
-
-    // Look for USB controllers
-    int count = 0;
-    struct pci_device *pci, *ehcipci = NULL;
-    foreachpci(pci) {
-        if (pci->class != PCI_CLASS_SERIAL_USB)
-            continue;
-
-        if (!ehcipci || pci->bdf >= ehcipci->bdf) {
-            // Check to see if this device has an ehci controller
-            int found = 0;
-            ehcipci = pci;
-            for (;;) {
-                if (pci_classprog(ehcipci) == PCI_CLASS_SERIAL_USB_EHCI) {
-                    // Found an ehci controller.
-                    int ret = ehci_setup(ehcipci, count++, pci);
-                    if (ret)
-                        // Error
-                        break;
-                    count += found;
-                    pci = ehcipci;
-                    break;
-                }
-                if (ehcipci->class == PCI_CLASS_SERIAL_USB)
-                    found++;
-                ehcipci = container_of_or_null(
-                    ehcipci->node.next, struct pci_device, node);
-                if (!ehcipci || (pci_bdf_to_busdev(ehcipci->bdf)
-                                 != pci_bdf_to_busdev(pci->bdf)))
-                    // No ehci controller found.
-                    break;
-            }
-        }
-
-        if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI)
-            uhci_setup(pci, count++);
-        else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI)
-            ohci_setup(pci, count++);
-    }
-}
diff --git a/src/usb.h b/src/usb.h
deleted file mode 100644 (file)
index a43e829..0000000
--- a/src/usb.h
+++ /dev/null
@@ -1,241 +0,0 @@
-// USB functions and data.
-#ifndef __USB_H
-#define __USB_H
-
-#include "util.h" // struct mutex_s
-
-// Information on a USB end point.
-struct usb_pipe {
-    union {
-        struct usb_s *cntl;
-        struct usb_pipe *freenext;
-    };
-    u8 type;
-    u8 ep;
-    u8 devaddr;
-    u8 speed;
-    u16 maxpacket;
-    u8 eptype;
-};
-
-// Common information for usb devices.
-struct usbdevice_s {
-    struct usbhub_s *hub;
-    struct usb_pipe *defpipe;
-    u32 port;
-    struct usb_config_descriptor *config;
-    struct usb_interface_descriptor *iface;
-    int imax;
-    u8 speed;
-    u8 devaddr;
-};
-
-// Common information for usb controllers.
-struct usb_s {
-    struct usb_pipe *freelist;
-    struct mutex_s resetlock;
-    struct pci_device *pci;
-    int busid;
-    u8 type;
-    u8 maxaddr;
-};
-
-// Information for enumerating USB hubs
-struct usbhub_s {
-    struct usbhub_op_s *op;
-    struct usbdevice_s *usbdev;
-    struct usb_s *cntl;
-    struct mutex_s lock;
-    u32 powerwait;
-    u32 port;
-    u32 threads;
-    u32 portcount;
-    u32 devcount;
-};
-
-// Hub callback (32bit) info
-struct usbhub_op_s {
-    int (*detect)(struct usbhub_s *hub, u32 port);
-    int (*reset)(struct usbhub_s *hub, u32 port);
-    void (*disconnect)(struct usbhub_s *hub, u32 port);
-};
-
-#define USB_TYPE_UHCI 1
-#define USB_TYPE_OHCI 2
-#define USB_TYPE_EHCI 3
-
-#define USB_FULLSPEED 0
-#define USB_LOWSPEED  1
-#define USB_HIGHSPEED 2
-
-#define USB_MAXADDR 127
-
-
-/****************************************************************
- * usb structs and flags
- ****************************************************************/
-
-// USB mandated timings (in ms)
-#define USB_TIME_SIGATT 100
-#define USB_TIME_ATTDB  100
-#define USB_TIME_DRST   10
-#define USB_TIME_DRSTR  50
-#define USB_TIME_RSTRCY 10
-
-#define USB_TIME_SETADDR_RECOVERY 2
-
-#define USB_PID_OUT                     0xe1
-#define USB_PID_IN                      0x69
-#define USB_PID_SETUP                   0x2d
-
-#define USB_DIR_OUT                     0               /* to device */
-#define USB_DIR_IN                      0x80            /* to host */
-
-#define USB_TYPE_MASK                   (0x03 << 5)
-#define USB_TYPE_STANDARD               (0x00 << 5)
-#define USB_TYPE_CLASS                  (0x01 << 5)
-#define USB_TYPE_VENDOR                 (0x02 << 5)
-#define USB_TYPE_RESERVED               (0x03 << 5)
-
-#define USB_RECIP_MASK                  0x1f
-#define USB_RECIP_DEVICE                0x00
-#define USB_RECIP_INTERFACE             0x01
-#define USB_RECIP_ENDPOINT              0x02
-#define USB_RECIP_OTHER                 0x03
-
-#define USB_REQ_GET_STATUS              0x00
-#define USB_REQ_CLEAR_FEATURE           0x01
-#define USB_REQ_SET_FEATURE             0x03
-#define USB_REQ_SET_ADDRESS             0x05
-#define USB_REQ_GET_DESCRIPTOR          0x06
-#define USB_REQ_SET_DESCRIPTOR          0x07
-#define USB_REQ_GET_CONFIGURATION       0x08
-#define USB_REQ_SET_CONFIGURATION       0x09
-#define USB_REQ_GET_INTERFACE           0x0A
-#define USB_REQ_SET_INTERFACE           0x0B
-#define USB_REQ_SYNCH_FRAME             0x0C
-
-struct usb_ctrlrequest {
-    u8 bRequestType;
-    u8 bRequest;
-    u16 wValue;
-    u16 wIndex;
-    u16 wLength;
-} PACKED;
-
-#define USB_DT_DEVICE                   0x01
-#define USB_DT_CONFIG                   0x02
-#define USB_DT_STRING                   0x03
-#define USB_DT_INTERFACE                0x04
-#define USB_DT_ENDPOINT                 0x05
-#define USB_DT_DEVICE_QUALIFIER         0x06
-#define USB_DT_OTHER_SPEED_CONFIG       0x07
-
-struct usb_device_descriptor {
-    u8  bLength;
-    u8  bDescriptorType;
-
-    u16 bcdUSB;
-    u8  bDeviceClass;
-    u8  bDeviceSubClass;
-    u8  bDeviceProtocol;
-    u8  bMaxPacketSize0;
-    u16 idVendor;
-    u16 idProduct;
-    u16 bcdDevice;
-    u8  iManufacturer;
-    u8  iProduct;
-    u8  iSerialNumber;
-    u8  bNumConfigurations;
-} PACKED;
-
-#define USB_CLASS_PER_INTERFACE         0       /* for DeviceClass */
-#define USB_CLASS_AUDIO                 1
-#define USB_CLASS_COMM                  2
-#define USB_CLASS_HID                   3
-#define USB_CLASS_PHYSICAL              5
-#define USB_CLASS_STILL_IMAGE           6
-#define USB_CLASS_PRINTER               7
-#define USB_CLASS_MASS_STORAGE          8
-#define USB_CLASS_HUB                   9
-
-struct usb_config_descriptor {
-    u8  bLength;
-    u8  bDescriptorType;
-
-    u16 wTotalLength;
-    u8  bNumInterfaces;
-    u8  bConfigurationValue;
-    u8  iConfiguration;
-    u8  bmAttributes;
-    u8  bMaxPower;
-} PACKED;
-
-struct usb_interface_descriptor {
-    u8  bLength;
-    u8  bDescriptorType;
-
-    u8  bInterfaceNumber;
-    u8  bAlternateSetting;
-    u8  bNumEndpoints;
-    u8  bInterfaceClass;
-    u8  bInterfaceSubClass;
-    u8  bInterfaceProtocol;
-    u8  iInterface;
-} PACKED;
-
-struct usb_endpoint_descriptor {
-    u8  bLength;
-    u8  bDescriptorType;
-
-    u8  bEndpointAddress;
-    u8  bmAttributes;
-    u16 wMaxPacketSize;
-    u8  bInterval;
-} PACKED;
-
-#define USB_ENDPOINT_NUMBER_MASK        0x0f    /* in bEndpointAddress */
-#define USB_ENDPOINT_DIR_MASK           0x80
-
-#define USB_ENDPOINT_XFERTYPE_MASK      0x03    /* in bmAttributes */
-#define USB_ENDPOINT_XFER_CONTROL       0
-#define USB_ENDPOINT_XFER_ISOC          1
-#define USB_ENDPOINT_XFER_BULK          2
-#define USB_ENDPOINT_XFER_INT           3
-#define USB_ENDPOINT_MAX_ADJUSTABLE     0x80
-
-
-/****************************************************************
- * usb mass storage flags
- ****************************************************************/
-
-#define US_SC_ATAPI_8020   0x02
-#define US_SC_ATAPI_8070   0x05
-#define US_SC_SCSI         0x06
-
-#define US_PR_BULK         0x50  /* bulk-only transport */
-#define US_PR_UAS          0x62  /* usb attached scsi   */
-
-/****************************************************************
- * function defs
- ****************************************************************/
-
-// usb.c
-struct usb_pipe *usb_alloc_pipe(struct usbdevice_s *usbdev
-                                , struct usb_endpoint_descriptor *epdesc);
-int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize);
-int usb_poll_intr(struct usb_pipe *pipe, void *data);
-int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req
-                         , void *data);
-void free_pipe(struct usb_pipe *pipe);
-struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype);
-void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev
-                   , struct usb_endpoint_descriptor *epdesc);
-int usb_getFrameExp(struct usbdevice_s *usbdev
-                    , struct usb_endpoint_descriptor *epdesc);
-struct usb_endpoint_descriptor *findEndPointDesc(struct usbdevice_s *usbdev
-                                                 , int type, int dir);
-void usb_enumerate(struct usbhub_s *hub);
-void usb_setup(void);
-
-#endif // usb.h
index 6944cfb64225a777fe2f5dbdae0ea9788124506a..9b1b7741f6b3c64a22b9e55214f75b37421965e1 100644 (file)
@@ -281,7 +281,7 @@ void handle_1586(struct bregs *regs);
 void useRTC(void);
 void releaseRTC(void);
 
-// timer.c
+// hw/timer.c
 void timer_setup(void);
 void pmtimer_setup(u16 ioport);
 u32 timer_calc(u32 msecs);
index c9a444886545ba5b69d36b6c5a57a2b6eed241bb..83d5a74bcfdfe1a5e711d20fe5b0aaf04ee048df 100644 (file)
@@ -6,9 +6,9 @@
 
 #include "bregs.h" // set_code_invalid
 #include "biosvar.h" // GET_GLOBAL
-#include "pci.h" // pci_find_device
-#include "pci_regs.h" // PCI_VENDOR_ID
-#include "pci_ids.h" // PCI_VENDOR_ID_VIA
+#include "hw/pci.h" // pci_find_device
+#include "hw/pci_regs.h" // PCI_VENDOR_ID
+#include "hw/pci_ids.h" // PCI_VENDOR_ID_VIA
 #include "util.h" // handle_155f
 #include "config.h" // CONFIG_*
 
diff --git a/src/virtio-blk.c b/src/virtio-blk.c
deleted file mode 100644 (file)
index 6c0cd74..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-// Virtio block boot support.
-//
-// Copyright (C) 2010 Red Hat Inc.
-//
-// Authors:
-//  Gleb Natapov <gnatapov@redhat.com>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // foreachpci
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // GET_GLOBAL
-#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK
-#include "pci_regs.h" // PCI_VENDOR_ID
-#include "boot.h" // boot_add_hd
-#include "virtio-pci.h"
-#include "virtio-ring.h"
-#include "virtio-blk.h"
-#include "disk.h"
-
-struct virtiodrive_s {
-    struct drive_s drive;
-    struct vring_virtqueue *vq;
-    u16 ioaddr;
-};
-
-static int
-virtio_blk_op(struct disk_op_s *op, int write)
-{
-    struct virtiodrive_s *vdrive_g =
-        container_of(op->drive_g, struct virtiodrive_s, drive);
-    struct vring_virtqueue *vq = GET_GLOBAL(vdrive_g->vq);
-    struct virtio_blk_outhdr hdr = {
-        .type = write ? VIRTIO_BLK_T_OUT : VIRTIO_BLK_T_IN,
-        .ioprio = 0,
-        .sector = op->lba,
-    };
-    u8 status = VIRTIO_BLK_S_UNSUPP;
-    struct vring_list sg[] = {
-        {
-            .addr       = MAKE_FLATPTR(GET_SEG(SS), &hdr),
-            .length     = sizeof(hdr),
-        },
-        {
-            .addr       = op->buf_fl,
-            .length     = GET_GLOBAL(vdrive_g->drive.blksize) * op->count,
-        },
-        {
-            .addr       = MAKE_FLATPTR(GET_SEG(SS), &status),
-            .length     = sizeof(status),
-        },
-    };
-
-    /* Add to virtqueue and kick host */
-    if (write)
-        vring_add_buf(vq, sg, 2, 1, 0, 0);
-    else
-        vring_add_buf(vq, sg, 1, 2, 0, 0);
-    vring_kick(GET_GLOBAL(vdrive_g->ioaddr), vq, 1);
-
-    /* Wait for reply */
-    while (!vring_more_used(vq))
-        usleep(5);
-
-    /* Reclaim virtqueue element */
-    vring_get_buf(vq, NULL);
-
-    /* Clear interrupt status register.  Avoid leaving interrupts stuck if
-     * VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised.
-     */
-    vp_get_isr(GET_GLOBAL(vdrive_g->ioaddr));
-
-    return status == VIRTIO_BLK_S_OK ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
-}
-
-int
-process_virtio_blk_op(struct disk_op_s *op)
-{
-    if (! CONFIG_VIRTIO_BLK)
-        return 0;
-    switch (op->command) {
-    case CMD_READ:
-        return virtio_blk_op(op, 0);
-    case CMD_WRITE:
-        return virtio_blk_op(op, 1);
-    case CMD_FORMAT:
-    case CMD_RESET:
-    case CMD_ISREADY:
-    case CMD_VERIFY:
-    case CMD_SEEK:
-        return DISK_RET_SUCCESS;
-    default:
-        op->count = 0;
-        return DISK_RET_EPARAM;
-    }
-}
-
-static void
-init_virtio_blk(struct pci_device *pci)
-{
-    u16 bdf = pci->bdf;
-    dprintf(1, "found virtio-blk at %x:%x\n", pci_bdf_to_bus(bdf),
-            pci_bdf_to_dev(bdf));
-    struct virtiodrive_s *vdrive_g = malloc_fseg(sizeof(*vdrive_g));
-    if (!vdrive_g) {
-        warn_noalloc();
-        return;
-    }
-    memset(vdrive_g, 0, sizeof(*vdrive_g));
-    vdrive_g->drive.type = DTYPE_VIRTIO_BLK;
-    vdrive_g->drive.cntl_id = bdf;
-
-    u16 ioaddr = vp_init_simple(bdf);
-    vdrive_g->ioaddr = ioaddr;
-    if (vp_find_vq(ioaddr, 0, &vdrive_g->vq) < 0 ) {
-        dprintf(1, "fail to find vq for virtio-blk %x:%x\n",
-                pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
-        goto fail;
-    }
-
-    struct virtio_blk_config cfg;
-    vp_get(ioaddr, 0, &cfg, sizeof(cfg));
-
-    u32 f = vp_get_features(ioaddr);
-    vdrive_g->drive.blksize = (f & (1 << VIRTIO_BLK_F_BLK_SIZE)) ?
-        cfg.blk_size : DISK_SECTOR_SIZE;
-
-    vdrive_g->drive.sectors = cfg.capacity;
-    dprintf(3, "virtio-blk %x:%x blksize=%d sectors=%u\n",
-            pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
-            vdrive_g->drive.blksize, (u32)vdrive_g->drive.sectors);
-
-    if (vdrive_g->drive.blksize != DISK_SECTOR_SIZE) {
-        dprintf(1, "virtio-blk %x:%x block size %d is unsupported\n",
-                pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
-                vdrive_g->drive.blksize);
-        goto fail;
-    }
-
-    vdrive_g->drive.pchs.cylinders = cfg.cylinders;
-    vdrive_g->drive.pchs.heads = cfg.heads;
-    vdrive_g->drive.pchs.spt = cfg.sectors;
-    char *desc = znprintf(MAXDESCSIZE, "Virtio disk PCI:%x:%x",
-                          pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
-
-    boot_add_hd(&vdrive_g->drive, desc, bootprio_find_pci_device(pci));
-
-    vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
-                  VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
-    return;
-
-fail:
-    free(vdrive_g->vq);
-    free(vdrive_g);
-}
-
-void
-virtio_blk_setup(void)
-{
-    ASSERT32FLAT();
-    if (! CONFIG_VIRTIO_BLK)
-        return;
-
-    dprintf(3, "init virtio-blk\n");
-
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci->vendor != PCI_VENDOR_ID_REDHAT_QUMRANET
-            || pci->device != PCI_DEVICE_ID_VIRTIO_BLK)
-            continue;
-        init_virtio_blk(pci);
-    }
-}
diff --git a/src/virtio-blk.h b/src/virtio-blk.h
deleted file mode 100644 (file)
index b233c74..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _VIRTIO_BLK_H
-#define _VIRTIO_BLK_H
-
-struct virtio_blk_config
-{
-    u64 capacity;
-    u32 size_max;
-    u32 seg_max;
-    u16 cylinders;
-    u8 heads;
-    u8 sectors;
-    u32 blk_size;
-    u8 physical_block_exp;
-    u8 alignment_offset;
-    u16 min_io_size;
-    u32 opt_io_size;
-} __attribute__((packed));
-
-#define VIRTIO_BLK_F_BLK_SIZE 6
-
-/* These two define direction. */
-#define VIRTIO_BLK_T_IN         0
-#define VIRTIO_BLK_T_OUT        1
-
-/* This is the first element of the read scatter-gather list. */
-struct virtio_blk_outhdr {
-    /* VIRTIO_BLK_T* */
-    u32 type;
-    /* io priority. */
-    u32 ioprio;
-    /* Sector (ie. 512 byte offset) */
-    u64 sector;
-};
-
-#define VIRTIO_BLK_S_OK         0
-#define VIRTIO_BLK_S_IOERR      1
-#define VIRTIO_BLK_S_UNSUPP     2
-
-struct disk_op_s;
-int process_virtio_blk_op(struct disk_op_s *op);
-void virtio_blk_setup(void);
-
-#endif /* _VIRTIO_BLK_H */
diff --git a/src/virtio-pci.c b/src/virtio-pci.c
deleted file mode 100644 (file)
index 4b9ad0a..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* virtio-pci.c - pci interface for virtio interface
- *
- * (c) Copyright 2008 Bull S.A.S.
- *
- *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
- *
- * some parts from Linux Virtio PCI driver
- *
- *  Copyright IBM Corp. 2007
- *  Authors: Anthony Liguori  <aliguori@us.ibm.com>
- *
- *  Adopted for Seabios: Gleb Natapov <gleb@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPLv3
- * See the COPYING file in the top-level directory.
- */
-
-#include "virtio-ring.h"
-#include "virtio-pci.h"
-#include "config.h" // CONFIG_DEBUG_LEVEL
-#include "util.h" // dprintf
-#include "pci.h" // pci_config_readl
-#include "pci_regs.h" // PCI_BASE_ADDRESS_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;
-}
-
-u16 vp_init_simple(u16 bdf)
-{
-    u16 ioaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) &
-        PCI_BASE_ADDRESS_IO_MASK;
-
-    vp_reset(ioaddr);
-    vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
-                  VIRTIO_CONFIG_S_DRIVER );
-    return ioaddr;
-}
diff --git a/src/virtio-pci.h b/src/virtio-pci.h
deleted file mode 100644 (file)
index e1d972d..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef _VIRTIO_PCI_H
-#define _VIRTIO_PCI_H
-
-#include "ioport.h" // inl
-
-/* A 32-bit r/o bitmask of the features supported by the host */
-#define VIRTIO_PCI_HOST_FEATURES        0
-
-/* A 32-bit r/w bitmask of features activated by the guest */
-#define VIRTIO_PCI_GUEST_FEATURES       4
-
-/* A 32-bit r/w PFN for the currently selected queue */
-#define VIRTIO_PCI_QUEUE_PFN            8
-
-/* A 16-bit r/o queue size for the currently selected queue */
-#define VIRTIO_PCI_QUEUE_NUM            12
-
-/* A 16-bit r/w queue selector */
-#define VIRTIO_PCI_QUEUE_SEL            14
-
-/* A 16-bit r/w queue notifier */
-#define VIRTIO_PCI_QUEUE_NOTIFY         16
-
-/* An 8-bit device status register.  */
-#define VIRTIO_PCI_STATUS               18
-
-/* An 8-bit r/o interrupt status register.  Reading the value will return the
- * current contents of the ISR and will also clear it.  This is effectively
- * a read-and-acknowledge. */
-#define VIRTIO_PCI_ISR                  19
-
-/* The bit of the ISR which indicates a device configuration change. */
-#define VIRTIO_PCI_ISR_CONFIG           0x2
-
-/* The remaining space is defined by each driver as the per-driver
- * configuration space */
-#define VIRTIO_PCI_CONFIG               20
-
-/* Virtio ABI version, this must match exactly */
-#define VIRTIO_PCI_ABI_VERSION          0
-
-static inline u32 vp_get_features(unsigned int ioaddr)
-{
-   return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES);
-}
-
-static inline void vp_set_features(unsigned int ioaddr, u32 features)
-{
-        outl(features, ioaddr + VIRTIO_PCI_GUEST_FEATURES);
-}
-
-static inline void vp_get(unsigned int ioaddr, unsigned offset,
-                     void *buf, unsigned len)
-{
-   u8 *ptr = buf;
-   unsigned i;
-
-   for (i = 0; i < len; i++)
-           ptr[i] = inb(ioaddr + VIRTIO_PCI_CONFIG + offset + i);
-}
-
-static inline u8 vp_get_status(unsigned int ioaddr)
-{
-   return inb(ioaddr + VIRTIO_PCI_STATUS);
-}
-
-static inline void vp_set_status(unsigned int ioaddr, u8 status)
-{
-   if (status == 0)        /* reset */
-           return;
-   outb(status, ioaddr + VIRTIO_PCI_STATUS);
-}
-
-static inline u8 vp_get_isr(unsigned int ioaddr)
-{
-   return inb(ioaddr + VIRTIO_PCI_ISR);
-}
-
-static inline void vp_reset(unsigned int ioaddr)
-{
-   outb(0, ioaddr + VIRTIO_PCI_STATUS);
-   (void)inb(ioaddr + VIRTIO_PCI_ISR);
-}
-
-static inline void vp_notify(unsigned int ioaddr, int queue_index)
-{
-   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
-}
-
-static inline void vp_del_vq(unsigned int ioaddr, int queue_index)
-{
-   /* select the queue */
-
-   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
-
-   /* deactivate the queue */
-
-   outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN);
-}
-
-struct vring_virtqueue;
-u16 vp_init_simple(u16 bdf);
-int vp_find_vq(unsigned int ioaddr, int queue_index,
-               struct vring_virtqueue **p_vq);
-#endif /* _VIRTIO_PCI_H_ */
diff --git a/src/virtio-ring.c b/src/virtio-ring.c
deleted file mode 100644 (file)
index bddb090..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/* virtio-pci.c - virtio ring management
- *
- * (c) Copyright 2008 Bull S.A.S.
- *
- *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
- *
- *  some parts from Linux Virtio Ring
- *
- *  Copyright Rusty Russell IBM Corporation 2007
- *
- *  Adopted for Seabios: Gleb Natapov <gleb@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPLv3
- * See the COPYING file in the top-level directory.
- *
- *
- */
-
-#include "virtio-ring.h"
-#include "virtio-pci.h"
-#include "biosvar.h" // GET_GLOBAL
-#include "util.h" // dprintf
-
-#define BUG() do {                                                      \
-            panic("BUG: failure at %d/%s()!\n", __LINE__, __func__);    \
-        } while (0)
-#define BUG_ON(condition) do { if (condition) BUG(); } while (0)
-
-/*
- * vring_more_used
- *
- * is there some used buffers ?
- *
- */
-
-int vring_more_used(struct vring_virtqueue *vq)
-{
-    struct vring_used *used = GET_LOWFLAT(vq->vring.used);
-    int more = GET_LOWFLAT(vq->last_used_idx) != GET_LOWFLAT(used->idx);
-    /* Make sure ring reads are done after idx read above. */
-    smp_rmb();
-    return more;
-}
-
-/*
- * vring_free
- *
- * put at the begin of the free list the current desc[head]
- */
-
-void vring_detach(struct vring_virtqueue *vq, unsigned int head)
-{
-    struct vring *vr = &vq->vring;
-    struct vring_desc *desc = GET_LOWFLAT(vr->desc);
-    unsigned int i;
-
-    /* find end of given descriptor */
-
-    i = head;
-    while (GET_LOWFLAT(desc[i].flags) & VRING_DESC_F_NEXT)
-        i = GET_LOWFLAT(desc[i].next);
-
-    /* link it with free list and point to it */
-
-    SET_LOWFLAT(desc[i].next, GET_LOWFLAT(vq->free_head));
-    SET_LOWFLAT(vq->free_head, head);
-}
-
-/*
- * vring_get_buf
- *
- * get a buffer from the used list
- *
- */
-
-int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
-{
-    struct vring *vr = &vq->vring;
-    struct vring_used_elem *elem;
-    struct vring_used *used = GET_LOWFLAT(vq->vring.used);
-    u32 id;
-    int ret;
-
-//    BUG_ON(!vring_more_used(vq));
-
-    elem = &used->ring[GET_LOWFLAT(vq->last_used_idx) % GET_LOWFLAT(vr->num)];
-    id = GET_LOWFLAT(elem->id);
-    if (len != NULL)
-        *len = GET_LOWFLAT(elem->len);
-
-    ret = GET_LOWFLAT(vq->vdata[id]);
-
-    vring_detach(vq, id);
-
-    SET_LOWFLAT(vq->last_used_idx, GET_LOWFLAT(vq->last_used_idx) + 1);
-
-    return ret;
-}
-
-void vring_add_buf(struct vring_virtqueue *vq,
-                   struct vring_list list[],
-                   unsigned int out, unsigned int in,
-                   int index, int num_added)
-{
-    struct vring *vr = &vq->vring;
-    int i, av, head, prev;
-    struct vring_desc *desc = GET_LOWFLAT(vr->desc);
-    struct vring_avail *avail = GET_LOWFLAT(vr->avail);
-
-    BUG_ON(out + in == 0);
-
-    prev = 0;
-    head = GET_LOWFLAT(vq->free_head);
-    for (i = head; out; i = GET_LOWFLAT(desc[i].next), out--) {
-        SET_LOWFLAT(desc[i].flags, VRING_DESC_F_NEXT);
-        SET_LOWFLAT(desc[i].addr, (u64)virt_to_phys(list->addr));
-        SET_LOWFLAT(desc[i].len, list->length);
-        prev = i;
-        list++;
-    }
-    for ( ; in; i = GET_LOWFLAT(desc[i].next), in--) {
-        SET_LOWFLAT(desc[i].flags, VRING_DESC_F_NEXT|VRING_DESC_F_WRITE);
-        SET_LOWFLAT(desc[i].addr, (u64)virt_to_phys(list->addr));
-        SET_LOWFLAT(desc[i].len, list->length);
-        prev = i;
-        list++;
-    }
-    SET_LOWFLAT(desc[prev].flags,
-                GET_LOWFLAT(desc[prev].flags) & ~VRING_DESC_F_NEXT);
-
-    SET_LOWFLAT(vq->free_head, i);
-
-    SET_LOWFLAT(vq->vdata[head], index);
-
-    av = (GET_LOWFLAT(avail->idx) + num_added) % GET_LOWFLAT(vr->num);
-    SET_LOWFLAT(avail->ring[av], head);
-}
-
-void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
-{
-    struct vring *vr = &vq->vring;
-    struct vring_avail *avail = GET_LOWFLAT(vr->avail);
-
-    /* Make sure idx update is done after ring write. */
-    smp_wmb();
-    SET_LOWFLAT(avail->idx, GET_LOWFLAT(avail->idx) + num_added);
-
-    vp_notify(ioaddr, GET_LOWFLAT(vq->queue_index));
-}
diff --git a/src/virtio-ring.h b/src/virtio-ring.h
deleted file mode 100644 (file)
index b7a7aaf..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef _VIRTIO_RING_H
-#define _VIRTIO_RING_H
-
-#include "types.h" // u64
-#include "memmap.h" // PAGE_SIZE
-
-#define PAGE_SHIFT 12
-#define PAGE_MASK  (PAGE_SIZE-1)
-
-#define virt_to_phys(v) (unsigned long)(v)
-#define phys_to_virt(p) (void*)(p)
-/* Compiler barrier is enough as an x86 CPU does not reorder reads or writes */
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-
-/* Status byte for guest to report progress, and synchronize features. */
-/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
-#define VIRTIO_CONFIG_S_ACKNOWLEDGE     1
-/* We have found a driver for the device. */
-#define VIRTIO_CONFIG_S_DRIVER          2
-/* Driver has used its parts of the config, and is happy */
-#define VIRTIO_CONFIG_S_DRIVER_OK       4
-/* We've given up on this device. */
-#define VIRTIO_CONFIG_S_FAILED          0x80
-
-#define MAX_QUEUE_NUM      (128)
-
-#define VRING_DESC_F_NEXT  1
-#define VRING_DESC_F_WRITE 2
-
-#define VRING_AVAIL_F_NO_INTERRUPT 1
-
-#define VRING_USED_F_NO_NOTIFY     1
-
-struct vring_desc
-{
-   u64 addr;
-   u32 len;
-   u16 flags;
-   u16 next;
-};
-
-struct vring_avail
-{
-   u16 flags;
-   u16 idx;
-   u16 ring[0];
-};
-
-struct vring_used_elem
-{
-   u32 id;
-   u32 len;
-};
-
-struct vring_used
-{
-   u16 flags;
-   u16 idx;
-   struct vring_used_elem ring[];
-};
-
-struct vring {
-   unsigned int num;
-   struct vring_desc *desc;
-   struct vring_avail *avail;
-   struct vring_used *used;
-};
-
-#define vring_size(num) \
-   (((((sizeof(struct vring_desc) * num) + \
-      (sizeof(struct vring_avail) + sizeof(u16) * num)) \
-         + PAGE_MASK) & ~PAGE_MASK) + \
-         (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
-
-typedef unsigned char virtio_queue_t[vring_size(MAX_QUEUE_NUM)];
-
-struct vring_virtqueue {
-   virtio_queue_t queue;
-   struct vring vring;
-   u16 free_head;
-   u16 last_used_idx;
-   u16 vdata[MAX_QUEUE_NUM];
-   /* PCI */
-   int queue_index;
-};
-
-struct vring_list {
-  char *addr;
-  unsigned int length;
-};
-
-static inline void vring_init(struct vring *vr,
-                         unsigned int num, unsigned char *queue)
-{
-   unsigned int i;
-   unsigned long pa;
-
-   ASSERT32FLAT();
-   vr->num = num;
-
-   /* physical address of desc must be page aligned */
-
-   pa = virt_to_phys(queue);
-   pa = (pa + PAGE_MASK) & ~PAGE_MASK;
-   vr->desc = phys_to_virt(pa);
-
-   vr->avail = (struct vring_avail *)&vr->desc[num];
-   /* disable interrupts */
-   vr->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
-
-   /* physical address of used must be page aligned */
-
-   pa = virt_to_phys(&vr->avail->ring[num]);
-   pa = (pa + PAGE_MASK) & ~PAGE_MASK;
-   vr->used = phys_to_virt(pa);
-
-   for (i = 0; i < num - 1; i++)
-           vr->desc[i].next = i + 1;
-   vr->desc[i].next = 0;
-}
-
-int vring_more_used(struct vring_virtqueue *vq);
-void vring_detach(struct vring_virtqueue *vq, unsigned int head);
-int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
-void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
-                   unsigned int out, unsigned int in,
-                   int index, int num_added);
-void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added);
-
-#endif /* _VIRTIO_RING_H_ */
diff --git a/src/virtio-scsi.c b/src/virtio-scsi.c
deleted file mode 100644 (file)
index 4de1255..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-// Virtio SCSI boot support.
-//
-// Copyright (C) 2012 Red Hat Inc.
-//
-// Authors:
-//  Paolo Bonzini <pbonzini@redhat.com>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "pci.h" // foreachpci
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // GET_GLOBAL
-#include "pci_ids.h" // PCI_DEVICE_ID_VIRTIO_BLK
-#include "pci_regs.h" // PCI_VENDOR_ID
-#include "boot.h" // bootprio_find_scsi_device
-#include "blockcmd.h" // scsi_drive_setup
-#include "virtio-pci.h"
-#include "virtio-ring.h"
-#include "virtio-scsi.h"
-#include "disk.h"
-
-struct virtio_lun_s {
-    struct drive_s drive;
-    struct pci_device *pci;
-    struct vring_virtqueue *vq;
-    u16 ioaddr;
-    u16 target;
-    u16 lun;
-};
-
-static int
-virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op,
-                void *cdbcmd, u16 target, u16 lun, u16 blocksize)
-{
-    struct virtio_scsi_req_cmd req;
-    struct virtio_scsi_resp_cmd resp;
-    struct vring_list sg[3];
-
-    memset(&req, 0, sizeof(req));
-    req.lun[0] = 1;
-    req.lun[1] = target;
-    req.lun[2] = (lun >> 8) | 0x40;
-    req.lun[3] = (lun & 0xff);
-    memcpy(req.cdb, cdbcmd, 16);
-
-    u32 len = op->count * blocksize;
-    int datain = cdb_is_read(cdbcmd, blocksize);
-    int in_num = (datain ? 2 : 1);
-    int out_num = (len ? 3 : 2) - in_num;
-
-    sg[0].addr   = MAKE_FLATPTR(GET_SEG(SS), &req);
-    sg[0].length = sizeof(req);
-
-    sg[out_num].addr   = MAKE_FLATPTR(GET_SEG(SS), &resp);
-    sg[out_num].length = sizeof(resp);
-
-    if (len) {
-        int data_idx = (datain ? 2 : 1);
-        sg[data_idx].addr   = op->buf_fl;
-        sg[data_idx].length = len;
-    }
-
-    /* Add to virtqueue and kick host */
-    vring_add_buf(vq, sg, out_num, in_num, 0, 0);
-    vring_kick(ioaddr, vq, 1);
-
-    /* Wait for reply */
-    while (!vring_more_used(vq))
-        usleep(5);
-
-    /* Reclaim virtqueue element */
-    vring_get_buf(vq, NULL);
-
-    /* Clear interrupt status register.  Avoid leaving interrupts stuck if
-     * VRING_AVAIL_F_NO_INTERRUPT was ignored and interrupts were raised.
-     */
-    vp_get_isr(ioaddr);
-
-    if (resp.response == VIRTIO_SCSI_S_OK && resp.status == 0) {
-        return DISK_RET_SUCCESS;
-    }
-    return DISK_RET_EBADTRACK;
-}
-
-int
-virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
-{
-    struct virtio_lun_s *vlun =
-        container_of(op->drive_g, struct virtio_lun_s, drive);
-
-    return virtio_scsi_cmd(GET_GLOBAL(vlun->ioaddr),
-                           GET_GLOBAL(vlun->vq), op, cdbcmd,
-                           GET_GLOBAL(vlun->target), GET_GLOBAL(vlun->lun),
-                           blocksize);
-}
-
-static int
-virtio_scsi_add_lun(struct pci_device *pci, u16 ioaddr,
-                    struct vring_virtqueue *vq, u16 target, u16 lun)
-{
-    struct virtio_lun_s *vlun = malloc_fseg(sizeof(*vlun));
-    if (!vlun) {
-        warn_noalloc();
-        return -1;
-    }
-    memset(vlun, 0, sizeof(*vlun));
-    vlun->drive.type = DTYPE_VIRTIO_SCSI;
-    vlun->drive.cntl_id = pci->bdf;
-    vlun->pci = pci;
-    vlun->ioaddr = ioaddr;
-    vlun->vq = vq;
-    vlun->target = target;
-    vlun->lun = lun;
-
-    int prio = bootprio_find_scsi_device(pci, target, lun);
-    int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio);
-    if (ret)
-        goto fail;
-    return 0;
-
-fail:
-    free(vlun);
-    return -1;
-}
-
-static int
-virtio_scsi_scan_target(struct pci_device *pci, u16 ioaddr,
-                        struct vring_virtqueue *vq, u16 target)
-{
-    /* TODO: send REPORT LUNS.  For now, only LUN 0 is recognized.  */
-    int ret = virtio_scsi_add_lun(pci, ioaddr, vq, target, 0);
-    return ret < 0 ? 0 : 1;
-}
-
-static void
-init_virtio_scsi(struct pci_device *pci)
-{
-    u16 bdf = pci->bdf;
-    dprintf(1, "found virtio-scsi at %x:%x\n", pci_bdf_to_bus(bdf),
-            pci_bdf_to_dev(bdf));
-    struct vring_virtqueue *vq = NULL;
-    u16 ioaddr = vp_init_simple(bdf);
-    if (vp_find_vq(ioaddr, 2, &vq) < 0 ) {
-        dprintf(1, "fail to find vq for virtio-scsi %x:%x\n",
-                pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));
-        goto fail;
-    }
-
-    vp_set_status(ioaddr, VIRTIO_CONFIG_S_ACKNOWLEDGE |
-                  VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
-
-    int i, tot;
-    for (tot = 0, i = 0; i < 256; i++)
-        tot += virtio_scsi_scan_target(pci, ioaddr, vq, i);
-
-    if (!tot)
-        goto fail;
-
-    return;
-
-fail:
-    free(vq);
-}
-
-void
-virtio_scsi_setup(void)
-{
-    ASSERT32FLAT();
-    if (! CONFIG_VIRTIO_SCSI)
-        return;
-
-    dprintf(3, "init virtio-scsi\n");
-
-    struct pci_device *pci;
-    foreachpci(pci) {
-        if (pci->vendor != PCI_VENDOR_ID_REDHAT_QUMRANET
-            || pci->device != PCI_DEVICE_ID_VIRTIO_SCSI)
-            continue;
-        init_virtio_scsi(pci);
-    }
-}
diff --git a/src/virtio-scsi.h b/src/virtio-scsi.h
deleted file mode 100644 (file)
index 96c3701..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef _VIRTIO_SCSI_H
-#define _VIRTIO_SCSI_H
-
-#define VIRTIO_SCSI_CDB_SIZE      32
-#define VIRTIO_SCSI_SENSE_SIZE    96
-
-struct virtio_scsi_config
-{
-    u32 num_queues;
-    u32 seg_max;
-    u32 max_sectors;
-    u32 cmd_per_lun;
-    u32 event_info_size;
-    u32 sense_size;
-    u32 cdb_size;
-    u16 max_channel;
-    u16 max_target;
-    u32 max_lun;
-} __attribute__((packed));
-
-/* This is the first element of the "out" scatter-gather list. */
-struct virtio_scsi_req_cmd {
-    u8 lun[8];
-    u64 id;
-    u8 task_attr;
-    u8 prio;
-    u8 crn;
-    char cdb[VIRTIO_SCSI_CDB_SIZE];
-} __attribute__((packed));
-
-/* This is the first element of the "in" scatter-gather list. */
-struct virtio_scsi_resp_cmd {
-    u32 sense_len;
-    u32 residual;
-    u16 status_qualifier;
-    u8 status;
-    u8 response;
-    u8 sense[VIRTIO_SCSI_SENSE_SIZE];
-} __attribute__((packed));
-
-#define VIRTIO_SCSI_S_OK            0
-
-struct disk_op_s;
-int virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
-void virtio_scsi_setup(void);
-
-#endif /* _VIRTIO_SCSI_H */
index b0ba1ecff86857e5eb463bd8a816c84ae9672569..20021182a71aa30a462ef0341c2a8d65d6397b18 100644 (file)
@@ -13,8 +13,8 @@
 #include "config.h" // CONFIG_*
 #include "biosvar.h" // GET_GLOBAL
 #include "stdvga.h" // VGAREG_SEQU_ADDRESS
-#include "pci.h" // pci_config_readl
-#include "pci_regs.h" // PCI_BASE_ADDRESS_0
+#include "hw/pci.h" // pci_config_readl
+#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
 
 
 /****************************************************************
index 8eb226afc9a080f04174d957ef97df9fa165fd2f..012e2b1064ff04d3a18a236e5d72d9d07170424f 100644 (file)
@@ -11,8 +11,8 @@
 #include "util.h" // dprintf
 #include "bregs.h" // struct bregs
 #include "stdvga.h" // VGAREG_SEQU_ADDRESS
-#include "pci.h" // pci_config_readl
-#include "pci_regs.h" // PCI_BASE_ADDRESS_0
+#include "hw/pci.h" // pci_config_readl
+#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
 
 
 /****************************************************************
index e508cbd8ead1817e67e708a57d13942f96d55666..cdc9e44ade370906a5ea29f810a94b5ef2340912 100644 (file)
@@ -12,8 +12,8 @@
 #include "vgabios.h" // VGAREG_*
 #include "util.h" // memset
 #include "stdvga.h" // stdvga_crtc_write
-#include "pci.h" // pci_config_readl
-#include "pci_regs.h" // PCI_BASE_ADDRESS_0
+#include "hw/pci.h" // pci_config_readl
+#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
 
 
 /****************************************************************
index 987a25944a4aa48a2fa825873251611f6d39c69a..506dd8d7b34b2d22ea4a0733cbcf72cf8c189573 100644 (file)
@@ -15,8 +15,8 @@
 #include "clext.h" // clext_1012
 #include "vgahw.h" // vgahw_set_mode
 #include "vbe.h" // VBE_RETURN_STATUS_FAILED
-#include "pci.h" // pci_config_readw
-#include "pci_regs.h" // PCI_VENDOR_ID
+#include "hw/pci.h" // pci_config_readw
+#include "hw/pci_regs.h" // PCI_VENDOR_ID
 
 // Standard Video Save Pointer Table
 struct VideoSavePointer_s {