Hi there,

>From ching Huang <[email protected]> 
This patch is against to http://bxr.su/OpenBSD/sys/dev/pci/arc.c
1. Adjust some code to meet coding style and have more readability.
2. Add new code for ARC-1203, 1200, 1201 series, they are belong to 
ARC_HBA_TYPE_B.
3. Add new code for ARC-1884, it belongs to ARC_HBA_TYPE_E.
4. Extract or rewrite some code to a new function for support more adapter type 
controller and code structure.

Signed-off-by: ching Huang <[email protected]>
---

diff -upN a/sys/dev/pci/arc.c b/sys/dev/pci/arc.c
--- a/sys/dev/pci/arc.c Mon Jul  6 19:24:58 2020
+++ b/sys/dev/pci/arc.c Mon Jul  6 19:25:30 2020
@@ -17,7 +17,11 @@
  */
 
 /*
- * Ching Huang   Support ARC1880,1882,1213,1223,1214
+ *  Rev#    Date        Name           Description
+ * 1.1.0.0  2012/04/18  Ching Huang    Support ARC188x,1213,1223,12x5,12x6
+ * 1.2.0.0  2012/11/14  Ching Huang    Support ARC12x4
+ * 1.3.0.0  2016/03/09  Ching Huang    Support ARC1200,1201,1203
+ * 1.4.0.0  2018/09/05  Ching Huang    Support ARC1884
  */
 #include "bio.h"
 
@@ -61,20 +65,28 @@ int arcdebug = 0;
 #define DNPRINTF(n, p...)      /* n, p */
 #endif
 
+#define ARC_VERSION    "arc v1.4.0.0-20200623"
+#define ARC_ADAPTER_ID    0xff
+
 #define ARC_HBA_TYPE_A    0x00000001
 #define ARC_HBA_TYPE_B    0x00000002
 #define ARC_HBA_TYPE_C    0x00000003
 #define ARC_HBA_TYPE_D    0x00000004
+#define ARC_HBA_TYPE_E    0x00000005
 
 #define ARC_RA_PCI_BAR                 PCI_MAPREG_START
 #define ARC_RB_DOORBELL_BAR            PCI_MAPREG_START
 #define ARC_RB_RWBUFFER_BAR            PCI_MAPREG_PPB_END
 #define ARC_RC_PCI_BAR                 PCI_MAPREG_PCB_END
 #define ARC_RD_PCI_BAR                 PCI_MAPREG_START
+#define ARC_RE_PCI_BAR                 PCI_MAPREG_PCB_END
+#define ARC_RF_PCI_BAR                 PCI_MAPREG_START
 
 #define ARCMSR_MAX_CCB_COUNT           264
 #define ARCMSR_MAX_HBB_POSTQUEUE       264
 #define ARCMSR_MAX_HBD_POSTQUEUE       256
+#define ARCMSR_MAX_HBE_COMPLETION_Q    256
+#define ARCMSR_MAX_HBF_COMPLETION_Q    256
 
 /* Areca boards using the Intel IOP are Type A (RA) */
 
@@ -130,12 +142,53 @@ int arcdebug = 0;
 
 /* Areca boards using the Marvel IOP0 are Type B (RB) */
 
-#define ARC_RB_DRV2IOP_DOORBELL                0x00020400
-#define ARC_RB_DRV2IOP_DOORBELL_MASK   0x00020404
-#define ARC_RB_IOP2DRV_DOORBELL                0x00020408
-#define ARC_RB_IOP2DRV_DOORBELL_FIRMWARE_OK    (1<<31)
-#define ARC_RB_IOP2DRV_DOORBELL_MASK   0x0002040c
+#define ARC_RB_INB_DOORBELL                    0x00020400
+#define ARC_RB_INB_DOORBELL_MASK               0x00020404
+#define ARC_RB_OUTB_DOORBELL                   0x00020408
+#define ARC_RB_OUTB_DOORBELL_MASK              0x0002040c
+#define ARC_RB_OUTB_DOORBELL_FIRMWARE_OK       (1<<31)
 
+#define ARC_RB_OUTB_DOORBELL_1203              0x00021870
+#define ARC_RB_OUTB_DOORBELL_MASK_1203         0x00021874
+#define ARC_RB_INB_DOORBELL_1203               0x00021878
+#define ARC_RB_INB_DOORBELL_MASK_1203          0x0002187C
+
+#define ARC_RB_INB_MSG0_GET_CONFIG             0x00010008
+#define ARC_RB_INB_MSG0_SET_CONFIG             0x00020008
+#define ARC_RB_INB_MSG0_ABORT_CMD              0x00030008
+#define ARC_RB_INB_MSG0_STOP_BGRB              0x00040008
+#define ARC_RB_INB_MSG0_FLUSH_CACHE            0x00050008
+#define ARC_RB_INB_MSG0_START_BGRB             0x00060008
+#define ARC_RB_INB_MSG0_START_DRIVER_MODE      0x000E0008
+#define ARC_RB_INB_MSG0_SET_POST_WINDOW                0x000F0008
+#define ARC_RB_INB_MSG0_ACTIVE_EOI_MODE                0x00100008
+#define ARC_RB_INB_MSG0_FIRMWARE_OK            0x80000000
+
+#define ARC_RB_I2D_DATA_WRITE_OK               0x00000001
+#define ARC_RB_I2D_DATA_READ_OK                        0x00000002
+#define ARC_RB_I2D_CDB_DONE                    0x00000004
+#define ARC_RB_I2D_MSG_CMD_DONE                        0x00000008
+#define ARC_RB_I2D_INTR_ENABLE_DOORBELL                0x0000000F
+#define ARC_RB_I2D_DOORBELL_INT                        0x0000000B
+#define ARC_RB_I2D_POSTQ_INT                   0x00000004
+
+#define ARC_RB_D2I_DATA_WRITE_OK               0x00000001
+#define ARC_RB_D2I_DATA_READ_OK                        0x00000002
+#define ARC_RB_D2I_CDB_POSTED                  0x00000004
+#define ARC_RB_D2I_MSG_CMD_POSTED              0x00000008
+#define ARC_RB_D2I_END_OF_INTERRUPT            0x00000010
+
+#define ARC_RB_DOORBELL_HANDLE_INT             0x0000000F
+#define ARC_RB_DOORBELL_INT_CLEAR_PATTERN      0xFF00FFF0
+#define ARC_RB_MESSAGE_INT_CLEAR_PATTERN       0xFF00FFF7
+
+/* data tunnel buffer between user space and firmware */
+#define ARC_RB_MSG_RWBUF                       0x0000fa00      /* iop 
message_rwbuffer for message command */
+#define ARC_RB_MSG_WBUF                                0x0000fe00      /* user 
space data to iop 128bytes */
+#define ARC_RB_MSG_RBUF                                0x0000ff00      /* iop 
data to user space 128bytes */
+
+#define ARC_RB_REPLY_QUEUE_ERR                 (1<<28)
+
 /* Areca boards using the LSI IOP are Type C (RC) */
 
 #define ARC_RC_INB_DOORBELL            0x20
@@ -258,6 +311,57 @@ int arcdebug = 0;
 #define ARC_RD_REPLY_QUEUE_ERR         1
 #define        ARC_RD_OUTB_LIST_INT_CLR        1
 
+/* Areca boards using the LSI IOP are Type E (RE) */
+#define ARC_SIGNATURE_1884             0x188417D3
+
+#define ARC_RE_INB_DOORBELL            0x00
+#define ARC_RE_OUTB_DOORBELL           0x00
+#define ARC_RE_INTR_STAT               0x30
+#define ARC_RE_INTR_MASK               0x34
+#define ARC_RE_D2I_MSG_CMD_DONE                0x08
+#define ARC_RE_I2D_MSG_CMD_DONE                0x08
+#define ARC_RE_REPLY_PRODUCER_INDEX    0x68
+#define ARC_RE_REPLY_CONSUMER_INDEX    0x6C
+#define ARC_RE_INB_MSGADDR0            0xB0
+#define ARC_RE_INB_MSGADDR1            0xB4
+#define ARC_RE_OUTB_MSGADDR0           0xB8
+#define ARC_RE_OUTB_MSGADDR1           0xBC
+#define ARC_RE_INB_POSTQ_LOW           0xC0
+#define ARC_RE_INB_POSTQ_HIGH          0xC4
+#define ARC_RE_OUTB_REPLYQ_LOW         0xC8
+#define ARC_RE_OUTB_REPLYQ_HIGH                0xCC
+#define ARC_RE_MSG_WBUF_LEN            0x2000
+#define ARC_RE_MSG_WBUF                        0x2004
+#define ARC_RE_MSG_RBUF_LEN            0x2100
+#define ARC_RE_MSG_RBUF                        0x2104
+#define ARC_RE_MSG_RWBUF               0x2200
+
+#define ARC_RE_INB_MSG0_NOP            (0x00000000)
+#define ARC_RE_INB_MSG0_GET_CONFIG     (0x00000001)
+#define ARC_RE_INB_MSG0_SET_CONFIG     (0x00000002)
+#define ARC_RE_INB_MSG0_ABORT_CMD      (0x00000003)
+#define ARC_RE_INB_MSG0_STOP_BGRB      (0x00000004)
+#define ARC_RE_INB_MSG0_FLUSH_CACHE    (0x00000005)
+#define ARC_RE_INB_MSG0_START_BGRB     (0x00000006)
+#define ARC_RE_INB_MSG0_SYNC_TIMER     (0x00000008)
+#define ARC_RE_DOORBELL_SYNC           (0x00000100)
+
+#define ARC_RE_D2I_DATA_WRITE_OK       0x00000002
+#define ARC_RE_D2I_DATA_READ_OK                0x00000004
+#define ARC_RE_D2I_MESSAGE_CMD_DONE    0x00000008
+#define ARC_RE_I2D_DATA_WRITE_OK       0x00000002
+#define ARC_RE_I2D_DATA_READ_OK                0x00000004
+#define ARC_RE_I2D_MESSAGE_CMD_DONE    0x00000008
+#define ARC_RE_MESSAGE_FIRMWARE_OK     0x80000000
+#define ARC_RE_OUTB_MSG_FIRMWARE_OK    0x80000000
+
+#define ARC_RE_INTR_STAT_DOORBELL      (1<<0)
+#define ARC_RE_INTR_STAT_POSTQUEUE     (1<<3)
+#define ARC_RE_INTR_MASK_ALL           0x00000009
+#define ARC_RE_INTR_MASK_DOORBELL      (1<<0)
+#define ARC_RE_INTR_MASK_POSTQUEUE     (1<<3)
+#define ARC_RE_REPLY_QUEUE_ERR         1
+
 struct arc_msg_firmware_info {
        u_int32_t               signature;
 #define ARC_FWINFO_SIGNATURE_GET_CONFIG                (0x87974060)
@@ -443,6 +547,15 @@ struct arc_iop;
 struct arc_ccb;
 SLIST_HEAD(arc_ccb_list, arc_ccb);
 
+struct arc_HBB_Msgu {
+       u_int32_t post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
+       u_int32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
+       u_int32_t postq_index;
+       u_int32_t doneq_index;
+};
+
+#define        ARC_HBB_CMDQ_PTR_LEN    sizeof(struct arc_HBB_Msgu)
+
 struct InBound_SRB {
        u_int32_t addressLow;   /* pointer to SRB block */
        u_int32_t addressHigh;
@@ -456,14 +569,25 @@ struct OutBound_SRB {
 };
 
 struct arc_HBD_Msgu {
-       struct InBound_SRB post_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE];
-       struct OutBound_SRB done_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE+1];
+       struct InBound_SRB post_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE];
+       struct OutBound_SRB done_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE+1];
        u_int16_t postq_index;
        u_int16_t doneq_index;
 };
 
-#define                ARC_MAX_CMDQ_PTR_LEN    sizeof(struct arc_HBD_Msgu)
+#define        ARC_HBD_CMDQ_PTR_LEN    sizeof(struct arc_HBD_Msgu)
 
