From 12c10932ccb801caf51fe0c36160a63c47c30821 Mon Sep 17 00:00:00 2001 From: gibbs Date: Tue, 10 Nov 1998 06:44:54 +0000 Subject: Fix probes when a port address is specified. --- sys/dev/buslogic/bt.c | 121 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 98 insertions(+), 23 deletions(-) (limited to 'sys/dev/buslogic/bt.c') diff --git a/sys/dev/buslogic/bt.c b/sys/dev/buslogic/bt.c index 8c4b3e2..57a885b 100644 --- a/sys/dev/buslogic/bt.c +++ b/sys/dev/buslogic/bt.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bt.c,v 1.7 1998/10/15 23:46:28 gibbs Exp $ + * $Id: bt.c,v 1.8 1998/10/30 02:06:44 gibbs Exp $ */ /* @@ -181,12 +181,26 @@ u_long bt_unit = 0; */ struct bt_isa_port bt_isa_ports[] = { - { 0x330, 0 }, - { 0x334, 0 }, - { 0x230, 0 }, - { 0x234, 0 }, - { 0x130, 0 }, - { 0x134, 0 } + { 0x130, 0, 4 }, + { 0x134, 0, 5 }, + { 0x230, 0, 2 }, + { 0x234, 0, 3 }, + { 0x330, 0, 0 }, + { 0x334, 0, 1 } +}; + +/* + * I/O ports listed in the order enumerated by the + * card for certain op codes. + */ +u_int16_t bt_board_ports[] = +{ + 0x330, + 0x334, + 0x230, + 0x234, + 0x130, + 0x134 }; /* Exported functions */ @@ -814,7 +828,7 @@ bt_check_probed_iop(u_int ioport) { u_int i; - for (i=0; i < BT_NUM_ISAPORTS; i++) { + for (i = 0; i < BT_NUM_ISAPORTS; i++) { if (bt_isa_ports[i].addr == ioport) { if (bt_isa_ports[i].probed != 0) return (1); @@ -826,17 +840,11 @@ bt_check_probed_iop(u_int ioport) return (1); } -u_int -bt_fetch_isa_iop(isa_compat_io_t port) -{ - return (bt_isa_ports[port].addr); -} - void bt_mark_probed_bio(isa_compat_io_t port) { if (port < BIO_DISABLED) - bt_isa_ports[port].probed = 1; + bt_mark_probed_iop(bt_board_ports[port]); } void @@ -852,6 +860,44 @@ bt_mark_probed_iop(u_int ioport) } } +void +bt_find_probe_range(int ioport, int *port_index, int *max_port_index) +{ + if (ioport > 0) { + int i; + + for (i = 0;i < BT_NUM_ISAPORTS; i++) + if (ioport <= bt_isa_ports[i].addr) + break; + if ((i >= BT_NUM_ISAPORTS) + || (ioport != bt_isa_ports[i].addr)) { + printf(" +bt_isa_probe: Invalid baseport of 0x%x specified. +bt_isa_probe: Nearest valid baseport is 0x%x. +bt_isa_probe: Failing probe.\n", + ioport, + (i < BT_NUM_ISAPORTS) + ? bt_isa_ports[i].addr + : bt_isa_ports[BT_NUM_ISAPORTS - 1].addr); + *port_index = *max_port_index = -1; + return; + } + *port_index = *max_port_index = bt_isa_ports[i].bio; + } else { + *port_index = 0; + *max_port_index = BT_NUM_ISAPORTS - 1; + } +} + +int +bt_iop_from_bio(isa_compat_io_t bio_index) +{ + if (bio_index >= 0 && bio_index < BT_NUM_ISAPORTS) + return (bt_board_ports[bio_index]); + return (-1); +} + + static void btallocccbs(struct bt_softc *bt) { @@ -924,6 +970,7 @@ btfreeccb(struct bt_softc *bt, struct bt_ccb *bccb) } bccb->flags = BCCB_FREE; SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links); + bt->active_ccbs--; splx(s); } @@ -936,13 +983,16 @@ btgetccb(struct bt_softc *bt) s = splcam(); if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) { SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); + bt->active_ccbs++; } else if (bt->num_ccbs < bt->max_ccbs) { btallocccbs(bt); bccb = SLIST_FIRST(&bt->free_bt_ccbs); if (bccb == NULL) printf("%s: Can't malloc BCCB\n", bt_name(bt)); - else + else { SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links); + bt->active_ccbs++; + } } splx(s); @@ -1347,8 +1397,27 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) /* Tell the adapter about this command */ bt->cur_outbox->ccb_addr = btccbvtop(bt, bccb); - if (bt->cur_outbox->action_code != BMBO_FREE) - panic("%s: Too few mailboxes or to many ccbs???", bt_name(bt)); + if (bt->cur_outbox->action_code != BMBO_FREE) { + /* + * We should never encounter a busy mailbox. + * If we do, warn the user, and treat it as + * a resource shortage. If the controller is + * hung, one of the pending transactions will + * timeout causing us to start recovery operations. + */ + printf("%s: Encountered busy mailbox with %d out of %d " + "commands active!!!", bt_name(bt), bt->active_ccbs, + bt->max_ccbs); + untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch); + if (nseg != 0) + bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap); + btfreeccb(bt, bccb); + bt->resource_shortage = TRUE; + xpt_freeze_simq(bt->sim, /*count*/1); + ccb->ccb_h.status = CAM_REQUEUE_REQ; + xpt_done(ccb); + return; + } bt->cur_outbox->action_code = BMBO_START; bt_outb(bt, COMMAND_REG, BOP_START_MBOX); btnextoutbox(bt); @@ -1469,14 +1538,20 @@ btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code) break; case BMBI_ABORT: case BMBI_ERROR: -#if 0 - printf("bt: ccb %x - error %x occured. btstat = %x, sdstat = %x\n", - bccb, comp_code, bccb->hccb.btstat, bccb->hccb.sdstat); -#endif + printf("bt: ccb %p - error %x occured. " + "btstat = %x, sdstat = %x\n", + (void *)bccb, comp_code, bccb->hccb.btstat, + bccb->hccb.sdstat); /* An error occured */ switch(bccb->hccb.btstat) { case BTSTAT_DATARUN_ERROR: - if (bccb->hccb.data_len <= 0) { + if (bccb->hccb.data_len == 0) { + /* + * At least firmware 4.22, does this + * for a QUEUE FULL condition. + */ + bccb->hccb.sdstat = SCSI_STATUS_QUEUE_FULL; + } else if (bccb->hccb.data_len < 0) { csio->ccb_h.status = CAM_DATA_RUN_ERR; break; } -- cgit v1.1