Index: sys/dev/hptiop/hptiop.c =================================================================== --- sys/dev/hptiop/hptiop.c (revision 224900) +++ sys/dev/hptiop/hptiop.c (working copy) @@ -495,8 +495,12 @@ static void hptiop_drain_outbound_queue_itl(struct static int hptiop_intr_itl(struct hpt_iop_hba * hba) { u_int32_t status; + void *plx = hba->u.itl.plx; int ret = 0; + if (plx != NULL && bus_space_read_4(hba->bar2t, hba->bar2h, 0x11C5C) & 0xf) + bus_space_write_4(hba->bar2t, hba->bar2h, 0x11C60, 1); + status = BUS_SPACE_RD4_ITL(outbound_intstatus); if (status & IOPMU_OUTBOUND_INT_MSG0) { @@ -1052,7 +1056,8 @@ static bus_dmamap_callback_t hptiop_mv_map_ctlc static int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba) { - hba->bar0_rid = 0x10; + u_int32_t id; + hba->bar0_rid = PCIR_BAR(0); hba->bar0_res = bus_alloc_resource_any(hba->pcidev, SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); @@ -1066,13 +1071,52 @@ static int hptiop_alloc_pci_res_itl(struct hpt_iop hba->u.itl.mu = (struct hpt_iopmu_itl *) rman_get_virtual(hba->bar0_res); - if (!hba->u.itl.mu) { + if (hba->u.itl.mu == NULL) { bus_release_resource(hba->pcidev, SYS_RES_MEMORY, hba->bar0_rid, hba->bar0_res); device_printf(hba->pcidev, "alloc mem res failed\n"); return -1; } + /* Special case for 44xx series */ + id = pci_get_device(hba->pcidev); + if ((id & 0xff00) == 0x4400) { + /* + * On 44xx, BAR2 acts as BAR0 of other ITL devices. + * In order to reuse the code, we use bar0* to hold + * BAR2 resources and vice versa. + */ + hba->bar2_rid = hba->bar0_rid; + hba->bar2_res = hba->bar0_res; + hba->bar2t = hba->bar0t; + hba->bar2h = hba->bar0h; + + hba->bar0_rid = PCIR_BAR(2); + hba->bar0_res = bus_alloc_resource_any(hba->pcidev, + SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); + if (hba->bar0_res == NULL) { + bus_release_resource(hba->pcidev, SYS_RES_MEMORY, + hba->bar2_rid, hba->bar2_res); + device_printf(hba->pcidev, "failed to get iop bar2.\n"); + return -1; + } + + hba->bar0t = rman_get_bustag(hba->bar0_res); + hba->bar0h = rman_get_bushandle(hba->bar0_res); + + hba->u.itl.plx = hba->u.itl.mu; + hba->u.itl.mu = (struct hpt_iopmu_itl *) + rman_get_virtual(hba->bar0_res); + if (hba->u.itl.mu == NULL) { + bus_release_resource(hba->pcidev, SYS_RES_MEMORY, + hba->bar0_rid, hba->bar0_res); + bus_release_resource(hba->pcidev, SYS_RES_MEMORY, + hba->bar2_rid, hba->bar2_res); + device_printf(hba->pcidev, "alloc mem res failed\n"); + return -1; + } + } + return 0; } @@ -1130,6 +1174,9 @@ static void hptiop_release_pci_res_itl(struct hpt_ if (hba->bar0_res) bus_release_resource(hba->pcidev, SYS_RES_MEMORY, hba->bar0_rid, hba->bar0_res); + if (hba->bar2_res) + bus_release_resource(hba->pcidev, SYS_RES_MEMORY, + hba->bar2_rid, hba->bar2_res); } static void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba) @@ -1269,24 +1316,31 @@ static int hptiop_probe(device_t dev) id = pci_get_device(dev); switch (id) { + case 0x4210: + case 0x4211: + case 0x4310: + case 0x4311: + case 0x4320: + case 0x4321: case 0x4322: - case 0x4321: - case 0x4320: + case 0x4400: sas = 1; case 0x3220: case 0x3320: case 0x3410: - case 0x3520: case 0x3510: case 0x3511: + case 0x3520: case 0x3521: case 0x3522: + case 0x3530: case 0x3540: + case 0x3560: ops = &hptiop_itl_ops; break; + case 0x3020: case 0x3120: case 0x3122: - case 0x3020: ops = &hptiop_mv_ops; break; default: Index: sys/dev/hptiop/hptiop.h =================================================================== --- sys/dev/hptiop/hptiop.h (revision 224900) +++ sys/dev/hptiop/hptiop.h (working copy) @@ -282,6 +282,7 @@ struct hpt_iop_hba { union { struct { struct hpt_iopmu_itl *mu; + void *plx; } itl; struct { struct hpt_iopmv_regs *regs;