+struct arc_HBE_Msgu {
+       u_int16_t       cmdFlag;
+       u_int16_t       cmdSMID;
+       u_int16_t       cmdLMID;        // reserved (0)
+       u_int16_t       cmdFlag2;       // reserved (0)
+};
+
+#define        ARC_HBE_COMPLETION_Q_LEN        (sizeof(struct arc_HBE_Msgu) * 
ARCMSR_MAX_HBE_COMPLETION_Q + 128)
+#define        ARC_HBF_COMPLETION_Q_LEN        ARC_HBE_COMPLETION_Q_LEN
+#define        ARC_HBF_MESG_BUFFER_SIZE        (256 * 3)
+
 struct arc_msg_scsicmd {
        u_int8_t                bus;
        u_int8_t                target;
@@ -476,7 +600,7 @@ struct arc_msg_scsicmd {
 #define ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512     (1<<0)
 #define ARC_MSG_SCSICMD_FLAG_FROM_BIOS         (1<<1)
 #define ARC_MSG_SCSICMD_FLAG_WRITE             (1<<2)
-#define ARC_MSG_SCSICMD_FLAG_SIMPLEQ   (0x00)
+#define ARC_MSG_SCSICMD_FLAG_SIMPLEQ           (0x00)
 #define ARC_MSG_SCSICMD_FLAG_HEADQ             (0x08)
 #define ARC_MSG_SCSICMD_FLAG_ORDERQ            (0x10)
        u_int8_t                msgPages;
@@ -510,20 +634,19 @@ struct arc_sge {
 #define ARC_BLOCKSIZE          512
 
 /* the firmware deals with up to 256 or 512 byte command frames. */
-/* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 38) == 508 */
+/* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 38) == 504 */
 #define ARC_SGL_MAXLEN         38
 /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 17) == 252 */
 #define ARC_SGL_256LEN         17
 
 struct arc_io_cmd {
        struct arc_msg_scsicmd  cmd;
-       struct arc_sge  sgl[ARC_SGL_MAXLEN];
+       struct arc_sge          sgl[ARC_SGL_MAXLEN];
        u_int32_t               reserved1;
-       struct arc_ccb  *ccb;
-       u_int32_t               reserved2[6];
+       u_int32_t               ccb_id;
 } __packed;
 
-#define ARC_IO_CMD_LEN 512+32
+#define ARC_IO_CMD_LEN         (sizeof(struct arc_io_cmd))
 
 /* stuff to manage a scsi command */
 struct arc_ccb {
@@ -538,11 +661,12 @@ struct arc_ccb {
 
        SLIST_ENTRY(arc_ccb)    ccb_link;
        u_int32_t               arc_io_cmd_length;
+       u_int32_t               smid;
+       u_int32_t               ccb_id;
 };
 
 struct arc_softc {
        struct device           sc_dev;
-       const struct arc_iop    *sc_iop;
        struct scsi_link        sc_link;
 
        pci_chipset_tag_t       sc_pc;
@@ -574,11 +698,39 @@ struct arc_softc {
 
        u_int32_t               sc_ledmask;
        u_int32_t               sc_adp_type;
+       u_int32_t               sc_ccb_phys_lo;
        u_int32_t               sc_ccb_phys_hi;
        u_int32_t               postQ_buffer;
        u_int32_t               doneQ_buffer;
        bus_addr_t              cmdQ_ptr_offset;
-       struct arc_HBD_Msgu *pmu;
+       union {
+               struct arc_HBB_Msgu     *pmuB;
+               struct arc_HBD_Msgu     *pmu;
+               struct arc_HBE_Msgu     *pmuE;
+               struct arc_HBE_Msgu     *pmuF;
+       };
+       bus_space_tag_t         sc_msgt;
+       bus_space_handle_t      sc_msgh;
+       bus_size_t              sc_msgs;
+       bus_size_t              inb_doorbell;
+       bus_size_t              inb_doorbell_mask;
+       bus_size_t              outb_doorbell;
+       bus_size_t              outb_doorbell_mask;
+       u_int32_t               sc_int_mask;
+       pcireg_t                ab_product;
+       u_int32_t               doneq_index;
+       u_int32_t               doneq_size;
+       u_int32_t               doneq_entry;
+       u_int32_t               doneq_phys_lo;
+       u_int32_t               doneq_phys_hi;
+       u_int32_t               in_doorbell;
+       u_int32_t               out_doorbell;
+       u_int32_t               *message_wbuffer;
+       u_int32_t               *message_rbuffer;
+       u_int32_t               *msgcode_rwbuffer;
+       u_int32_t               msgBuf_phys_lo;
+       u_int32_t               msgBuf_phys_hi;
+       u_int32_t               ioc_compq_size;
 };
 #define DEVNAME(_s)            ((_s)->sc_dev.dv_xname)
 
@@ -599,51 +751,61 @@ int       arc_detach(struct device *, int);
 int    arc_activate(struct device *, int);
 int    arc_intr(void *);
 int    arc_intr_A(void *);
+int    arc_intr_B(void *);
 int    arc_intr_C(void *);
 int    arc_intr_D(void *);
+int    arc_intr_E(void *);
 
 /* interface for scsi midlayer to talk to */
 void   arc_scsi_cmd(struct scsi_xfer *);
+void   arc_minphys(struct buf *, struct scsi_link *);
 
 /* code to deal with getting bits in and out of the bus space */
 u_int32_t      arc_read(struct arc_softc *, bus_size_t);
 void           arc_read_region(struct arc_softc *, bus_size_t,
-                           void *, size_t);
+                   void *, size_t);
 void           arc_write(struct arc_softc *, bus_size_t, u_int32_t);
 void           arc_write_region(struct arc_softc *, bus_size_t,
-                           void *, size_t);
-int                    arc_wait_eq(struct arc_softc *, bus_size_t,
-                           u_int32_t, u_int32_t);
-int                    arc_wait_ne(struct arc_softc *, bus_size_t,
-                           u_int32_t, u_int32_t);
-int                    arc_msg0(struct arc_softc *, u_int32_t);
+                   void *, size_t);
+int            arc_wait_eq(struct arc_softc *, bus_size_t,
+                   u_int32_t, u_int32_t);
+int            arc_wait_ne(struct arc_softc *, bus_size_t,
+                   u_int32_t, u_int32_t);
+int            arc_msg0(struct arc_softc *, u_int32_t);
+u_int32_t      arc_read2(struct arc_softc *, bus_size_t);
+void           arc_read_region2(struct arc_softc *, bus_size_t,
+                   void *, size_t);
+void           arc_write2(struct arc_softc *, bus_size_t, u_int32_t);
+void           arc_write_region2(struct arc_softc *, bus_size_t,
+                   void *, size_t);
 
 struct arc_dmamem      *arc_dmamem_alloc(struct arc_softc *, size_t);
 void           arc_dmamem_free(struct arc_softc *,
                            struct arc_dmamem *);
-void arc_free_ccb_src(struct arc_softc *sc);
+void           arc_free_ccb_src(struct arc_softc *sc);
 
-int                    arc_alloc_ccbs(struct arc_softc *);
+int            arc_alloc_ccbs(struct arc_softc *);
 struct arc_ccb *arc_get_ccb(struct arc_softc *);
 void           arc_put_ccb(struct arc_softc *, struct arc_ccb *);
-int                    arc_load_xs(struct arc_ccb *);
-int                    arc_complete(struct arc_softc *, struct arc_ccb *,
-                           int);
+int            arc_load_xs(struct arc_ccb *);
+int            arc_complete(struct arc_softc *, struct arc_ccb *,
+                   int);
 void           arc_scsi_cmd_done(struct arc_softc *, struct arc_ccb *,
-                           u_int32_t);
+                   u_int32_t);
 
-int                    arc_map_pci_resources(struct arc_softc *,
-                           struct pci_attach_args *);
+int            arc_map_pci_resources(struct arc_softc *,
+                   struct pci_attach_args *);
 void           arc_unmap_pci_resources(struct arc_softc *);
-int            arc_chipA_firmware(struct arc_softc *);
-int            arc_chipB_firmware(struct arc_softc *);
-int            arc_chipC_firmware(struct arc_softc *);
-int            arc_chipD_firmware(struct arc_softc *);
+int            arc_query_firmware(struct arc_softc *);
 void           arc_enable_all_intr(struct arc_softc *);
 void           arc_disable_all_intr(struct arc_softc *);
 void           arc_stop_bgrb_proc(struct arc_softc *sc);
 void           arc_flush_cache(struct arc_softc *sc);
 void           arc_iop_set_conf(struct arc_softc *sc);
+int            arc_start_bkgrnd_rebuild(struct arc_softc *);
+int            arc_get_firmware_config(struct arc_softc *,
+                   struct arc_msg_firmware_info *);
+void           arc_clear_doorbell_qbuffer(struct arc_softc *);
 
 #if NBIO > 0
 /* stuff to do messaging via the doorbells */
@@ -651,30 +813,29 @@ void              arc_lock(struct arc_softc *);
 void           arc_unlock(struct arc_softc *);
 void           arc_wait(struct arc_softc *);
 u_int8_t       arc_msg_cksum(void *, u_int16_t);
-int                    arc_msgbuf(struct arc_softc *, void *, size_t,
-                           void *, size_t, int);
+int            arc_msgbuf(struct arc_softc *, void *, size_t,
+                   void *, size_t, int);
 
 /* bioctl */
-int                    arc_bioctl(struct device *, u_long, caddr_t);
-int                    arc_bio_inq(struct arc_softc *, struct bioc_inq *);
-int                    arc_bio_vol(struct arc_softc *, struct bioc_vol *);
-int                    arc_bio_disk(struct arc_softc *, struct bioc_disk *);
-int                    arc_bio_alarm(struct arc_softc *, struct bioc_alarm *);
-int                    arc_bio_alarm_state(struct arc_softc *,
-                           struct bioc_alarm *);
-int                    arc_bio_blink(struct arc_softc *, struct bioc_blink *);
+int            arc_bioctl(struct device *, u_long, caddr_t);
+int            arc_bio_inq(struct arc_softc *, struct bioc_inq *);
+int            arc_bio_vol(struct arc_softc *, struct bioc_vol *);
+int            arc_bio_disk(struct arc_softc *, struct bioc_disk *);
+int            arc_bio_alarm(struct arc_softc *, struct bioc_alarm *);
+int            arc_bio_alarm_state(struct arc_softc *,
+                   struct bioc_alarm *);
+int            arc_bio_blink(struct arc_softc *, struct bioc_blink *);
+int            arc_bio_getvol(struct arc_softc *, int,
+                   struct arc_fw_volinfo *);
 
-int                    arc_bio_getvol(struct arc_softc *, int,
-                           struct arc_fw_volinfo *);
-
 #ifndef SMALL_KERNEL
 struct arc_task {
        struct task t;
        struct arc_softc *sc;
 };
 /* sensors */
-void                   arc_create_sensors(void *);
-void                   arc_refresh_sensors(void *);
+void           arc_create_sensors(void *);
+void           arc_refresh_sensors(void *);
 #endif /* SMALL_KERNEL */
 #endif
 
@@ -692,63 +853,47 @@ struct scsi_adapter arc_switch = {
 };
 
 /* real stuff for dealing with the hardware */
-struct arc_iop {
-       int                     (*iop_query_firmware)(struct arc_softc *);
-};
 
-static const struct arc_iop arc_intel = {
-       arc_chipA_firmware
-};
-
-static const struct arc_iop arc_marvell = {
-       arc_chipB_firmware
-};
-
-static const struct arc_iop arc_lsi = {
-       arc_chipC_firmware
-};
-
-static const struct arc_iop arc_marvell2 = {
-       arc_chipD_firmware
-};
-
 struct arc_board {
        pcireg_t                ab_vendor;
        pcireg_t                ab_product;
-       const struct arc_iop    *ab_iop;
+       u_int16_t               ab_io_type;
 };
 const struct arc_board *arc_match_board(struct pci_attach_args *);
 
-static const struct arc_board arc_devices[] = {
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1110, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1120, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1130, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1160, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1170, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1200, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1200_B, &arc_marvell },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1202, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1210, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1214, &arc_marvell2 },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1220, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1230, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1260, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1270, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1280, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1380, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1381, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1680, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1681, &arc_intel },
-       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1880, &arc_lsi }
+const struct arc_board arc_devices[] = {
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1110, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1120, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1130, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1160, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1170, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1200, ARC_HBA_TYPE_B },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1200_B, ARC_HBA_TYPE_B },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1202, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1203, ARC_HBA_TYPE_B },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1210, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1214, ARC_HBA_TYPE_D },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1220, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1230, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1260, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1270, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1280, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1380, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1381, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1680, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1681, ARC_HBA_TYPE_A },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1880, ARC_HBA_TYPE_C },
+       { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1884, ARC_HBA_TYPE_E }
 };
 
 const struct arc_board *
 arc_match_board(struct pci_attach_args *pa)
 {
        const struct arc_board          *ab;
-       int                             i;
+       int                             i, j;
 
-       for (i = 0; i < sizeof(arc_devices) / sizeof(arc_devices[0]); i++) {
+       j = sizeof(arc_devices) / sizeof(arc_devices[0]);
+       for (i = 0; i < j; i++) {
                ab = &arc_devices[i];
 
                if (PCI_VENDOR(pa->pa_id) == ab->ab_vendor &&
@@ -765,6 +910,38 @@ arc_match(struct device *parent, void *match, void *au
        return ((arc_match_board(aux) == NULL) ? 0 : 1);
 }
 
+int
+arc_wait_firmware_ready(struct arc_softc *sc)
+{
+       int     ready;
+
+       switch(sc->sc_adp_type) {
+       case ARC_HBA_TYPE_A:
+               ready = arc_wait_eq(sc, ARC_RA_OUTB_ADDR1, 
ARC_RA_OUTB_ADDR1_FIRMWARE_OK,
+                       ARC_RA_OUTB_ADDR1_FIRMWARE_OK);
+               break;
+       case ARC_HBA_TYPE_B:
+               ready = arc_wait_eq(sc, sc->outb_doorbell, 
ARC_RB_OUTB_DOORBELL_FIRMWARE_OK,
+                       ARC_RB_OUTB_DOORBELL_FIRMWARE_OK);
+               break;
+       case ARC_HBA_TYPE_C:
+               ready = arc_wait_eq(sc, ARC_RC_OUTB_MSGADDR1, 
ARC_RC_OUTB_MSG_FIRMWARE_OK,
+                       ARC_RC_OUTB_MSG_FIRMWARE_OK);
+               break;
+       case ARC_HBA_TYPE_D:
+               ready = arc_wait_eq(sc, ARC_RD_OUTB_MSGADDR1, 
ARC_RD_OUTB_MSG_FIRMWARE_OK,
+                       ARC_RD_OUTB_MSG_FIRMWARE_OK);
+               break;
+       case ARC_HBA_TYPE_E:
+               ready = arc_wait_eq(sc, ARC_RE_OUTB_MSGADDR1, 
ARC_RE_OUTB_MSG_FIRMWARE_OK,
+                       ARC_RE_OUTB_MSG_FIRMWARE_OK);
+               break;
+       }
+       if (ready != 0)
+               printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
+       return (ready);
+}
+
 void
 arc_attach(struct device *parent, struct device *self, void *aux)
 {
@@ -772,36 +949,41 @@ arc_attach(struct device *parent, struct device *self,
        struct pci_attach_args          *pa = aux;
        struct scsibus_attach_args      saa;
        struct device                   *child;
+       const struct arc_board          *ab;
 
        sc->sc_talking = 0;
        rw_init(&sc->sc_lock, "arcmsg");
 
-       sc->sc_iop = arc_match_board(pa)->ab_iop;
-       if(sc->sc_iop == &arc_intel)
-               sc->sc_adp_type = ARC_HBA_TYPE_A;
-       else if(sc->sc_iop == &arc_marvell)
-               sc->sc_adp_type = ARC_HBA_TYPE_B;
-       else if(sc->sc_iop == &arc_lsi)
-               sc->sc_adp_type = ARC_HBA_TYPE_C;
-       else if(sc->sc_iop == &arc_marvell2)
-               sc->sc_adp_type = ARC_HBA_TYPE_D;
+       ab = arc_match_board(pa);
+       sc->sc_adp_type = ab->ab_io_type;
        if (arc_map_pci_resources(sc, pa) != 0) {
                /* error message printed by arc_map_pci_resources */
                return;
        }
 
+       sc->ab_product = ab->ab_product;
        if (arc_alloc_ccbs(sc) != 0) {
                /* error message printed by arc_alloc_ccbs */
                goto unmap_pci;
        }
 
-       arc_iop_set_conf(sc);
+       arc_wait_firmware_ready(sc);
 
-       if (sc->sc_iop->iop_query_firmware(sc) != 0) {
+       if (arc_query_firmware(sc) != 0) {
                /* error message printed by arc_query_firmware */
-               goto unmap_pci;
+               goto free_ccb;
        }
 
+       arc_iop_set_conf(sc);
+
+       if (arc_start_bkgrnd_rebuild(sc)) {
+               printf("%s: timeout waiting to start bg rebuild\n",
+                   DEVNAME(sc));
+               goto free_ccb;
+       }
+
+       arc_clear_doorbell_qbuffer(sc);
+
        sc->sc_link.adapter = &arc_switch;
        sc->sc_link.adapter_softc = sc;
        sc->sc_link.adapter_target = SDEV_NO_ADAPTER_TARGET;
@@ -809,6 +991,7 @@ arc_attach(struct device *parent, struct device *self,
        sc->sc_link.openings = sc->sc_req_count;
        sc->sc_link.pool = &sc->sc_iopool;
 
+       bzero(&saa, sizeof(saa));
        saa.saa_sc_link = &sc->sc_link;
 
        child = config_found(self, &saa, scsiprint);
@@ -839,6 +1022,8 @@ arc_attach(struct device *parent, struct device *self,
 #endif
 
        return;
+free_ccb:
+       arc_free_ccb_src(sc);
 unmap_pci:
        arc_unmap_pci_resources(sc);
 }
@@ -867,6 +1052,9 @@ arc_detach(struct device *self, int flags)
 
        arc_stop_bgrb_proc(sc);
        arc_flush_cache(sc);
+       arc_disable_all_intr(sc);
+       arc_free_ccb_src(sc);
+       arc_unmap_pci_resources(sc);
 
        return (0);
 }
@@ -909,10 +1097,10 @@ arc_intr_A(void *arg)
                        cmd = (struct arc_io_cmd *)(kva +
                        ((reg << ARC_RA_REPLY_QUEUE_ADDR_SHIFT) -
                        (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
-                       ccb = cmd->ccb;
+                       ccb = &sc->sc_ccbs[cmd->ccb_id];
 
                        bus_dmamap_sync(sc->sc_dmat, 
ARC_DMA_MAP(sc->sc_requests),
-                       ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
+                       ccb->cmd_dma_offset, ARC_IO_CMD_LEN,
                        BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
                        error = (reg & ARC_RA_REPLY_QUEUE_ERR)? 1:0;
@@ -923,6 +1111,78 @@ arc_intr_A(void *arg)
 }
 
 int
+arc_intr_B(void *arg)
+{
+       struct arc_softc                *sc = arg;
+       struct arc_ccb                  *ccb = NULL;
+       char                            *kva = ARC_DMA_KVA(sc->sc_requests);
+       struct arc_io_cmd               *cmd;
+       u_int32_t                       reg, intrstat, error;
+       u_int32_t doneq_index;
+       int                             ret = 0;
+       struct arc_HBB_Msgu *pmuB;
+
+       intrstat = arc_read(sc, sc->outb_doorbell) & 
ARC_RB_I2D_INTR_ENABLE_DOORBELL;
+       if (!intrstat)
+               return (ret);
+
+       arc_write(sc, sc->outb_doorbell, ~intrstat);
+       arc_write(sc, sc->inb_doorbell, ARC_RB_D2I_END_OF_INTERRUPT);
+       if (intrstat & ARC_RB_I2D_DOORBELL_INT) {
+               ret = 1;
+               if (sc->sc_talking) {
+                       /* if an ioctl is talking, wake it up */
+                       arc_write(sc, sc->outb_doorbell_mask, 
ARC_RB_I2D_CDB_DONE);
+                       wakeup(sc);
+               } else {
+                       /* otherwise drop it */
+                       if (intrstat & ARC_RB_I2D_DATA_WRITE_OK) {
+                               arc_write(sc, sc->inb_doorbell,
+                                   ARC_RB_I2D_DATA_READ_OK);
+                       }
+/*                     if (intrstat & ARC_RB_I2D_DATA_READ_OK) {
+                               arc_write(sc, sc->inb_doorbell,
+                                   ARC_RB_D2I_DATA_WRITE_OK);
+                       }
+*/
+                       if (intrstat & ARC_RB_I2D_MSG_CMD_DONE) {
+                               arc_write(sc, sc->outb_doorbell,
+                                   ARC_RB_MESSAGE_INT_CLEAR_PATTERN);
+                       }
+
+               }
+       }
+
+       if (intrstat & ARC_RB_I2D_POSTQ_INT) {
+               ret = 1;
+               bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
+                   sc->cmdQ_ptr_offset, ARC_HBB_CMDQ_PTR_LEN,
+                   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+               pmuB = sc->pmuB;
+               doneq_index = pmuB->doneq_index;
+               while ((reg = pmuB->done_qbuffer[doneq_index]) != 0) {
+                       if (doneq_index >= 4)
+                               pmuB->done_qbuffer[doneq_index - 4] = 0;
+                       else
+                               pmuB->done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE - 
(4 - doneq_index)] = 0;
+                       cmd = (struct arc_io_cmd *)(kva +
+                           ((reg << ARC_RA_REPLY_QUEUE_ADDR_SHIFT) -
+                           (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
+                       ccb = &sc->sc_ccbs[cmd->ccb_id];
+                       bus_dmamap_sync(sc->sc_dmat, 
ARC_DMA_MAP(sc->sc_requests),
+                           ccb->cmd_dma_offset, ARC_IO_CMD_LEN,
+                           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+                       error = (reg & ARC_RB_REPLY_QUEUE_ERR) ? 1 : 0;
+                       arc_scsi_cmd_done(sc, ccb, error);
+                       doneq_index++;
+                       doneq_index %= ARCMSR_MAX_HBB_POSTQUEUE;
+                       pmuB->doneq_index = doneq_index;
+               }
+       }
+       return (ret);
+}
+
+int
 arc_intr_C(void *arg)
 {
        struct arc_softc                *sc = arg;
@@ -974,15 +1234,17 @@ arc_intr_C(void *arg)
                while (arc_read(sc, ARC_RC_INTR_STAT) &
                        ARC_RC_INTR_STAT_POSTQUEUE) {
                        reg = arc_read(sc, ARC_RC_OUTB_REPLYQ_LOW);
+                       if (reg == 0xFFFFFFFF)
+                               break;
                        cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFE0) -
                        (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
-                       ccb = cmd->ccb;
+                       ccb = &sc->sc_ccbs[cmd->ccb_id];
 
                        bus_dmamap_sync(sc->sc_dmat, 
ARC_DMA_MAP(sc->sc_requests),
-                       ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
+                       ccb->cmd_dma_offset, ARC_IO_CMD_LEN,
                        BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
-                       error = (reg & ARC_RC_REPLY_QUEUE_ERR);
+                       error = reg & ARC_RC_REPLY_QUEUE_ERR;
                        arc_scsi_cmd_done(sc, ccb, error);
                        throttling++;
                        if(throttling == ARC_RC_THROTTLE) {
@@ -996,7 +1258,7 @@ arc_intr_C(void *arg)
        return (ret);
 }
 
-static u_int16_t
+u_int16_t
 arcmsr_get_doneq_index(struct arc_HBD_Msgu *phbdmu)
 {
        u_int16_t doneq_index, index_stripped;
@@ -1070,7 +1332,7 @@ arc_intr_D(void *arg)
                ret = 1;
                arc_write(sc, ARC_RD_OUTB_INTR_CAUSE, ARC_RD_OUTB_LIST_INT_CLR);
                bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
-                   sc->cmdQ_ptr_offset, ARC_MAX_CMDQ_PTR_LEN,
+                   0, sc->ioc_compq_size,
                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                pmu = sc->pmu;
                ob_write_ptr = pmu->done_qbuffer[0].addressLow;
@@ -1079,11 +1341,8 @@ arc_intr_D(void *arg)
                        doneq_index = arcmsr_get_doneq_index(pmu);
                        reg = pmu->done_qbuffer[(doneq_index & 
0xFF)+1].addressLow;
                        cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFF0) -
-                       (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
-                       ccb = cmd->ccb;
-                       bus_dmamap_sync(sc->sc_dmat, 
ARC_DMA_MAP(sc->sc_requests),
-                               ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
-                               BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+                           (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
+                       ccb = &sc->sc_ccbs[cmd->ccb_id];
                        error = (reg & ARC_RD_REPLY_QUEUE_ERR);
                        arc_scsi_cmd_done(sc, ccb, error);
                        arc_write(sc, ARC_RD_OUTB_READ_PTR, doneq_index);
@@ -1095,6 +1354,79 @@ arc_intr_D(void *arg)
 }
 
 int
+arc_intr_E(void *arg)
+{
+       struct arc_softc                *sc = arg;
+       struct arc_ccb                  *ccb = NULL;
+       u_int32_t                       reg, intrstat, obmsg, error, val;
+       int                             ret = 0;
+
+       intrstat = arc_read(sc, ARC_RE_INTR_STAT);
+       if (!(intrstat & (ARC_RE_INTR_STAT_POSTQUEUE |
+               ARC_RE_INTR_STAT_DOORBELL)))
+               return (ret);
+
+       if (intrstat & ARC_RE_INTR_STAT_DOORBELL) {
+               ret = 1;
+               if (sc->sc_talking) {
+                       /* if an ioctl is talking, wake it up */
+                       arc_write(sc, ARC_RE_INTR_MASK,
+                           ~ARC_RE_INTR_MASK_POSTQUEUE);
+                       wakeup(sc);
+               } else {
+                       /* otherwise drop it */
+                       reg = arc_read(sc, ARC_RE_OUTB_DOORBELL);
+                       val = sc->in_doorbell ^ reg;
+                       arc_write(sc, ARC_RE_INTR_STAT, 0);
+                       if (val & ARC_RE_I2D_DATA_WRITE_OK) {
+                               sc->out_doorbell ^= ARC_RE_I2D_DATA_READ_OK;
+                               arc_write(sc, ARC_RE_INB_DOORBELL, 
sc->out_doorbell);
+                       }
+/*                     if (val & ARC_RE_I2D_DATA_READ_OK) {
+                               sc->out_doorbell ^= ARC_RE_D2I_DATA_WRITE_OK;
+                               arc_write(sc, ARC_RE_INB_DOORBELL, 
sc->out_doorbell);
+                       }
+*/
+                       if (val & ARC_RE_I2D_MESSAGE_CMD_DONE) {
+                               obmsg = arc_read(sc, ARC_RE_MSG_RWBUF);
+                               if (obmsg == ARC_FWINFO_SIGNATURE_GET_CONFIG)
+                                       ;       /* handle devices hot-plug */
+                       }
+
+               }
+       }
+
+       if (intrstat & ARC_RE_INTR_STAT_POSTQUEUE) {
+               u_int16_t       cmdSMID;
+               u_int16_t       doneq_index;
+               ret = 1;
+               bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
+                   sc->cmdQ_ptr_offset, ARC_HBE_COMPLETION_Q_LEN,
+                   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+               while (arc_read(sc, ARC_RE_INTR_STAT) & 
ARC_RE_INTR_STAT_POSTQUEUE) {
+                       doneq_index = sc->doneq_index;
+                       if ((arc_read(sc, ARC_RE_REPLY_PRODUCER_INDEX) & 
0xFFFF) != doneq_index) {
+                               cmdSMID = sc->pmuE[doneq_index].cmdSMID;
+                               ccb = &sc->sc_ccbs[cmdSMID];
+                               bus_dmamap_sync(sc->sc_dmat, 
ARC_DMA_MAP(sc->sc_requests),
+                                   ccb->cmd_dma_offset, ARC_IO_CMD_LEN,
+                                   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+                               error = sc->pmuE[doneq_index].cmdFlag & 
ARC_RE_REPLY_QUEUE_ERR;
+                               arc_scsi_cmd_done(sc, ccb, error);
+                               doneq_index++;
+                               if (doneq_index >= sc->doneq_entry)
+                                       doneq_index = 0;
+                               sc->doneq_index = doneq_index;
+                               arc_write(sc, ARC_RE_REPLY_CONSUMER_INDEX, 
doneq_index);
+                       }
+               }
+       }
+
+       return (ret);
+}
+
+
+int
 arc_intr(void *arg)
 {
        struct arc_softc        *sc = arg;
@@ -1104,12 +1436,18 @@ arc_intr(void *arg)
        case ARC_HBA_TYPE_A:
                ret = arc_intr_A(arg);
                break;
+       case ARC_HBA_TYPE_B:
+               ret = arc_intr_B(arg);
+               break;
        case ARC_HBA_TYPE_C:
                ret = arc_intr_C(arg);
                break;
        case ARC_HBA_TYPE_D:
                ret = arc_intr_D(arg);
                break;
+       case ARC_HBA_TYPE_E:
+               ret = arc_intr_E(arg);
+               break;
        }
        return (ret);
 }
@@ -1123,10 +1461,6 @@ arc_scsi_cmd(struct scsi_xfer *xs)
        struct arc_msg_scsicmd          *cmd;
        u_int32_t                       reg, cdb_len;
        int                             s;
-       struct arc_HBD_Msgu *pmu;
-       u_int16_t index_stripped;
-       u_int16_t postq_index;
-       struct InBound_SRB *pinbound_srb;
 
        if (xs->cmdlen > ARC_MSG_CDBLEN) {
                bzero(&xs->sense, sizeof(xs->sense));
@@ -1149,7 +1483,7 @@ arc_scsi_cmd(struct scsi_xfer *xs)
 
        cmd = &ccb->ccb_cmd->cmd;
        reg = ccb->ccb_cmd_post;
-       ccb->ccb_cmd->ccb = ccb;
+       ccb->ccb_cmd->ccb_id = ccb->ccb_id;
        /* bus is always 0 */
        cmd->target = link->target;
        cmd->lun = link->lun;
@@ -1170,7 +1504,7 @@ arc_scsi_cmd(struct scsi_xfer *xs)
 
        /* we've built the command, let's put it on the hw */
        bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
-           ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
+           ccb->cmd_dma_offset, ARC_IO_CMD_LEN,
            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
        s = splbio();
@@ -1180,6 +1514,21 @@ arc_scsi_cmd(struct scsi_xfer *xs)
                        reg |= ARC_RA_POST_QUEUE_BIGFRAME;
                arc_write(sc, ARC_RA_POST_QUEUE, reg);
                break;
+       case ARC_HBA_TYPE_B: {
+               struct arc_HBB_Msgu *pmuB = sc->pmuB;
+               u_int32_t ending_index, index = pmuB->postq_index;
+
+               ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE);
+               pmuB->post_qbuffer[ending_index] = 0;
+               if (cmd->flags & ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512)
+                       reg |= ARC_RA_POST_QUEUE_BIGFRAME;
+               pmuB->post_qbuffer[index] = reg;
+               index++;
+               index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number 
set it to 0 */
+               pmuB->postq_index = index;
+               arc_write(sc, sc->inb_doorbell, ARC_RB_D2I_CDB_POSTED);
+               break;
+               }
        case ARC_HBA_TYPE_C:
                cdb_len = sizeof(struct arc_msg_scsicmd) +
                        sizeof(struct arc_sge) * ccb->ccb_dmamap->dm_nsegs;
@@ -1190,31 +1539,48 @@ arc_scsi_cmd(struct scsi_xfer *xs)
                        arc_write(sc, ARC_RC_INB_POSTQ_HIGH, 
sc->sc_ccb_phys_hi);
                arc_write(sc, ARC_RC_INB_POSTQ_LOW, reg);
                break;
-       case ARC_HBA_TYPE_D:
-                       pmu = sc->pmu;
-                       postq_index = pmu->postq_index;
-                       pinbound_srb = (struct InBound_SRB 
*)&pmu->post_qbuffer[postq_index & 0xFF];
+       case ARC_HBA_TYPE_D: {
+               struct arc_HBD_Msgu *pmu;
+               u_int16_t index_stripped;
+               u_int16_t postq_index;
+               struct InBound_SRB *pinbound_srb;
+               pmu = sc->pmu;
+               postq_index = pmu->postq_index;
+               pinbound_srb = (struct InBound_SRB 
*)&pmu->post_qbuffer[postq_index & 0xFF];
 
-                       pinbound_srb->addressHigh = sc->sc_ccb_phys_hi;
-                       pinbound_srb->addressLow = ccb->ccb_cmd_post;
-                       pinbound_srb->length = ccb->arc_io_cmd_length >> 2;
-                       cmd->context = ccb->ccb_cmd_post;
-                       if (postq_index & 0x4000) {
-                               index_stripped = postq_index & 0xFF;
-                               index_stripped += 1;
-                               index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
-                               pmu->postq_index = index_stripped ? 
(index_stripped | 0x4000) : index_stripped;
-                       } else {
-                               index_stripped = postq_index;
-                               index_stripped += 1;
-                               index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
-                               pmu->postq_index = index_stripped ? 
index_stripped : (index_stripped | 0x4000);
-                       }
-                       bus_dmamap_sync(sc->sc_dmat, 
ARC_DMA_MAP(sc->sc_requests),
-                           sc->cmdQ_ptr_offset, ARC_MAX_CMDQ_PTR_LEN,
-                           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-                       arc_write(sc, ARC_RD_INB_WRITE_PTR, postq_index);
+               pinbound_srb->addressHigh = sc->sc_ccb_phys_hi;
+               pinbound_srb->addressLow = ccb->ccb_cmd_post;
+               pinbound_srb->length = ccb->arc_io_cmd_length >> 2;
+               cmd->context = ccb->ccb_cmd_post;
+               if (postq_index & 0x4000) {
+                       index_stripped = postq_index & 0xFF;
+                       index_stripped += 1;
+                       index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
+                       pmu->postq_index = index_stripped ? (index_stripped | 
0x4000) : index_stripped;
+               } else {
+                       index_stripped = postq_index;
+                       index_stripped += 1;
+                       index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
+                       pmu->postq_index = index_stripped ? index_stripped : 
(index_stripped | 0x4000);
+               }
+               bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
+                   sc->cmdQ_ptr_offset, ARC_HBD_CMDQ_PTR_LEN,
+                   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+               arc_write(sc, ARC_RD_INB_WRITE_PTR, postq_index);
                break;
+               }
+       case ARC_HBA_TYPE_E:
+               cdb_len = sizeof(struct arc_msg_scsicmd) +
+                   sizeof(struct arc_sge) * ccb->ccb_dmamap->dm_nsegs;
+               if (cdb_len > 0x300)
+                       cdb_len = 0x300;
+               reg = ccb->smid | ((cdb_len - 1) >> 6);
+               bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
+                   sc->cmdQ_ptr_offset, ARC_HBE_COMPLETION_Q_LEN,
+                   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+               arc_write(sc, ARC_RE_INB_POSTQ_HIGH, 0);
+               arc_write(sc, ARC_RE_INB_POSTQ_LOW, reg);
+               break;
        }
        if (xs->flags & SCSI_POLL) {
                if (arc_complete(sc, ccb, xs->timeout) != 0) {
@@ -1334,7 +1700,6 @@ arc_complete(struct arc_softc *sc, struct arc_ccb *ncc
        struct arc_io_cmd               *cmd;
        u_int32_t                       reg, error, write_ptr;
        u_int16_t       doneq_index;
-       struct arc_HBD_Msgu *phbdmu;
        int             ret = 0;
 
        arc_disable_all_intr(sc);
@@ -1344,11 +1709,27 @@ arc_complete(struct arc_softc *sc, struct arc_ccb *ncc
                        reg = arc_read(sc, ARC_RA_REPLY_QUEUE);
                        error = (reg & ARC_RA_REPLY_QUEUE_ERR)? 1:0;
                        break;
+               case ARC_HBA_TYPE_B: {
+                       struct arc_HBB_Msgu *pmuB = sc->pmuB;
+                       doneq_index = pmuB->doneq_index;
+                       reg = pmuB->done_qbuffer[doneq_index];
+                       if ( reg == 0) {
+                               reg = 0xffffffff;
+                               break;
+                       }
+                       pmuB->done_qbuffer[doneq_index] = 0;
+                       doneq_index++;
+                       doneq_index %= ARCMSR_MAX_HBB_POSTQUEUE;
+                       pmuB->doneq_index = doneq_index;
+                       error = (reg & ARC_RB_REPLY_QUEUE_ERR)? 1:0;
+                       break;
+                       }
                case ARC_HBA_TYPE_C:
                        reg = arc_read(sc, ARC_RC_OUTB_REPLYQ_LOW);
                        error = (reg & ARC_RC_REPLY_QUEUE_ERR);
                        break;
-               case ARC_HBA_TYPE_D:
+               case ARC_HBA_TYPE_D: {
+                       struct arc_HBD_Msgu *phbdmu;
                        phbdmu = sc->pmu;
                        write_ptr = phbdmu->done_qbuffer[0].addressLow;
                        doneq_index = phbdmu->doneq_index;
@@ -1365,6 +1746,26 @@ Loop0:
                        }
                        error = (reg & ARC_RD_REPLY_QUEUE_ERR);
                        break;
+                       }
+               case ARC_HBA_TYPE_E: {
+                       u_int16_t       cmdSMID;
+                       u_int16_t       doneq_index;
+                       doneq_index = sc->doneq_index;
+                       if ((arc_read(sc, ARC_RE_REPLY_PRODUCER_INDEX) & 
0xFFFF) == doneq_index)
+                               reg = 0xffffffff;
+                       else {
+                               cmdSMID = sc->pmuE[doneq_index].cmdSMID;
+                               ccb = &sc->sc_ccbs[cmdSMID];
+                               error = sc->pmuE[doneq_index].cmdFlag & 
ARC_RE_REPLY_QUEUE_ERR;
+                               doneq_index++;
+                               if (doneq_index >= sc->doneq_entry)
+                                       doneq_index = 0;
+                               sc->doneq_index = doneq_index;
+                               arc_write(sc, ARC_RE_REPLY_CONSUMER_INDEX, 
doneq_index);
+                               reg = 0;
+                       }
+                       break;
+                       }
                }
                if (reg == 0xffffffff) {
                        if (timeout-- == 0) {
@@ -1376,20 +1777,24 @@ Loop0:
 
                switch(sc->sc_adp_type) {
                case ARC_HBA_TYPE_A:
+               case ARC_HBA_TYPE_B:
                        cmd = (struct arc_io_cmd *)(kva +
                        ((reg << ARC_RA_REPLY_QUEUE_ADDR_SHIFT) -
                        ARC_DMA_DVA(sc->sc_requests)));
-                   break;
+                       break;
                case ARC_HBA_TYPE_C:
                case ARC_HBA_TYPE_D:
                        cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFE0) -
-                       ARC_DMA_DVA(sc->sc_requests)));
-                   break;
+                           ARC_DMA_DVA(sc->sc_requests)));
+                       break;
+               case ARC_HBA_TYPE_E:
+                       cmd = ccb->ccb_cmd;
+                       break;
                }
-               ccb = cmd->ccb;
+               ccb = &sc->sc_ccbs[cmd->ccb_id];
 
                bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
-                   ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
+                   ccb->cmd_dma_offset, ARC_IO_CMD_LEN,
                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
                arc_scsi_cmd_done(sc, ccb, error);
@@ -1411,6 +1816,10 @@ arc_enable_all_intr(struct arc_softc *sc)
                        ARC_RA_INTRMASK_DOORBELL | ARC_RA_INTRMASK_MSG0);
                arc_write(sc, ARC_RA_INTRMASK, int_mask);
            break;
+       case ARC_HBA_TYPE_B:
+               int_mask = sc->sc_int_mask | ARC_RB_I2D_INTR_ENABLE_DOORBELL;
+               arc_write(sc, sc->outb_doorbell_mask, int_mask);
+               break;
        case ARC_HBA_TYPE_C:
                int_mask = arc_read(sc, ARC_RC_INTR_MASK);
                int_mask &= ~(ARC_RC_INTR_MASK_POSTQUEUE |
@@ -1422,6 +1831,12 @@ arc_enable_all_intr(struct arc_softc *sc)
                int_mask |= ARC_RD_INTR_ENABLE_ALL;
                arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
            break;
+       case ARC_HBA_TYPE_E:
+               int_mask = arc_read(sc, ARC_RE_INTR_MASK);
+               int_mask &= ~(ARC_RE_INTR_MASK_POSTQUEUE |
+                   ARC_RE_INTR_MASK_DOORBELL);
+               arc_write(sc, ARC_RE_INTR_MASK, int_mask);
+           break;
        }
 }
 
@@ -1436,6 +1851,11 @@ arc_disable_all_intr(struct arc_softc *sc)
                int_mask |= ARC_RA_INTR_MASK_ALL;
                arc_write(sc, ARC_RA_INTRMASK, int_mask);
                break;
+       case ARC_HBA_TYPE_B:
+               int_mask = arc_read(sc, sc->outb_doorbell_mask);
+               arc_write(sc, sc->outb_doorbell_mask, 0);
+               sc->sc_int_mask = int_mask;
+               break;
        case ARC_HBA_TYPE_C:
                int_mask = arc_read(sc, ARC_RC_INTR_MASK);
                int_mask |= ARC_RC_INTR_MASK_ALL;
@@ -1444,8 +1864,13 @@ arc_disable_all_intr(struct arc_softc *sc)
        case ARC_HBA_TYPE_D:
                int_mask = arc_read(sc, ARC_RD_INTR_ENABLE);
                int_mask &= ~ARC_RD_INTR_ENABLE_ALL;
-               arc_write(sc, ARC_RD_INTR_ENABLE, ARC_RD_INTR_DISABLE_ALL);
+               arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
                break;
+       case ARC_HBA_TYPE_E:
+               int_mask = arc_read(sc, ARC_RE_INTR_MASK);
+               int_mask |= ARC_RE_INTR_MASK_ALL;
+               arc_write(sc, ARC_RE_INTR_MASK, int_mask);
+               break;
        }
 }
 
@@ -1463,16 +1888,33 @@ arc_map_pci_resources(struct arc_softc *sc, struct pci
                case ARC_HBA_TYPE_A:
                memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, 
ARC_RA_PCI_BAR);
                if (pci_mapreg_map(pa, ARC_RA_PCI_BAR, memtype, 0, &sc->sc_iot,
-               &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
+                   &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
                        printf(": unable to map ARC_HBA_TYPE_A system"
                                " interface register\n");
                        return(1);
                }
                break;
+               case ARC_HBA_TYPE_B:
+               memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, 
ARC_RB_DOORBELL_BAR);
+               if (pci_mapreg_map(pa, ARC_RB_DOORBELL_BAR, memtype, 0, 
&sc->sc_iot,
+                   &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
+                       printf(": unable to map ARC_HBA_TYPE_B system"
+                           " interface register\n");
+                       return(1);
+               }
+               memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, 
ARC_RB_RWBUFFER_BAR);
+               if (pci_mapreg_map(pa, ARC_RB_RWBUFFER_BAR, memtype, 0, 
&sc->sc_msgt,
+                   &sc->sc_msgh, NULL, &sc->sc_msgs, 0) != 0) {
+                       printf(": unable to map ARC_HBA_TYPE_B buffer"
+                           " interface register\n");
+                       bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
+                       return(1);
+               }
+               break;
                case ARC_HBA_TYPE_C:
                memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, 
ARC_RC_PCI_BAR);
                if (pci_mapreg_map(pa, ARC_RC_PCI_BAR, memtype, 0, &sc->sc_iot,
-               &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
+                   &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
                        printf(": unable to map ARC_HBA_TYPE_C system"
                                " interface register\n");
                        return(1);
@@ -1481,12 +1923,25 @@ arc_map_pci_resources(struct arc_softc *sc, struct pci
                case ARC_HBA_TYPE_D:
                memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, 
ARC_RD_PCI_BAR);
                if (pci_mapreg_map(pa, ARC_RD_PCI_BAR, memtype, 0, &sc->sc_iot,
-               &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
+                   &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
                        printf(": unable to map ARC_HBA_TYPE_D system"
                                " interface register\n");
                        return(1);
                }
                break;
+               case ARC_HBA_TYPE_E:
+               memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, 
ARC_RE_PCI_BAR);
+               if (pci_mapreg_map(pa, ARC_RE_PCI_BAR, memtype, 0, &sc->sc_iot,
+                   &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
+                       printf(": unable to map ARC_HBA_TYPE_E system"
+                           " interface register\n");
+                       return(1);
+               }
+               arc_write(sc, ARC_RE_INTR_STAT, 0);
+               arc_write(sc, ARC_RE_OUTB_DOORBELL, ARC_RE_DOORBELL_SYNC);
+               sc->in_doorbell = 0;
+               sc->out_doorbell = 0;
+               break;
        }
 
        arc_disable_all_intr(sc);
@@ -1506,8 +1961,7 @@ arc_map_pci_resources(struct arc_softc *sc, struct pci
        return (0);
 
 unmap:
-       bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
-       sc->sc_ios = 0;
+       arc_unmap_pci_resources(sc);
        return (1);
 }
 
@@ -1516,119 +1970,116 @@ arc_unmap_pci_resources(struct arc_softc *sc)
 {
        pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
        bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
+       if (sc->sc_adp_type == ARC_HBA_TYPE_B)
+               bus_space_unmap(sc->sc_msgt, sc->sc_msgh, sc->sc_msgs);
        sc->sc_ios = 0;
 }
 
-int
-arc_chipA_firmware(struct arc_softc *sc)
+void
+arc_clear_doorbell_qbuffer(struct arc_softc *sc)
 {
-       struct arc_msg_firmware_info    fwinfo;
-       char                            string[81]; /* sizeof(vendor)*2+1 */
-       u_int32_t       ob_doorbell;
+       u_int32_t       ob_doorbell, i, tmp;
 
-       if (arc_wait_eq(sc, ARC_RA_OUTB_ADDR1, ARC_RA_OUTB_ADDR1_FIRMWARE_OK,
-           ARC_RA_OUTB_ADDR1_FIRMWARE_OK) != 0) {
-               printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
-               return (1);
+       switch(sc->sc_adp_type) {
+       case ARC_HBA_TYPE_A:
+               ob_doorbell = arc_read(sc, ARC_RA_OUTB_DOORBELL);
+               arc_write(sc, ARC_RA_OUTB_DOORBELL, ob_doorbell);
+               arc_write(sc, ARC_RA_INB_DOORBELL, ARC_RA_INB_DOORBELL_READ_OK);
+               for (i = 0; i < 200; i++) {
+                       delay(20000);
+                       ob_doorbell = arc_read(sc, ARC_RA_OUTB_DOORBELL);
+                       if (ob_doorbell & ARC_RA_OUTB_DOORBELL_WRITE_OK) {
+                               arc_write(sc, ARC_RA_OUTB_DOORBELL, 
ob_doorbell);
+                               arc_write(sc, ARC_RA_INB_DOORBELL,
+                                   ARC_RA_INB_DOORBELL_READ_OK);
+                       } else
+                               break;
+               }
+               break;
+       case ARC_HBA_TYPE_B:
+               arc_write(sc, sc->outb_doorbell, 
ARC_RB_DOORBELL_INT_CLEAR_PATTERN);
+               arc_write(sc, sc->inb_doorbell, ARC_RB_D2I_DATA_READ_OK);
+               for (i = 0; i < 200; i++) {
+                       delay(20000);
+                       if (arc_read(sc, sc->outb_doorbell) & 
ARC_RB_I2D_DATA_WRITE_OK) {
+                               arc_write(sc, sc->outb_doorbell,
+                                   ARC_RB_DOORBELL_INT_CLEAR_PATTERN);
+                               arc_write(sc, sc->inb_doorbell,
+                                   ARC_RB_D2I_DATA_READ_OK);
+                       } else
+                               break;
+               }
+               break;
+       case ARC_HBA_TYPE_C:
+               ob_doorbell = arc_read(sc, ARC_RC_OUTB_DOORBELL);
+               arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, ob_doorbell);
+               arc_write(sc, ARC_RC_INB_DOORBELL, ARC_RC_D2I_DATA_READ_OK);
+               for (i = 0; i < 200; i++) {
+                       delay(20000);
+                       ob_doorbell = arc_read(sc, ARC_RC_OUTB_DOORBELL);
+                       if (ob_doorbell & ARC_RC_I2D_DATA_WRITE_OK) {
+                               arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR,
+                                   ob_doorbell);
+                               arc_write(sc, ARC_RC_INB_DOORBELL,
+                                   ARC_RC_D2I_DATA_READ_OK);
+                       } else
+                               break;
+               }
+               break;
+       case ARC_HBA_TYPE_D:
+               ob_doorbell = arc_read(sc, ARC_RD_OUTB_DOORBELL);
+               arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, ob_doorbell);
+               arc_write(sc, ARC_RD_INB_DOORBELL, ARC_RD_D2I_DATA_READ_OK);
+               for (i = 0; i < 200; i++) {
+                       delay(20000);
+                       ob_doorbell = arc_read(sc, ARC_RD_OUTB_DOORBELL);
+                       if (ob_doorbell & ARC_RD_I2D_DATA_WRITE_OK) {
+                               arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR,
+                                   ob_doorbell);
+                               arc_write(sc, ARC_RD_INB_DOORBELL,
+                                   ARC_RD_D2I_DATA_READ_OK);
+                       } else
+                               break;
+               }
+               break;
+       case ARC_HBA_TYPE_E:
+               sc->in_doorbell = arc_read(sc, ARC_RE_OUTB_DOORBELL);
+               arc_write(sc, ARC_RE_INTR_STAT, 0);
+               sc->out_doorbell ^= ARC_RE_D2I_DATA_READ_OK;
+               arc_write(sc, ARC_RE_INB_DOORBELL, sc->out_doorbell);
+               for (i = 0; i < 200; i++) {
+                       delay(20000);
+                       tmp = sc->in_doorbell;
+                       sc->in_doorbell = arc_read(sc, ARC_RE_OUTB_DOORBELL);
+                       if ((tmp ^ sc->in_doorbell) & ARC_RE_I2D_DATA_WRITE_OK) 
{
+                               arc_write(sc, ARC_RE_INTR_STAT, 0);
+                               sc->out_doorbell ^= ARC_RE_D2I_DATA_READ_OK;
+                               arc_write(sc, ARC_RE_INB_DOORBELL, 
sc->out_doorbell);
+                       } else
+                               break;
+               }
+               break;
        }
-
-       if (arc_msg0(sc, ARC_RA_INB_MSG0_GET_CONFIG) != 0) {
-               printf("%s: timeout waiting for get config\n", DEVNAME(sc));
-               return (1);
-       }
-
-       arc_read_region(sc, ARC_RA_MSGBUF, &fwinfo, sizeof(fwinfo));
-
-       DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
-           letoh32(fwinfo.signature));
-
-       if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
-               printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
-               return (1);
-       }
-
-       DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.request_len));
-       DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.queue_len));
-       DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.sdram_size));
-       DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
-
-       scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
-       DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
-       scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
-       DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
-
-       scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
-       DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
-
-       if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
-               printf("%s: unexpected request frame size (%d != %d)\n",
-                   DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
-               return (1);
-       }
-
-       sc->sc_req_count = letoh32(fwinfo.queue_len);
-
-       if (arc_msg0(sc, ARC_RA_INB_MSG0_START_BGRB) != 0) {
-               printf("%s: timeout waiting to start bg rebuild\n",
-                   DEVNAME(sc));
-               return (1);
-       }
-
-       /* clear doorbell buffer */
-       ob_doorbell = arc_read(sc, ARC_RA_OUTB_DOORBELL);
-       arc_write(sc, ARC_RA_OUTB_DOORBELL, ob_doorbell);
-       arc_write(sc, ARC_RA_INB_DOORBELL, ARC_RA_INB_DOORBELL_READ_OK);
-
-       printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
-           DEVNAME(sc), letoh32(fwinfo.sata_ports),
-           letoh32(fwinfo.sdram_size), string);
-
-       return (0);
 }
 
 int
-arc_chipB_firmware(struct arc_softc *sc)
+arc_query_firmware(struct arc_softc *sc)
 {
-       if (arc_wait_eq(sc, ARC_RB_IOP2DRV_DOORBELL,
-           ARC_RA_OUTB_ADDR1_FIRMWARE_OK,
-           ARC_RA_OUTB_ADDR1_FIRMWARE_OK) != 0) {
-               printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
-               return (1);
-       }
-
-       return (1);
-}
-
-int
-arc_chipC_firmware(struct arc_softc *sc)
-{
        struct arc_msg_firmware_info    fwinfo;
-       char    string[81]; /* sizeof(vendor)*2+1 */
-       u_int32_t       ob_doorbell;
+       char    adapter_model[sizeof(fwinfo.model)+1]={0};
+       char    fw_version[sizeof(fwinfo.fw_version)+1]={0};
 
-       if (arc_wait_eq(sc, ARC_RC_OUTB_MSGADDR1, ARC_RC_OUTB_MSG_FIRMWARE_OK,
-           ARC_RC_OUTB_MSG_FIRMWARE_OK) != 0) {
-               printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
-               return (1);
-       }
-
-       if (arc_msg0(sc, ARC_RC_INB_MSG0_GET_CONFIG) != 0) {
+       if (arc_get_firmware_config(sc, &fwinfo)) {
                printf("%s: timeout waiting for get config\n", DEVNAME(sc));
-               return (1);
+               return 1;
        }
 
-       arc_read_region(sc, ARC_RC_MSG_RWBUF, &fwinfo, sizeof(fwinfo));
-
        DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
            letoh32(fwinfo.signature));
 
        if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
                printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
-               return (1);
+               return 1;
        }
 
        DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
@@ -1638,114 +2089,83 @@ arc_chipC_firmware(struct arc_softc *sc)
        DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
            letoh32(fwinfo.sdram_size));
        DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
+           letoh32(fwinfo.sata_ports));
 
