Date: Tue, 11 Jul 1995 21:49:19 +1000 From: Stephen Hocking <sysseh@devetir.qld.gov.au> To: bugs@freebsd.org Message-ID: <199507111149.LAA24598@netfl15a.devetir.qld.gov.au>
next in thread | raw e-mail | index | archive | help
The following patch to v1.8 of seagate.c fixes PR i386/337 (seagate controller code hangs on boot.) for me. It basically alters its behaiviour when confronted with a Future Domain TMC 885 controller in WRT disconnects, deassertion of STAT_REQ and various phase checks. *** seagate.c.dist Tue Jul 4 11:32:10 1995 --- seagate.c Tue Jul 11 20:31:23 1995 *************** *** 7,12 **** --- 7,13 ---- * Copyright 1992, 1994 Drew Eckhardt (drew@colorado.edu) * Copyright 1994, Julian Elischer (julian@tfs.com) * Copyright 1994-1995, Serge Vakulenko (vak@cronyx.ru) + * Copyright 1995 Stephen Hocking (sysseh@devetir.qld.gov.au) * * Others that has contributed by example code is * Glen Overby (overby@cray.com) *************** *** 45,50 **** --- 46,57 ---- * new asm fragments for data input/output, target-dependent * delays, device flags, polling mode, generic cleanup * vak 950115 Added request-sense ops + * seh 950701 Fixed up Future Domain TMC-885 problems with disconnects, + * weird phases and the like. (we could probably investigate + * what the board's idea of the phases are, but that requires + * doco that I don't have). Note that it is slower than the + * 2.0R driver with both SEA_BLINDTRANSFER & SEA_ASSEMBLER + * defined by a factor of more than 2. I'll look at that later! * * $Id: seagate.c,v 1.8 1995/05/30 08:03:04 rgrimes Exp $ */ *************** *** 128,134 **** #define HOST_SCSI_ADDR 7 /* address of the adapter on the SCSI bus */ /* ! * Defice config flags */ #define FLAG_NOPARITY 0x01 /* disable SCSI bus parity check */ --- 135,141 ---- #define HOST_SCSI_ADDR 7 /* address of the adapter on the SCSI bus */ /* ! * Define config flags */ #define FLAG_NOPARITY 0x01 /* disable SCSI bus parity check */ *************** *** 324,330 **** static int sea_poll (adapter_t *z, scb_t *scb); static int sea_init (adapter_t *z); static int sea_reselect (adapter_t *z); ! static int sea_select (adapter_t *z, scb_t *scb); static int sea_abort (adapter_t *z, scb_t *scb); static void sea_send_abort (adapter_t *z); static u_char sea_msg_input (adapter_t *z); --- 331,337 ---- static int sea_poll (adapter_t *z, scb_t *scb); static int sea_init (adapter_t *z); static int sea_reselect (adapter_t *z); ! static int sea_select (volatile adapter_t *z, scb_t *scb); static int sea_abort (adapter_t *z, scb_t *scb); static void sea_send_abort (adapter_t *z); static u_char sea_msg_input (adapter_t *z); *************** *** 348,353 **** --- 355,363 ---- DC_CLS_MISC /* host adapters aren't special */ } }; + /* FD TMC885's can't handle detach & re-attach */ + static int sea_select_cmd = CMD_DRVR_ENABLE | CMD_ATTN; + /* * Check if the device can be found at the port given and if so, * detect the type of board. Set it up ready for further work. *************** *** 421,426 **** --- 431,441 ---- z->CONTROL = z->addr + 0x1c00; /* TMC-885/TMC-950 reg. offsets */ z->STATUS = z->addr + 0x1c00; z->DATA = z->addr + 0x1e00; + /* FD TMC885's can't handle detach & re-attach */ + sea_select_cmd = CMD_DRVR_ENABLE; + /* FD TMC-885 is supposed to be at id 6. How strange. */ + z->scsi_addr = HOST_SCSI_ADDR - 1; + z->scsi_id = 1 << z->scsi_addr; if (sea_init (z) == 0) return (1); *************** *** 476,482 **** } /* Reset the scsi bus (I don't know if this is needed). */ ! *z->CONTROL = CMD_RST | CMD_DRVR_ENABLE; /* Hold reset for at least 25 microseconds. */ DELAY (25); /* Check that status cleared. */ --- 491,497 ---- } /* Reset the scsi bus (I don't know if this is needed). */ ! *z->CONTROL = CMD_RST | CMD_DRVR_ENABLE | z->parity | CMD_INTR; /* Hold reset for at least 25 microseconds. */ DELAY (25); /* Check that status cleared. */ *************** *** 497,503 **** /* Enable the adapter. */ *z->CONTROL = CMD_INTR | z->parity; /* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */ ! DELAY (10); /* Check that DATA register is NOT writable. */ c = *z->DATA; --- 512,518 ---- /* Enable the adapter. */ *z->CONTROL = CMD_INTR | z->parity; /* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */ ! DELAY (15); /* Check that DATA register is NOT writable. */ c = *z->DATA; *************** *** 591,598 **** adapter_t *z = &seadata[unit]; scb_t *scb; ! /* PRINT (("sea%d/%d/%d command 0x%x\n", unit, xs->sc_link->target, ! xs->sc_link->lun, xs->cmd->opcode)); */ if (xs->bp) flags |= SCSI_NOSLEEP; if (flags & ITSDONE) { --- 606,613 ---- adapter_t *z = &seadata[unit]; scb_t *scb; ! PRINT (("sea%d/%d/%d command 0x%x\n", unit, xs->sc_link->target, ! xs->sc_link->lun, xs->cmd->opcode)); if (xs->bp) flags |= SCSI_NOSLEEP; if (flags & ITSDONE) { *************** *** 680,688 **** * this time there is no clock queue entry to remove. */ sea_timeout ((void*) scb); } ! /* PRINT (("sea%d/%d/%d command %s\n", unit, xs->sc_link->target, xs->sc_link->lun, ! xs->error ? "failed" : "done")); */ return (xs->error ? HAD_ERROR : COMPLETE); } --- 695,703 ---- * this time there is no clock queue entry to remove. */ sea_timeout ((void*) scb); } ! PRINT (("sea%d/%d/%d command %s\n", unit, xs->sc_link->target, xs->sc_link->lun, ! xs->error ? "failed" : "done")); return (xs->error ? HAD_ERROR : COMPLETE); } *************** *** 781,790 **** * for IDENTIFY and queue messages. * Return 1 if selection succeded. */ ! int sea_select (adapter_t *z, scb_t *scb) { /* Start arbitration. */ ! *z->CONTROL = z->parity; *z->DATA = z->scsi_id; *z->CONTROL = CMD_START_ARB | z->parity; --- 796,807 ---- * for IDENTIFY and queue messages. * Return 1 if selection succeded. */ ! int sea_select (volatile adapter_t *z, scb_t *scb) { + register unsigned char tmp; + /* Start arbitration. */ ! *z->CONTROL = z->parity | CMD_INTR; *z->DATA = z->scsi_id; *z->CONTROL = CMD_START_ARB | z->parity; *************** *** 801,811 **** *z->CONTROL = CMD_INTR | z->parity; return (0); } ! DELAY (2); *z->DATA = (1 << scb->xfer->sc_link->target) | z->scsi_id; ! *z->CONTROL = CMD_DRVR_ENABLE | CMD_SEL | CMD_ATTN | z->parity; ! DELAY (1); /* Wait for a bsy from target. * If the target is not present on the bus, we get --- 818,828 ---- *z->CONTROL = CMD_INTR | z->parity; return (0); } ! DELAY (1); *z->DATA = (1 << scb->xfer->sc_link->target) | z->scsi_id; ! *z->CONTROL = sea_select_cmd | CMD_SEL | z->parity; ! DELAY (2); /* Wait for a bsy from target. * If the target is not present on the bus, we get *************** *** 823,830 **** /* Try to make the target to take a message from us. * Should start a MSGOUT phase. */ ! *z->CONTROL = CMD_DRVR_ENABLE | CMD_ATTN | z->parity; ! DELAY (1); WAITFOR (*z->STATUS & STAT_REQ, 0); if (! (*z->STATUS & STAT_REQ)) { PRINT (("sea%d/%d/%d timeout waiting for REQ\n", --- 840,852 ---- /* Try to make the target to take a message from us. * Should start a MSGOUT phase. */ ! *z->CONTROL = sea_select_cmd | z->parity; ! DELAY (15); ! WAITFOR (*z->STATUS & STAT_REQ, 0); ! ! if (z->type == CTLR_FUTURE_DOMAIN) ! *z->CONTROL = CMD_INTR | z->parity | CMD_DRVR_ENABLE; ! WAITFOR (*z->STATUS & STAT_REQ, 0); if (! (*z->STATUS & STAT_REQ)) { PRINT (("sea%d/%d/%d timeout waiting for REQ\n", *************** *** 835,842 **** return (0); } ! /* Check for phase mismatch. */ ! if ((*z->STATUS & PHASE_MASK) != PHASE_MSGOUT) { PRINT (("sea%d/%d/%d waiting for MSGOUT: invalid phase %s\n", z->sc_link.adapter_unit, scb->xfer->sc_link->target, scb->xfer->sc_link->lun, --- 857,864 ---- return (0); } ! /* Check for phase mismatch. FD 885 always seems to get this wrong! */ ! if ((*z->STATUS & PHASE_MASK) != PHASE_MSGOUT && z->type != CTLR_FUTURE_DOMAIN) { PRINT (("sea%d/%d/%d waiting for MSGOUT: invalid phase %s\n", z->sc_link.adapter_unit, scb->xfer->sc_link->target, scb->xfer->sc_link->lun, *************** *** 846,855 **** return (0); } ! /* Allow disconnects. */ ! *z->CONTROL = CMD_DRVR_ENABLE | z->parity; ! *z->DATA = MSG_IDENTIFY (scb->xfer->sc_link->lun); ! WAITREQ (&z->target[scb->xfer->sc_link->target], msgout, 1000); *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity; SET_BUSY (z, scb); --- 868,879 ---- return (0); } ! /* Allow disconnects. (except for FD controllers) */ ! if (z->type == CTLR_SEAGATE) { ! *z->CONTROL = CMD_DRVR_ENABLE | z->parity; ! *z->DATA = MSG_IDENTIFY (scb->xfer->sc_link->lun); ! WAITREQ (&z->target[scb->xfer->sc_link->target], msgout, 1000); ! } *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity; SET_BUSY (z, scb); *************** *** 881,887 **** /* Host responds by asserting the BSY signal. */ /* Target should respond by deasserting the SEL signal. */ target_mask &= ~z->scsi_id; ! *z->CONTROL = CMD_DRVR_ENABLE | CMD_BSY | z->parity; WAITFOR (! (*z->STATUS & STAT_SEL), "reselection acknowledge"); /* Remove the busy status. */ --- 905,911 ---- /* Host responds by asserting the BSY signal. */ /* Target should respond by deasserting the SEL signal. */ target_mask &= ~z->scsi_id; ! *z->CONTROL = CMD_DRVR_ENABLE | CMD_BSY | z->parity | CMD_INTR; WAITFOR (! (*z->STATUS & STAT_SEL), "reselection acknowledge"); /* Remove the busy status. */ *************** *** 1037,1044 **** */ void sea_data_output (adapter_t *z, u_char **pdata, u_long *plen) { ! u_char *data = *pdata; ! u_long len = *plen; asm ("cld 1: movb (%%ebx), %%al --- 1061,1068 ---- */ void sea_data_output (adapter_t *z, u_char **pdata, u_long *plen) { ! volatile u_char *data = *pdata; ! volatile u_long len = *plen; asm ("cld 1: movb (%%ebx), %%al *************** *** 1065,1072 **** */ void sea_data_input (adapter_t *z, u_char **pdata, u_long *plen) { ! u_char *data = *pdata; ! u_long len = *plen; if (len >= 512) { asm (" cld --- 1089,1096 ---- */ void sea_data_input (adapter_t *z, u_char **pdata, u_long *plen) { ! volatile u_char *data = *pdata; ! volatile u_long len = *plen; if (len >= 512) { asm (" cld *************** *** 1123,1129 **** PRINT (("%x", *cmd)); *z->DATA = *cmd++; ! WAITREQ (t, cmdout1, 10000); --cmdlen; while (cmdlen) { --- 1147,1154 ---- PRINT (("%x", *cmd)); *z->DATA = *cmd++; ! if (z->type == CTLR_SEAGATE) ! WAITREQ (t, cmdout1, 10000); --cmdlen; while (cmdlen) { *************** *** 1132,1140 **** if (! (sts & STAT_BSY)) break; ! /* Check for phase mismatch. */ ! if ((sts & PHASE_MASK) != PHASE_CMDOUT) { ! printf ("sea: sending command: invalid phase %s\n", PHASE_NAME (sts & PHASE_MASK)); return; } --- 1157,1165 ---- if (! (sts & STAT_BSY)) break; ! /* Check for phase mismatch. FD 885 seems to get this wrong! */ ! if ((sts & PHASE_MASK) != PHASE_CMDOUT && z->type != CTLR_FUTURE_DOMAIN) { ! printf ("sea: sea_cmd_output: invalid phase %s\n", PHASE_NAME (sts & PHASE_MASK)); return; } *************** *** 1145,1151 **** PRINT (("-%x", *cmd)); *z->DATA = *cmd++; ! WAITREQ (t, cmdout, 1000); --cmdlen; } PRINT (("\n")); --- 1170,1177 ---- PRINT (("-%x", *cmd)); *z->DATA = *cmd++; ! if (z->type == CTLR_SEAGATE) ! WAITREQ (t, cmdout, 1000); --cmdlen; } PRINT (("\n")); *************** *** 1197,1203 **** /* Check for phase mismatch. * Reached if the target decides that it has finished the transfer. */ if ((sts & PHASE_MASK) != PHASE_MSGIN) { ! printf ("sea: sending message: invalid phase %s\n", PHASE_NAME (sts & PHASE_MASK)); return (MSG_ABORT); } --- 1223,1229 ---- /* Check for phase mismatch. * Reached if the target decides that it has finished the transfer. */ if ((sts & PHASE_MASK) != PHASE_MSGIN) { ! printf ("sea: sea_msg_input: invalid phase %s\n", PHASE_NAME (sts & PHASE_MASK)); return (MSG_ABORT); } *************** *** 1343,1349 **** break; case PHASE_STATIN: scb->xfer->status = *z->DATA; ! WAITREQ (t, statin, 2000); PRINT (("sea%d/%d/%d (STATIN) got 0x%x\n", z->sc_link.adapter_unit, scb->xfer->sc_link->target, --- 1369,1376 ---- break; case PHASE_STATIN: scb->xfer->status = *z->DATA; ! if (z->type == CTLR_SEAGATE) ! WAITREQ (t, statin, 2000); PRINT (("sea%d/%d/%d (STATIN) got 0x%x\n", z->sc_link.adapter_unit, scb->xfer->sc_link->target, I do not speak for the Worker's Compensation Board of Queensland - They don't pay me enough for that!
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199507111149.LAA24598>