xhci: Run the XHCI driver entirely in 32bit mode.

Since the XHCI driver needs to jump into 32bit mode anyway, it is
simpler to just run all of the code in 32bit mode.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
diff --git a/Makefile b/Makefile
index de91329..488bd04 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@
     serial.c clock.c resume.c pnpbios.c vgahooks.c pcibios.c apm.c \
     fw/smp.c \
     hw/pci.c hw/timer.c hw/rtc.c hw/dma.c hw/pic.c hw/ps2port.c hw/serialio.c \
-    hw/usb.c hw/usb-uhci.c hw/usb-ohci.c hw/usb-ehci.c hw/usb-xhci.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/usb-uas.c \
     hw/blockcmd.c hw/floppy.c hw/ata.c hw/ramdisk.c \
     hw/virtio-ring.c hw/virtio-pci.c hw/virtio-blk.c hw/virtio-scsi.c \
@@ -38,7 +38,7 @@
 SRC16=$(SRCBOTH) system.c disk.c font.c
 SRC32FLAT=$(SRCBOTH) post.c memmap.c malloc.c pmm.c romfile.c optionroms.c \
     boot.c bootsplash.c jpeg.c bmp.c \
-    hw/ahci.c hw/pvscsi.c hw/usb-hub.c \
+    hw/ahci.c hw/pvscsi.c hw/usb-xhci.c hw/usb-hub.c \
     fw/coreboot.c fw/lzmadecode.c fw/csm.c fw/biostables.c \
     fw/paravirt.c fw/shadow.c fw/pciinit.c fw/smm.c fw/mtrr.c fw/xen.c \
     fw/acpi.c fw/mptable.c fw/pirtable.c fw/smbios.c fw/romfile_loader.c
diff --git a/src/block.c b/src/block.c
index 898c279..264f376 100644
--- a/src/block.c
+++ b/src/block.c
@@ -388,6 +388,8 @@
     case DTYPE_MEGASAS:
         ret = process_scsi_op(op);
         break;
+    case DTYPE_USB_32:
+    case DTYPE_UAS_32:
     case DTYPE_PVSCSI: ;
         extern void _cfunc32flat_process_scsi_op(void);
         ret = call32(_cfunc32flat_process_scsi_op
diff --git a/src/block.h b/src/block.h
index bb57748..5d0afb5 100644
--- a/src/block.h
+++ b/src/block.h
@@ -79,7 +79,9 @@
 #define DTYPE_VIRTIO_SCSI  0x60
 #define DTYPE_VIRTIO_BLK   0x61
 #define DTYPE_USB          0x70
-#define DTYPE_UAS          0x71
+#define DTYPE_USB_32       0x71
+#define DTYPE_UAS          0x72
+#define DTYPE_UAS_32       0x73
 #define DTYPE_LSI_SCSI     0x80
 #define DTYPE_ESP_SCSI     0x81
 #define DTYPE_MEGASAS      0x82
diff --git a/src/hw/blockcmd.c b/src/hw/blockcmd.c
index db61cbd..eb531d4 100644
--- a/src/hw/blockcmd.c
+++ b/src/hw/blockcmd.c
@@ -43,6 +43,12 @@
         return esp_scsi_cmd_data(op, cdbcmd, blocksize);
     case DTYPE_MEGASAS:
         return megasas_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_USB_32:
+        if (!MODESEGMENT)
+            return usb_cmd_data(op, cdbcmd, blocksize);
+    case DTYPE_UAS_32:
+        if (!MODESEGMENT)
+            return uas_cmd_data(op, cdbcmd, blocksize);
     case DTYPE_PVSCSI:
         if (!MODESEGMENT)
             return pvscsi_cmd_data(op, cdbcmd, blocksize);
diff --git a/src/hw/usb-msc.c b/src/hw/usb-msc.c
index 2cf9725..a7af9a7 100644
--- a/src/hw/usb-msc.c
+++ b/src/hw/usb-msc.c
@@ -147,7 +147,10 @@
         return -1;
     }
     memset(drive, 0, sizeof(*drive));
-    drive->drive.type = DTYPE_USB;
+    if (usb_32bit_pipe(inpipe))
+        drive->drive.type = DTYPE_USB_32;
+    else
+        drive->drive.type = DTYPE_USB;
     drive->bulkin = inpipe;
     drive->bulkout = outpipe;
     drive->lun = lun;
