summaryrefslogtreecommitdiffstats
path: root/sys/dev/buslogic/bt.c
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1998-11-10 06:44:54 +0000
committergibbs <gibbs@FreeBSD.org>1998-11-10 06:44:54 +0000
commit12c10932ccb801caf51fe0c36160a63c47c30821 (patch)
treee1da86a46f5875e7efd3c258990c3555b79207b4 /sys/dev/buslogic/bt.c
parentde6b8e170af7d1f2104bda47abec30de3677cabc (diff)
downloadFreeBSD-src-12c10932ccb801caf51fe0c36160a63c47c30821.zip
FreeBSD-src-12c10932ccb801caf51fe0c36160a63c47c30821.tar.gz
Fix probes when a port address is specified.
Diffstat (limited to 'sys/dev/buslogic/bt.c')
-rw-r--r--sys/dev/buslogic/bt.c121
1 files changed, 98 insertions, 23 deletions
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;
}
OpenPOWER on IntegriCloud