-       scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
-       DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
-       scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
-       DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
+       scsi_strvis(adapter_model, fwinfo.model, sizeof(fwinfo.model));
+       scsi_strvis(fw_version, fwinfo.fw_version, sizeof(fwinfo.fw_version));
 
-       scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
-       DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
-
        if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
                printf("%s: unexpected request frame size (%d != %d)\n",
                    DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
-               return (1);
+               return 1;
        }
 
        sc->sc_req_count = letoh32(fwinfo.queue_len);
 
-       if (arc_msg0(sc, ARC_RC_INB_MSG0_START_BGRB) != 0) {
-               printf("%s: timeout waiting to start bg rebuild\n",
-                   DEVNAME(sc));
-               return (1);
-       }
+       printf("%s: %s, %s, F/W: %s\n", DEVNAME(sc), ARC_VERSION,
+           adapter_model, fw_version);
 
-       /* clear doorbell buffer */
-       ob_doorbell = arc_read(sc, ARC_RC_OUTB_DOORBELL);
-       arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, ob_doorbell);
-       arc_write(sc, ARC_RC_INB_DOORBELL, ARC_RC_D2I_DATA_READ_OK);
-
-       printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
-           DEVNAME(sc), letoh32(fwinfo.sata_ports),
-           letoh32(fwinfo.sdram_size), string);
-
-       return (0);
+       return 0;
 }
 
 int