diff --git a/src/hw/usb-uas.c b/src/hw/usb-uas.c
index 33657ac..9474383 100644
--- a/src/hw/usb-uas.c
+++ b/src/hw/usb-uas.c
@@ -179,7 +179,10 @@
         return -1;
     }
     memset(drive, 0, sizeof(*drive));
-    drive->drive.type = DTYPE_UAS;
+    if (usb_32bit_pipe(data_in))
+        drive->drive.type = DTYPE_UAS_32;
+    else
+        drive->drive.type = DTYPE_UAS;
     drive->command = command;
     drive->status = status;
     drive->data_in = data_in;
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c
index b30bc01..dc54182 100644
--- a/src/hw/usb-xhci.c
+++ b/src/hw/usb-xhci.c
@@ -309,8 +309,8 @@
 static void xhci_doorbell(struct usb_xhci_s *xhci, u32 slotid, u32 value)
 {
     struct xhci_db *db = GET_LOWFLAT(xhci->db);
-    u32 addr = (u32)(&db[slotid].doorbell);
-    pci_writel(addr, value);
+    void *addr = &db[slotid].doorbell;
+    writel(addr, value);
 }
 
 static void xhci_process_events(struct usb_xhci_s *xhci)
@@ -365,10 +365,9 @@
         }
         SET_LOWFLAT(evts->nidx, nidx);
         struct xhci_ir *ir = GET_LOWFLAT(xhci->ir);
-        u32 addr = (u32)(&ir->erdp_low);
         u32 erdp = (u32)(evts->ring + nidx);
-        pci_writel(addr, erdp);
-        pci_writel((u32)(&ir->erdp_high), 0);
+        writel(&ir->erdp_low, erdp);
+        writel(&ir->erdp_high, 0);
     }
 }
 
@@ -1062,7 +1061,7 @@
     return 0;
 }
 
-int
+int VISIBLE32FLAT
 xhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datalen)
 {
     if (!CONFIG_USB_XHCI)
@@ -1081,7 +1080,7 @@
     return 0;
 }
 
-int
+int VISIBLE32FLAT
 xhci_poll_intr(struct usb_pipe *p, void *data)
 {
     if (!CONFIG_USB_XHCI)
diff --git a/src/hw/usb.c b/src/hw/usb.c
index e1356f9..8ffddf8 100644
--- a/src/hw/usb.c
+++ b/src/hw/usb.c
@@ -89,6 +89,8 @@
     case USB_TYPE_EHCI:
         return ehci_send_bulk(pipe_fl, dir, data, datasize);
     case USB_TYPE_XHCI:
+        if (MODESEGMENT)
+            return -1;
         return xhci_send_bulk(pipe_fl, dir, data, datasize);
     }
 }
@@ -96,6 +98,7 @@
 int
 usb_poll_intr(struct usb_pipe *pipe_fl, void *data)
 {
+    ASSERT16();
     switch (GET_LOWFLAT(pipe_fl->type)) {
     default:
     case USB_TYPE_UHCI:
@@ -104,11 +107,17 @@
         return ohci_poll_intr(pipe_fl, data);
     case USB_TYPE_EHCI:
         return ehci_poll_intr(pipe_fl, data);
-    case USB_TYPE_XHCI:
-        return xhci_poll_intr(pipe_fl, data);
+    case USB_TYPE_XHCI: ;
+        extern void _cfunc32flat_xhci_poll_intr(void);
+        return call32_params(_cfunc32flat_xhci_poll_intr, (u32)pipe_fl
+                             , (u32)MAKE_FLATPTR(GET_SEG(SS), (u32)data), 0, -1);
     }
 }
 
+int usb_32bit_pipe(struct usb_pipe *pipe_fl)
+{
+    return CONFIG_USB_XHCI && GET_LOWFLAT(pipe_fl->type) == USB_TYPE_XHCI;
+}
 
 /****************************************************************
  * Helper functions
diff --git a/src/hw/usb.h b/src/hw/usb.h
index cb5a05c..6196296 100644
--- a/src/hw/usb.h
+++ b/src/hw/usb.h
@@ -228,6 +228,7 @@
                                 , 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 usb_32bit_pipe(struct usb_pipe *pipe_fl);
 int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req
                          , void *data);
 void free_pipe(struct usb_pipe *pipe);