-arc_chipD_firmware(struct arc_softc *sc)
+arc_get_firmware_config(struct arc_softc *sc, struct arc_msg_firmware_info 
*fwinfo)
 {
-       struct arc_msg_firmware_info    fwinfo;
-       char    string[81]; /* sizeof(vendor)*2+1 */
-       u_int32_t       ob_doorbell;
+       int     ready = 1;
 
-       if (arc_wait_eq(sc, ARC_RD_OUTB_MSGADDR1, ARC_RD_OUTB_MSG_FIRMWARE_OK,
-           ARC_RD_OUTB_MSG_FIRMWARE_OK) != 0) {
-               printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
-               return (1);
+       switch(sc->sc_adp_type) {
+       case ARC_HBA_TYPE_A:
+               ready = arc_msg0(sc, ARC_RA_INB_MSG0_GET_CONFIG);
+               if (!ready)
+                       arc_read_region(sc, ARC_RA_MSGBUF, fwinfo, 
sizeof(*fwinfo));
+               break;
+       case ARC_HBA_TYPE_B:
+               ready = arc_msg0(sc, ARC_RB_INB_MSG0_GET_CONFIG);
+               if (!ready)
+                       arc_read_region2(sc, ARC_RB_MSG_RWBUF, fwinfo, 
sizeof(*fwinfo));
+               break;
+       case ARC_HBA_TYPE_C:
+               ready = arc_msg0(sc, ARC_RC_INB_MSG0_GET_CONFIG);
+               if (!ready)
+                       arc_read_region(sc, ARC_RC_MSG_RWBUF, fwinfo, 
sizeof(*fwinfo));
+               break;
+       case ARC_HBA_TYPE_D:
+               ready = arc_msg0(sc, ARC_RD_INB_MSG0_GET_CONFIG);
+               if (!ready)
+                       arc_read_region(sc, ARC_RD_MSG_RWBUF, fwinfo, 
sizeof(*fwinfo));
+               break;
+       case ARC_HBA_TYPE_E:
+               ready = arc_msg0(sc, ARC_RE_INB_MSG0_GET_CONFIG);
+               if (!ready)
+                       arc_read_region(sc, ARC_RE_MSG_RWBUF, fwinfo, 
sizeof(*fwinfo));
+               break;
        }
+       return ready;
+}
 
-       if ((arc_read(sc, ARC_RD_OUTB_DOORBELL) & ARC_RD_I2D_MESSAGE_CMD_DONE))
-               arc_write(sc, ARC_RD_OUTB_DOORBELL, 
ARC_RD_I2D_MESSAGE_CMD_DONE_CLEAR);
+int
+arc_start_bkgrnd_rebuild(struct arc_softc *sc)
+{
+       int     ready = 1;
 
-       if (arc_msg0(sc, ARC_RD_INB_MSG0_GET_CONFIG) != 0) {
-               printf("%s: timeout waiting for get config\n", DEVNAME(sc));
-               return (1);
+       switch(sc->sc_adp_type) {
+       case ARC_HBA_TYPE_A:
+               ready = arc_msg0(sc, ARC_RA_INB_MSG0_START_BGRB);
+               break;
+       case ARC_HBA_TYPE_B:
+               ready = arc_msg0(sc, ARC_RB_INB_MSG0_START_BGRB);
+               break;
+       case ARC_HBA_TYPE_C:
+               ready = arc_msg0(sc, ARC_RC_INB_MSG0_START_BGRB);
+               break;
+       case ARC_HBA_TYPE_D:
+               ready = arc_msg0(sc, ARC_RD_INB_MSG0_START_BGRB);
+               break;
+       case ARC_HBA_TYPE_E:
+               ready = arc_msg0(sc, ARC_RE_INB_MSG0_START_BGRB);
+               break;
        }
-
-       arc_read_region(sc, ARC_RD_MSG_RWBUF, &fwinfo, sizeof(fwinfo));
-
-       DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
-           letoh32(fwinfo.signature));
-
-       if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
-               printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
-               return (1);
-       }
-
-       DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.request_len));
-       DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.queue_len));
-       DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.sdram_size));
-       DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
-           letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
-
-       scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
-       DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
-       scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
-       DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
-
-       scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
-       DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
-
-       if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
-               printf("%s: unexpected request frame size (%d != %d)\n",
-                   DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
-               return (1);
-       }
-
-       sc->sc_req_count = letoh32(fwinfo.queue_len) - 1;
-
-       if (arc_msg0(sc, ARC_RD_INB_MSG0_START_BGRB) != 0) {
-               printf("%s: timeout waiting to start bg rebuild\n",
-                   DEVNAME(sc));
-               return (1);
-       }
-
-       /* clear doorbell buffer */
-       ob_doorbell = arc_read(sc, ARC_RD_OUTB_DOORBELL);
-       arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, ob_doorbell);
-       arc_write(sc, ARC_RD_INB_DOORBELL, ARC_RD_D2I_DATA_READ_OK);
-
-       printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
-           DEVNAME(sc), letoh32(fwinfo.sata_ports),
-           letoh32(fwinfo.sdram_size), string);
-
-       return (0);
+       return ready;
 }
 
 void
@@ -1757,6 +2177,11 @@ arc_stop_bgrb_proc(struct arc_softc *sc)
                        printf("%s: timeout waiting to stop bg rebuild\n",
                                DEVNAME(sc));
                break;
+       case ARC_HBA_TYPE_B:
+               if (arc_msg0(sc, ARC_RB_INB_MSG0_STOP_BGRB) != 0)
+                       printf("%s: timeout waiting to stop bg rebuild\n",
+                               DEVNAME(sc));
+               break;
        case ARC_HBA_TYPE_C:
                if (arc_msg0(sc, ARC_RC_INB_MSG0_STOP_BGRB) != 0)
                        printf("%s: timeout waiting to stop bg rebuild\n",
@@ -1767,6 +2192,11 @@ arc_stop_bgrb_proc(struct arc_softc *sc)
                        printf("%s: timeout waiting to stop bg rebuild\n",
                                DEVNAME(sc));
                break;
+       case ARC_HBA_TYPE_E:
+               if (arc_msg0(sc, ARC_RE_INB_MSG0_STOP_BGRB) != 0)
+                       printf("%s: timeout waiting to stop bg rebuild\n",
+                               DEVNAME(sc));
+               break;
        }
 }
 
@@ -1779,6 +2209,11 @@ arc_flush_cache(struct arc_softc *sc)
                        printf("%s: timeout waiting to flush cache\n",
                                DEVNAME(sc));
                break;
+       case ARC_HBA_TYPE_B:
+               if (arc_msg0(sc, ARC_RB_INB_MSG0_FLUSH_CACHE) != 0)
+                       printf("%s: timeout waiting to flush cache\n",
+                               DEVNAME(sc));
+               break;
        case ARC_HBA_TYPE_C:
                if (arc_msg0(sc, ARC_RC_INB_MSG0_FLUSH_CACHE) != 0)
                        printf("%s: timeout waiting to flush cache\n",
@@ -1789,6 +2224,11 @@ arc_flush_cache(struct arc_softc *sc)
                        printf("%s: timeout waiting to flush cache\n",
                                DEVNAME(sc));
                break;
+       case ARC_HBA_TYPE_E:
+               if (arc_msg0(sc, ARC_RE_INB_MSG0_FLUSH_CACHE) != 0)
+                       printf("%s: timeout waiting to flush cache\n",
+                               DEVNAME(sc));
+               break;
        }
 }
 
@@ -1802,12 +2242,26 @@ arc_iop_set_conf(struct arc_softc *sc)
        switch (sc->sc_adp_type) {
        case ARC_HBA_TYPE_A:
                arc_write(sc, ARC_RA_MSGBUF, ARC_FWINFO_SIGNATURE_SET_CONFIG);
-               arc_write(sc, ARC_RA_MSGBUF+1, ccb_phys_hi);
+               arc_write(sc, ARC_RA_MSGBUF+4, ccb_phys_hi);
                arc_msg0(sc, ARC_RA_INB_MSG0_SET_CONFIG);
                break;
+       case ARC_HBA_TYPE_B: {
+               struct arc_HBB_Msgu *pmuB = sc->pmuB;
+               pmuB->postq_index = 0;
+               pmuB->doneq_index = 0;
+               arc_msg0(sc, ARC_RB_INB_MSG0_SET_POST_WINDOW);
+               arc_write2(sc, ARC_RB_MSG_RWBUF, 
ARC_FWINFO_SIGNATURE_SET_CONFIG);
+               arc_write2(sc, ARC_RB_MSG_RWBUF+4, ccb_phys_hi);
+               arc_write2(sc, ARC_RB_MSG_RWBUF+8, sc->postQ_buffer);
+               arc_write2(sc, ARC_RB_MSG_RWBUF+12, sc->doneQ_buffer);
+               arc_write2(sc, ARC_RB_MSG_RWBUF+16, 1056);
+               arc_msg0(sc, ARC_RB_INB_MSG0_SET_CONFIG);
+               arc_msg0(sc, ARC_RB_INB_MSG0_START_DRIVER_MODE);
+               break;
+               }
        case ARC_HBA_TYPE_C:
                arc_write(sc, ARC_RC_MSG_RWBUF, 
ARC_FWINFO_SIGNATURE_SET_CONFIG);
-               arc_write(sc, ARC_RC_MSG_RWBUF+1, ccb_phys_hi);
+               arc_write(sc, ARC_RC_MSG_RWBUF+4, ccb_phys_hi);
                arc_msg0(sc, ARC_RC_INB_MSG0_SET_CONFIG);
                break;
        case ARC_HBA_TYPE_D:
@@ -1821,6 +2275,17 @@ arc_iop_set_conf(struct arc_softc *sc)
                arc_write(sc, ARC_RD_MSG_RWBUF+16, 0x100);
                arc_msg0(sc, ARC_RD_INB_MSG0_SET_CONFIG);
                break;
+       case ARC_HBA_TYPE_E:
+               arc_write(sc, ARC_RC_MSG_RWBUF, 
ARC_FWINFO_SIGNATURE_SET_CONFIG);
+               arc_write(sc, ARC_RC_MSG_RWBUF+4, ARC_SIGNATURE_1884);
+               arc_write(sc, ARC_RC_MSG_RWBUF+8, sc->sc_ccb_phys_lo);
+               arc_write(sc, ARC_RC_MSG_RWBUF+12, sc->sc_ccb_phys_hi);
+               arc_write(sc, ARC_RC_MSG_RWBUF+16, ARC_IO_CMD_LEN);
+               arc_write(sc, ARC_RC_MSG_RWBUF+20, sc->doneq_phys_lo);
+               arc_write(sc, ARC_RC_MSG_RWBUF+24, sc->doneq_phys_hi);
+               arc_write(sc, ARC_RC_MSG_RWBUF+28, ARC_HBE_COMPLETION_Q_LEN);
+               arc_msg0(sc, ARC_RE_INB_MSG0_SET_CONFIG);
+               break;
        }
 }
 
@@ -2287,12 +2752,18 @@ arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wb
        case ARC_HBA_TYPE_A:
                reg = arc_read(sc, ARC_RA_OUTB_DOORBELL);
                break;
+       case ARC_HBA_TYPE_B:
+               reg = arc_read(sc, sc->outb_doorbell);
+               break;
        case ARC_HBA_TYPE_C:
                reg = arc_read(sc, ARC_RC_OUTB_DOORBELL);
                break;
        case ARC_HBA_TYPE_D:
                reg = arc_read(sc, ARC_RD_OUTB_DOORBELL);
                break;
+       case ARC_HBA_TYPE_E:
+               reg = arc_read(sc, ARC_RE_OUTB_DOORBELL);
+               break;
        }
 /*     if (reg)
                return (EBUSY); */
@@ -2334,17 +2805,27 @@ arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wb
                                /* copy the chunk to the hw */
                                arc_write(sc, ARC_RA_IOC_WBUF_LEN, rwlen);
                                arc_write_region(sc, ARC_RA_IOC_WBUF, rwbuf,
-                               sizeof(rwbuf));
+                                   sizeof(rwbuf));
 
                                /* say we have a buffer for the hw */
                                arc_write(sc, ARC_RA_INB_DOORBELL,
                                ARC_RA_INB_DOORBELL_WRITE_OK);
                                break;
+                       case ARC_HBA_TYPE_B:
+                               /* copy the chunk to the hw */
+                               arc_write2(sc, ARC_RB_MSG_WBUF, rwlen);
+                               arc_write_region2(sc, ARC_RB_MSG_WBUF+4, rwbuf,
+                                   sizeof(rwbuf));
+
+                               /* say we have a buffer for the hw */
+                               arc_write(sc, sc->inb_doorbell,
+                                   ARC_RB_D2I_DATA_WRITE_OK);
+                               break;
                        case ARC_HBA_TYPE_C:
                                /* copy the chunk to the hw */
                                arc_write(sc, ARC_RC_MSG_WBUF_LEN, rwlen);
                                arc_write_region(sc, ARC_RC_MSG_WBUF, rwbuf,
-                               sizeof(rwbuf));
+                                   sizeof(rwbuf));
 
                                /* say we have a buffer for the hw */
                                arc_write(sc, ARC_RC_INB_DOORBELL,
@@ -2354,12 +2835,22 @@ arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wb
                                /* copy the chunk to the hw */
                                arc_write(sc, ARC_RD_MSG_WBUF_LEN, rwlen);
                                arc_write_region(sc, ARC_RD_MSG_WBUF, rwbuf,
-                               sizeof(rwbuf));
+                                   sizeof(rwbuf));
 
                                /* say we have a buffer for the hw */
                                arc_write(sc, ARC_RD_INB_DOORBELL,
                                ARC_RD_D2I_DATA_WRITE_OK);
                                break;
+                       case ARC_HBA_TYPE_E:
+                               /* copy the chunk to the hw */
+                               arc_write(sc, ARC_RE_MSG_WBUF_LEN, rwlen);
+                               arc_write_region(sc, ARC_RE_MSG_WBUF, rwbuf,
+                                   sizeof(rwbuf));
+
+                               /* say we have a buffer for the hw */
+                               sc->out_doorbell ^= ARC_RE_D2I_DATA_WRITE_OK;
+                               arc_write(sc, ARC_RE_INB_DOORBELL, 
sc->out_doorbell);
+                               break;
                        }
                        wdone += rwlen;
                }
@@ -2375,6 +2866,13 @@ arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wb
                        write_ok = reg & ARC_RA_OUTB_DOORBELL_WRITE_OK;
                        read_ok = reg & ARC_RA_OUTB_DOORBELL_READ_OK;
                        break;
+               case ARC_HBA_TYPE_B:
+                       while ((reg = arc_read(sc, sc->outb_doorbell)) == 0)
+                               arc_wait(sc);
+                       arc_write(sc, sc->outb_doorbell, ~(reg & 
ARC_RB_I2D_DOORBELL_INT));
+                       write_ok = reg & ARC_RB_I2D_DATA_WRITE_OK;
+                       read_ok = reg & ARC_RB_I2D_DATA_READ_OK;
+                       break;
                case ARC_HBA_TYPE_C:
                        while ((reg = arc_read(sc, ARC_RC_OUTB_DOORBELL)) == 0)
                                arc_wait(sc);
@@ -2389,6 +2887,20 @@ arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wb
                        write_ok = reg & ARC_RD_I2D_DATA_WRITE_OK;
                        read_ok = reg & ARC_RD_I2D_DATA_READ_OK;
                        break;
+               case ARC_HBA_TYPE_E: {
+                       u_int32_t val;
+                       do {
+                               arc_wait(sc);
+                               reg = arc_read(sc, ARC_RE_OUTB_DOORBELL);
+                       } while ((reg ^ sc->in_doorbell) == 0);
+                       val = reg ^ sc->in_doorbell;
+                       sc->in_doorbell = reg;
+                       reg = val;
+                       arc_write(sc, ARC_RE_INTR_STAT, 0);
+                       write_ok = reg & ARC_RE_I2D_DATA_WRITE_OK;
+                       read_ok = reg & ARC_RE_I2D_DATA_READ_OK;
+                       break;
+                       }
                }
                DNPRINTF(ARC_D_DB, "%s: reg: 0x%08x\n", DEVNAME(sc), reg);
 
@@ -2397,12 +2909,18 @@ arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wb
                        case ARC_HBA_TYPE_A:
                                rwlen = arc_read(sc, ARC_RA_IOC_RBUF_LEN);
                                break;
+                       case ARC_HBA_TYPE_B:
+                               rwlen = arc_read2(sc, ARC_RB_MSG_RBUF);
+                               break;
                        case ARC_HBA_TYPE_C:
                                rwlen = arc_read(sc, ARC_RC_MSG_RBUF_LEN);
                                break;
                        case ARC_HBA_TYPE_D:
                                rwlen = arc_read(sc, ARC_RD_MSG_RBUF_LEN);
                                break;
+                       case ARC_HBA_TYPE_E:
+                               rwlen = arc_read(sc, ARC_RE_MSG_RBUF_LEN);
+                               break;
                        }
                        if (rwlen > sizeof(rwbuf)) {
                                DNPRINTF(ARC_D_DB, "%s:  rwlen too big\n",
@@ -2414,22 +2932,34 @@ arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wb
                        switch(sc->sc_adp_type) {
                        case ARC_HBA_TYPE_A:
                                arc_read_region(sc, ARC_RA_IOC_RBUF, rwbuf,
-                               sizeof(rwbuf));
+                                   sizeof(rwbuf));
                                arc_write(sc, ARC_RA_INB_DOORBELL,
                                ARC_RA_INB_DOORBELL_READ_OK);
                                break;
+                       case ARC_HBA_TYPE_B:
+                               arc_read_region2(sc, ARC_RB_MSG_RBUF+4, rwbuf,
+                                   sizeof(rwbuf));
+                               arc_write(sc, sc->inb_doorbell,
+                                   ARC_RB_I2D_DATA_READ_OK);
+                               break;
                        case ARC_HBA_TYPE_C:
                                arc_read_region(sc, ARC_RC_MSG_RBUF, rwbuf,
-                               sizeof(rwbuf));
+                                   sizeof(rwbuf));
                                arc_write(sc, ARC_RC_INB_DOORBELL,
                                ARC_RC_I2D_DATA_READ_OK);
                                break;
                        case ARC_HBA_TYPE_D:
                                arc_read_region(sc, ARC_RD_MSG_RBUF, rwbuf,
-                               sizeof(rwbuf));
+                                   sizeof(rwbuf));
                                arc_write(sc, ARC_RD_INB_DOORBELL,
                                ARC_RD_I2D_DATA_READ_OK);
                                break;
+                       case ARC_HBA_TYPE_E:
+                               arc_read_region(sc, ARC_RE_MSG_RBUF, rwbuf,
+                                   sizeof(rwbuf));
+                               sc->out_doorbell ^= ARC_RE_I2D_DATA_READ_OK;
+                               arc_write(sc, ARC_RE_INB_DOORBELL, 
sc->out_doorbell);
+                               break;
                        }
                        if ((rlen > 3) && (rdone == 3)) {
                                rlen = *(u_int16_t *)rwbuf;
@@ -2507,7 +3037,7 @@ out:
 void
 arc_lock(struct arc_softc *sc)
 {
-       int                             s;
+       int     s;
        u_int32_t int_mask;
 
        rw_enter_write(&sc->sc_lock);
@@ -2517,6 +3047,10 @@ arc_lock(struct arc_softc *sc)
                int_mask = arc_read(sc, ARC_RA_INTRMASK) | 
ARC_RA_INTRMASK_DOORBELL;
                arc_write(sc, ARC_RA_INTRMASK, int_mask);
                break;
+       case ARC_HBA_TYPE_B:
+               int_mask = arc_read(sc, sc->outb_doorbell_mask) & 
~ARC_RB_I2D_INTR_ENABLE_DOORBELL;
+               arc_write(sc, sc->outb_doorbell_mask, int_mask);
+               break;
        case ARC_HBA_TYPE_C:
                int_mask = arc_read(sc, ARC_RC_INTR_MASK) | 
ARC_RC_INTR_MASK_DOORBELL;
                arc_write(sc, ARC_RC_INTR_MASK, int_mask);
@@ -2525,6 +3059,10 @@ arc_lock(struct arc_softc *sc)
                int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) & 
~ARC_RD_INTR_ENABLE_DOORBELL;
                arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
                break;
+       case ARC_HBA_TYPE_E:
+               int_mask = arc_read(sc, ARC_RE_INTR_MASK) | 
ARC_RE_INTR_MASK_DOORBELL;
+               arc_write(sc, ARC_RE_INTR_MASK, int_mask);
+               break;
        }
        sc->sc_talking = 1;
        splx(s);
@@ -2533,7 +3071,7 @@ arc_lock(struct arc_softc *sc)
 void
 arc_unlock(struct arc_softc *sc)
 {
-       int                             s;
+       int     s;
        u_int32_t int_mask;
 
        s = splbio();
@@ -2543,6 +3081,10 @@ arc_unlock(struct arc_softc *sc)
                int_mask = arc_read(sc, ARC_RA_INTRMASK) & 
~ARC_RA_INTRMASK_DOORBELL;
                arc_write(sc, ARC_RA_INTRMASK, int_mask);
                break;
+       case ARC_HBA_TYPE_B:
+               int_mask = arc_read(sc, sc->outb_doorbell_mask) | 
ARC_RB_I2D_INTR_ENABLE_DOORBELL;
+               arc_write(sc, sc->outb_doorbell_mask, int_mask);
+               break;
        case ARC_HBA_TYPE_C:
                int_mask = arc_read(sc, ARC_RC_INTR_MASK) & 
~ARC_RC_INTR_MASK_DOORBELL;
                arc_write(sc, ARC_RC_INTR_MASK, int_mask);
@@ -2551,6 +3093,10 @@ arc_unlock(struct arc_softc *sc)
                int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) | 
ARC_RD_INTR_ENABLE_DOORBELL;
                arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
                break;
+       case ARC_HBA_TYPE_E:
+               int_mask = arc_read(sc, ARC_RE_INTR_MASK) & 
~ARC_RE_INTR_MASK_DOORBELL;
+               arc_write(sc, ARC_RE_INTR_MASK, int_mask);
+               break;
        }
        splx(s);
        rw_exit_write(&sc->sc_lock);
@@ -2559,7 +3105,7 @@ arc_unlock(struct arc_softc *sc)
 void
 arc_wait(struct arc_softc *sc)
 {
-       int                             error, s;
+       int     error, s;
        u_int32_t int_mask;
 
        s = splbio();
@@ -2567,16 +3113,25 @@ arc_wait(struct arc_softc *sc)
        case ARC_HBA_TYPE_A:
                int_mask = arc_read(sc, ARC_RA_INTRMASK) & 
~ARC_RA_INTRMASK_DOORBELL;
                arc_write(sc, ARC_RA_INTRMASK, int_mask);
-               error = tsleep_nsec(sc, PWAIT, "arcdb", SEC_TO_NSEC(1));
+               error = tsleep(sc, PWAIT, "arcdb", hz);
                if (error == EWOULDBLOCK) {
                        int_mask = arc_read(sc, ARC_RA_INTRMASK) | 
ARC_RA_INTRMASK_DOORBELL;
                        arc_write(sc, ARC_RA_INTRMASK, int_mask);
                }
                break;
+       case ARC_HBA_TYPE_B:
+               int_mask = arc_read(sc, sc->outb_doorbell_mask) | 
ARC_RB_I2D_INTR_ENABLE_DOORBELL;
+               arc_write(sc, sc->outb_doorbell_mask, int_mask);
+               error = tsleep(sc, PWAIT, "arcdb", hz);
+               if (error == EWOULDBLOCK) {
+                       int_mask = arc_read(sc, sc->outb_doorbell_mask) & 
~ARC_RB_I2D_INTR_ENABLE_DOORBELL;
+                       arc_write(sc, sc->outb_doorbell_mask, int_mask);
+               }
+               break;
        case ARC_HBA_TYPE_C:
                int_mask = arc_read(sc, ARC_RC_INTR_MASK) & 
~ARC_RC_INTR_MASK_DOORBELL;
                arc_write(sc, ARC_RC_INTR_MASK, int_mask);
-               error = tsleep_nsec(sc, PWAIT, "arcdb", SEC_TO_NSEC(1));
+               error = tsleep(sc, PWAIT, "arcdb", hz);
                if (error == EWOULDBLOCK) {
                        int_mask = arc_read(sc, ARC_RC_INTR_MASK) | 
ARC_RC_INTR_MASK_DOORBELL;
                        arc_write(sc, ARC_RC_INTR_MASK, int_mask);
@@ -2585,12 +3140,21 @@ arc_wait(struct arc_softc *sc)
        case ARC_HBA_TYPE_D:
                int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) | 
ARC_RD_INTR_ENABLE_DOORBELL;
                arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
-               error = tsleep_nsec(sc, PWAIT, "arcdb", SEC_TO_NSEC(1));
+               error = tsleep(sc, PWAIT, "arcdb", hz);
                if (error == EWOULDBLOCK) {
                        int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) & 
~ARC_RD_INTR_ENABLE_DOORBELL;
                        arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
                }
                break;
+       case ARC_HBA_TYPE_E:
+               int_mask = arc_read(sc, ARC_RE_INTR_MASK) & 
~ARC_RE_INTR_MASK_DOORBELL;
+               arc_write(sc, ARC_RE_INTR_MASK, int_mask);
+               error = tsleep(sc, PWAIT, "arcdb", hz);
+               if (error == EWOULDBLOCK) {
+                       int_mask = arc_read(sc, ARC_RE_INTR_MASK) | 
ARC_RE_INTR_MASK_DOORBELL;
+                       arc_write(sc, ARC_RE_INTR_MASK, int_mask);
+               }
+               break;
        }
        splx(s);
 }
@@ -2612,7 +3176,7 @@ arc_create_sensors(void *xat)
         * XXX * this is bollocks. the firmware has garbage coming out of it
         * so we have to wait a bit for it to finish spewing.
         */
-       tsleep_nsec(sc, PWAIT, "arcspew", SEC_TO_NSEC(2));
+       tsleep(sc, PWAIT, "arcspew", hz * 2);
 
        bzero(&bi, sizeof(bi));
        if (arc_bio_inq(sc, &bi) != 0) {
@@ -2706,7 +3270,7 @@ arc_refresh_sensors(void *arg)
 u_int32_t
 arc_read(struct arc_softc *sc, bus_size_t r)
 {
-       u_int32_t                       v;
+       u_int32_t       v;
 
        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
            BUS_SPACE_BARRIER_READ);
@@ -2747,12 +3311,12 @@ int
 arc_wait_eq(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
     u_int32_t target)
 {
-       int                             i;
+       int     i;
 
-       DNPRINTF(ARC_D_RW, "%s: arc_wait_eq 0x%x 0x%08x 0x%08x\n",
+       DNPRINTF(ARC_D_RW, "%s: arc_wait_eq 0x%lx 0x%08x 0x%08x\n",
            DEVNAME(sc), r, mask, target);
 
-       for (i = 0; i < 10000; i++) {
+       for (i = 0; i < 60000; i++) {
                if ((arc_read(sc, r) & mask) == target)
                        return (0);
                delay(1000);
@@ -2762,10 +3326,31 @@ arc_wait_eq(struct arc_softc *sc, bus_size_t r, u_int3
 }
 
 int
+arc_wait_doorbell(struct arc_softc *sc, bus_size_t r, u_int32_t mask)
+{
+       int     i;
+       u_int32_t       doorbell;
+
+       DNPRINTF(ARC_D_RW, "%s: arc_wait_doorbell 0x%x 0x%08x\n",
+           DEVNAME(sc), r, mask);
+
+       for (i = 0; i < 10000; i++) {
+               doorbell = arc_read(sc, r);
+               if ((sc->in_doorbell ^ doorbell) & mask) {
+                       sc->in_doorbell = doorbell;
+                       return (0);
+               }
+               delay(1000);
+       }
+
+       return (1);
+}
+
+int
 arc_wait_ne(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
     u_int32_t target)
 {
-       int                             i;
+       int     i;
 
        DNPRINTF(ARC_D_RW, "%s: arc_wait_ne 0x%x 0x%08x 0x%08x\n",
            DEVNAME(sc), r, mask, target);
@@ -2779,6 +3364,43 @@ arc_wait_ne(struct arc_softc *sc, bus_size_t r, u_int3
        return (1);
 }
 
+u_int32_t
+arc_read2(struct arc_softc *sc, bus_size_t r)
+{
+       u_int32_t       v;
+
+       bus_space_barrier(sc->sc_msgt, sc->sc_msgh, r, 4,
+           BUS_SPACE_BARRIER_READ);
+       v = bus_space_read_4(sc->sc_msgt, sc->sc_msgh, r);
+       return (v);
+}
+
+void
+arc_write2(struct arc_softc *sc, bus_size_t r, u_int32_t v)
+{
+       DNPRINTF(ARC_D_RW, "%s: arc_write 0x%x 0x%08x\n", DEVNAME(sc), r, v);
+
+       bus_space_write_4(sc->sc_msgt, sc->sc_msgh, r, v);
+       bus_space_barrier(sc->sc_msgt, sc->sc_msgh, r, 4,
+           BUS_SPACE_BARRIER_WRITE);
+}
+
+void
+arc_read_region2(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
+{
+       bus_space_barrier(sc->sc_msgt, sc->sc_msgh, r, len,
+           BUS_SPACE_BARRIER_READ);
+       bus_space_read_raw_region_4(sc->sc_msgt, sc->sc_msgh, r, buf, len);
+}
+
+void
+arc_write_region2(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
+{
+       bus_space_write_raw_region_4(sc->sc_msgt, sc->sc_msgh, r, buf, len);
+       bus_space_barrier(sc->sc_msgt, sc->sc_msgh, r, len,
+           BUS_SPACE_BARRIER_WRITE);
+}
+
 int
 arc_msg0(struct arc_softc *sc, u_int32_t m)
 {
@@ -2788,20 +3410,33 @@ arc_msg0(struct arc_softc *sc, u_int32_t m)
                arc_write(sc, ARC_RA_INB_MSG0, m);
                /* wait for the fw to do it */
                if (arc_wait_eq(sc, ARC_RA_INTRSTAT, ARC_RA_INTRSTAT_MSG0,
-               ARC_RA_INTRSTAT_MSG0) != 0)
+                   ARC_RA_INTRSTAT_MSG0) != 0)
                        return (1);
 
                /* ack it */
                arc_write(sc, ARC_RA_INTRSTAT, ARC_RA_INTRSTAT_MSG0);
                break;
 
+               case ARC_HBA_TYPE_B:
+               /* post message */
+               arc_write(sc, sc->inb_doorbell, m);
+               /* wait for the fw to do it */
+               if (arc_wait_eq(sc, sc->outb_doorbell, ARC_RB_I2D_MSG_CMD_DONE,
+                   ARC_RB_I2D_MSG_CMD_DONE) != 0)
+                       return (1);
+
+               /* ack it */
+               arc_write(sc, sc->outb_doorbell, 
ARC_RB_MESSAGE_INT_CLEAR_PATTERN);
+               arc_write(sc, sc->inb_doorbell, ARC_RB_D2I_END_OF_INTERRUPT);
+               break;
+
                case ARC_HBA_TYPE_C:
                /* post message */
                arc_write(sc, ARC_RC_INB_MSGADDR0, m);
                arc_write(sc, ARC_RC_INB_DOORBELL, ARC_RC_D2I_MSG_CMD_DONE);
                /* wait for the fw to do it */
                if (arc_wait_eq(sc, ARC_RC_OUTB_DOORBELL, 
ARC_RC_I2D_MSG_CMD_DONE,
-               ARC_RC_I2D_MSG_CMD_DONE) != 0)
+                   ARC_RC_I2D_MSG_CMD_DONE) != 0)
                        return (1);
 
                /* ack it */
@@ -2813,12 +3448,25 @@ arc_msg0(struct arc_softc *sc, u_int32_t m)
                arc_write(sc, ARC_RD_INB_MSGADDR0, m);
                /* wait for the fw to do it */
                if (arc_wait_eq(sc, ARC_RD_OUTB_DOORBELL, 
ARC_RD_I2D_MSG_CMD_DONE,
-               ARC_RD_I2D_MSG_CMD_DONE) != 0)
+                   ARC_RD_I2D_MSG_CMD_DONE) != 0)
                        return (1);
 
                /* ack it */
                arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, 
ARC_RD_I2D_MSG_CMD_DONE_CLR);
                break;
+
+               case ARC_HBA_TYPE_E:
+               /* post message */
+               arc_write(sc, ARC_RE_INB_MSGADDR0, m);
+               sc->out_doorbell ^= ARC_RE_D2I_MSG_CMD_DONE;
+               arc_write(sc, ARC_RE_INB_DOORBELL, sc->out_doorbell);
+               /* wait for the fw to do it */
+               if (arc_wait_doorbell(sc, ARC_RE_OUTB_DOORBELL, 
ARC_RE_I2D_MSG_CMD_DONE) != 0)
+                       return (1);
+
+               /* ack it */
+               arc_write(sc, ARC_RE_INTR_STAT, 0);
+               break;
        }
        return (0);
 }
@@ -2878,9 +3526,9 @@ arc_dmamem_free(struct arc_softc *sc, struct arc_dmame
 int
 arc_alloc_ccbs(struct arc_softc *sc)
 {
-       struct arc_ccb          *ccb;
-       u_int8_t                        *cmd;
-       u_int32_t                       i, size, len;
+       struct arc_ccb  *ccb;
+       u_int8_t                *cmd;
+       u_int32_t       i, size, iolen;
 
        SLIST_INIT(&sc->sc_ccb_free);
        mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
@@ -2888,16 +3536,30 @@ arc_alloc_ccbs(struct arc_softc *sc)
        size = sizeof(struct arc_ccb) * ARCMSR_MAX_CCB_COUNT;
        sc->sc_ccbs = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
 
-       len = ARC_IO_CMD_LEN;
-       size = ARCMSR_MAX_CCB_COUNT * len;
-       if(sc->sc_adp_type == ARC_HBA_TYPE_D)
+       size = ARCMSR_MAX_CCB_COUNT * ARC_IO_CMD_LEN;
+       iolen = size;
+       switch(sc->sc_adp_type) {
+       case ARC_HBA_TYPE_B:
+               size += sizeof(struct arc_HBB_Msgu);
+               break;
+       case ARC_HBA_TYPE_D:
                size += sizeof(struct arc_HBD_Msgu);
+               sc->ioc_compq_size = size;
+               break;
+       case ARC_HBA_TYPE_E:
+               size += ARC_HBE_COMPLETION_Q_LEN;
+               sc->doneq_size = ARC_HBE_COMPLETION_Q_LEN;
+               sc->doneq_entry = ARC_HBE_COMPLETION_Q_LEN / sizeof(struct 
arc_HBE_Msgu);
+               sc->doneq_index = 0;
+               break;
+       }
        sc->sc_requests = arc_dmamem_alloc(sc, size);
        if (sc->sc_requests == NULL) {
                printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
                goto free_ccbs;
        }
        cmd = ARC_DMA_KVA(sc->sc_requests);
+       sc->sc_ccb_phys_lo = ARC_DMA_DVA(sc->sc_requests);
 
        for (i = 0; i < ARCMSR_MAX_CCB_COUNT; i++) {
                ccb = &sc->sc_ccbs[i];
@@ -2910,25 +3572,52 @@ arc_alloc_ccbs(struct arc_softc *sc)
                }
 
                ccb->ccb_sc = sc;
-               ccb->cmd_dma_offset = len * i;
+               ccb->cmd_dma_offset = ARC_IO_CMD_LEN * i;
+               ccb->ccb_id = i;
+               ccb->smid = i << 16;
 
                ccb->ccb_cmd = (struct arc_io_cmd *)&cmd[ccb->cmd_dma_offset];
                ccb->ccb_cmd_post = (ARC_DMA_DVA(sc->sc_requests) +
                    ccb->cmd_dma_offset);
-               if ((sc->sc_adp_type != ARC_HBA_TYPE_C) &&
-                   (sc->sc_adp_type != ARC_HBA_TYPE_D))
+               if ((sc->sc_adp_type == ARC_HBA_TYPE_A) ||
+                   (sc->sc_adp_type == ARC_HBA_TYPE_B))
                        ccb->ccb_cmd_post = ccb->ccb_cmd_post >>
                            ARC_RA_POST_QUEUE_ADDR_SHIFT;
                arc_put_ccb(sc, ccb);
        }
        sc->sc_ccb_phys_hi = (u_int64_t)ARC_DMA_DVA(sc->sc_requests) >> 32;
-       if(sc->sc_adp_type == ARC_HBA_TYPE_D) {
-               sc->postQ_buffer = ARC_DMA_DVA(sc->sc_requests) +
-                   (ARCMSR_MAX_CCB_COUNT * len);
+       switch(sc->sc_adp_type) {
+       case ARC_HBA_TYPE_B:
+               sc->postQ_buffer = ARC_DMA_DVA(sc->sc_requests) + iolen;
+               sc->doneQ_buffer = sc->postQ_buffer + (sizeof(u_int32_t) *
+                   ARCMSR_MAX_HBB_POSTQUEUE);
+               sc->pmuB = (struct arc_HBB_Msgu *)&cmd[iolen];
+               sc->cmdQ_ptr_offset = iolen;
+               if (sc->ab_product == PCI_PRODUCT_ARECA_ARC1203) {
+                       sc->inb_doorbell = (bus_size_t)ARC_RB_INB_DOORBELL_1203;
+                       sc->inb_doorbell_mask = 
(bus_size_t)ARC_RB_INB_DOORBELL_MASK_1203;
+                       sc->outb_doorbell = 
(bus_size_t)ARC_RB_OUTB_DOORBELL_1203;
+                       sc->outb_doorbell_mask = 
(bus_size_t)ARC_RB_OUTB_DOORBELL_MASK_1203;
+               } else {
+                       sc->inb_doorbell = (bus_size_t)ARC_RB_INB_DOORBELL;
+                       sc->inb_doorbell_mask = 
(bus_size_t)ARC_RB_INB_DOORBELL_MASK;
+                       sc->outb_doorbell = (bus_size_t)ARC_RB_OUTB_DOORBELL;
+                       sc->outb_doorbell_mask = 
(bus_size_t)ARC_RB_OUTB_DOORBELL_MASK;
+               }
+               break;
+       case ARC_HBA_TYPE_D:
+               sc->postQ_buffer = ARC_DMA_DVA(sc->sc_requests) + iolen;
                sc->doneQ_buffer = sc->postQ_buffer + (sizeof(struct 
InBound_SRB) *
                    ARCMSR_MAX_HBD_POSTQUEUE);
-               sc->pmu = (struct arc_HBD_Msgu *)&cmd[ARCMSR_MAX_CCB_COUNT * 
len];
-               sc->cmdQ_ptr_offset = ARCMSR_MAX_CCB_COUNT * len;
+               sc->pmu = (struct arc_HBD_Msgu *)&cmd[iolen];
+               sc->cmdQ_ptr_offset = iolen;
+               break;
+       case ARC_HBA_TYPE_E:
+               sc->pmuE = (struct arc_HBE_Msgu *)&cmd[iolen];
+               sc->doneq_phys_lo = ARC_DMA_DVA(sc->sc_requests) + iolen;
+               sc->doneq_phys_hi = (u_int64_t)(ARC_DMA_DVA(sc->sc_requests) + 
iolen) >> 32;
+               sc->cmdQ_ptr_offset = iolen;
+               break;
        }
        scsi_iopool_init(&sc->sc_iopool, sc,
            (void *(*)(void *))arc_get_ccb,
diff -upN a/sys/dev/pci/pcidevs b/sys/dev/pci/pcidevs
--- a/sys/dev/pci/pcidevs       Mon Jul  6 19:24:58 2020
+++ b/sys/dev/pci/pcidevs       Mon Jul  6 19:25:30 2020
@@ -1031,6 +1031,7 @@ product ARECA ARC1200             0x1200  ARC-1200
 product ARECA ARC1200_B                0x1201  ARC-1200B
 product ARECA ARC1202          0x1202  ARC-1202
 product ARECA ARC1210          0x1210  ARC-1210
+product ARECA ARC1203          0X1203  ARC-1203
 product ARECA ARC1214          0x1214  ARC-1214
 product ARECA ARC1220          0x1220  ARC-1220
 product ARECA ARC1230          0x1230  ARC-1230
@@ -1042,6 +1043,8 @@ product ARECA ARC1381             0x1381  ARC-1381
 product ARECA ARC1680          0x1680  ARC-1680
 product ARECA ARC1681          0x1681  ARC-1681
 product ARECA ARC1880          0x1880  ARC-1880
+product ARECA ARC1884          0x1884  ARC-1884
+product ARECA ARC1886          0x188a  ARC-1886
 
 /* ASIX Electronics products */
 product ASIX AX88140A          0x1400  AX88140A/88141

Reply via email to