sgptr &= ~SG_RESID_VALID;  if ((sgptr & SG_LIST_NULL) != 0)
} case BAD_PHASE: { u_int lastphase;  lastphase = ahc_inb(ahc, LASTPHASE); if (lastphase == P_BUSFREE) { printf("%s:%c:%d: Missed busfree.  Curphase = 0x%x\n", ahc_name(ahc), devinfo.channel, devinfo.target, ahc_inb(ahc, SCSISIGI)); restart_sequencer(ahc); return; } else { printf("%s:%c:%d: unknown scsi bus phase %x.  " "Attempting to continue\n", ahc_name(ahc), devinfo.channel, devinfo.target, ahc_inb(ahc, SCSISIGI)); } break; } case BAD_STATUS: { u_int  scb_index; struct hardware_scb *hscb; struct scsi_xfer *xs;  scb_index = ahc_inb(ahc, SCB_TAG); scb = &ahc->scb_data->scbarray[scb_index];   ahc_outb(ahc, RETURN_1, 0); if (!(scb_index < ahc->scb_data->numscbs && (scb->flags & SCB_ACTIVE) != 0)) { printf("%s:%c:%d: ahc_intr - referenced scb " "not valid during seqint 0x%x scb(%d)\n", ahc_name(ahc), devinfo.channel, devinfo.target, intstat, scb_index); goto unpause; }  hscb = scb->hscb; xs = scb->xs;   if ((scb->flags & SCB_SENSE) != 0) {  scb->flags &= ~SCB_SENSE; ahcsetccbstatus(xs, XS_DRIVER_STUFFUP); break; }  ahc_freeze_devq(ahc, xs->sc_link); ahc_freeze_ccb(scb); xs->status = hscb->status; switch (hscb->status) { case SCSI_OK: printf("%s: Interrupted for staus of 0???\n", ahc_name(ahc)); break; case SCSI_CHECK: #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOWSENSE) { sc_print_addr(scb->xs->sc_link); printf("SCB %d: requests Check Status\n", scb->hscb->tag); } #endif  if (xs->error == XS_NOERROR && !(scb->flags & SCB_SENSE)) { struct ahc_dma_seg *sg; struct scsi_sense *sc; struct ahc_initiator_tinfo *tinfo; struct tmode_tstate *tstate;  sg = scb->sg_list; sc = (struct scsi_sense *)(&hscb->cmdstore);  if (hscb->residual_SG_count != 0) ahc_calc_residual(scb); else xs->resid = 0;  #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOWSENSE) { sc_print_addr(scb->xs->sc_link); printf("Sending Sense\n"); } #endif sg->addr = ahc->scb_data->sense_busaddr + (hscb->tag*sizeof(struct scsi_sense_data));  sg->len = sizeof(struct scsi_sense_data);  sc->opcode = REQUEST_SENSE; sc->byte2 =  SCB_LUN(scb) << 5; sc->unused[0] = 0; sc->unused[1] = 0; sc->length = sg->len; sc->control = 0;   hscb->control = 0;   ahc_calc_residual(scb); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOWSENSE) { sc_print_addr(xs->sc_link); printf("Sense: datalen %d resid %d" "chan %d id %d targ %d\n", xs->datalen, xs->resid, devinfo.channel, devinfo.our_scsiid, devinfo.target); } #endif if (xs->datalen > 0 && xs->resid == xs->datalen) { tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, devinfo.our_scsiid, devinfo.target, &tstate); ahc_update_target_msg_request(ahc, &devinfo, tinfo, TRUE, TRUE); } hscb->status = 0; hscb->SG_count = 1; hscb->SG_pointer = scb->sg_list_phys; hscb->data = sg->addr; hscb->datalen = sg->len; hscb->cmdpointer = hscb->cmdstore_busaddr; hscb->cmdlen = sizeof(*sc); scb->sg_count = hscb->SG_count; ahc_swap_hscb(hscb); ahc_swap_sg(scb->sg_list); scb->flags |= SCB_SENSE;  ahc_busy_tcl(ahc, scb); ahc_outb(ahc, RETURN_1, SEND_SENSE);   if (!(scb->xs->flags & SCSI_POLL)) timeout_add(&scb->xs->stimeout, 5 * hz); } break; case SCSI_BUSY:  ahc_freeze_devq(ahc, xs->sc_link); ahc_freeze_ccb(scb); break; } break; } case TRACE_POINT: { printf("SSTAT2 = 0x%x DFCNTRL = 0x%x\n", ahc_inb(ahc, SSTAT2), ahc_inb(ahc, DFCNTRL)); printf("SSTAT3 = 0x%x DSTATUS = 0x%x\n", ahc_inb(ahc, SSTAT3), ahc_inb(ahc, DFSTATUS)); printf("SSTAT0 = 0x%x, SCB_DATACNT = 0x%x\n", ahc_inb(ahc, SSTAT0), ahc_inb(ahc, SCB_DATACNT)); break; } case HOST_MSG_LOOP: {  if (ahc->msg_type == MSG_TYPE_NONE) { u_int bus_phase;  bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; if (bus_phase != P_MESGIN && bus_phase != P_MESGOUT) { printf("ahc_intr: HOST_MSG_LOOP bad " "phase 0x%x\n", bus_phase);  ahc_clear_intstat(ahc); restart_sequencer(ahc); }  if (devinfo.role == ROLE_INITIATOR) { struct scb *scb; u_int scb_index;  scb_index = ahc_inb(ahc, SCB_TAG); scb = &ahc->scb_data->scbarray[scb_index];  if (bus_phase == P_MESGOUT) ahc_setup_initiator_msgout(ahc, &devinfo, scb); else { ahc->msg_type = MSG_TYPE_INITIATOR_MSGIN; ahc->msgin_index = 0; } } else { if (bus_phase == P_MESGOUT) { ahc->msg_type = MSG_TYPE_TARGET_MSGOUT; ahc->msgin_index = 0; } else  ahc_setup_target_msgin(ahc, &devinfo); } }   ahc_handle_message_phase(ahc, NULL); break; } case PERR_DETECTED: {  if ((intstat & SCSIINT) == 0 && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) { u_int curphase;   curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; ahc_outb(ahc, LASTPHASE, curphase); ahc_outb(ahc, SCSISIGO, curphase); ahc_inb(ahc, SCSIDATL); } break; } case DATA_OVERRUN: {  u_int scbindex = ahc_inb(ahc, SCB_TAG); u_int lastphase = ahc_inb(ahc, LASTPHASE); int i;  scb = &ahc->scb_data->scbarray[scbindex]; for (i = 0; i < num_phases; i++) { if (lastphase == phase_table[i].phase) break; } sc_print_addr(scb->xs->sc_link); printf("data overrun detected %s." "  Tag == 0x%x.\n", phase_table[i].phasemsg, scb->hscb->tag); sc_print_addr(scb->xs->sc_link); printf("%s seen Data Phase.  Length = %d.  NumSGs = %d.\n", ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", scb->xs->datalen, scb->sg_count); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x : Length %d\n", i, (unsigned int)le32toh(scb->sg_list[i].addr), (unsigned int)le32toh(scb->sg_list[i].len)); } }  ahc_freeze_devq(ahc, scb->xs->sc_link); ahcsetccbstatus(scb->xs, XS_DRIVER_STUFFUP); ahc_freeze_ccb(scb); break; } case TRACEPOINT: { printf("TRACEPOINT: RETURN_2 = %d\n", ahc_inb(ahc, RETURN_2)); #if 0 printf("SSTAT1 == 0x%x\n", ahc_inb(ahc, SSTAT1)); printf("SSTAT0 == 0x%x\n", ahc_inb(ahc, SSTAT0)); printf(", SCSISIGI == 0x%x\n", ahc_inb(ahc, SCSISIGI)); printf("TRACEPOINT: CCHCNT = %d, SG_COUNT = %d\n", ahc_inb(ahc, CCHCNT), ahc_inb(ahc, SG_COUNT)); printf("TRACEPOINT: SCB_TAG = %d\n", ahc_inb(ahc, SCB_TAG)); printf("TRACEPOINT1: CCHADDR = %d, CCHCNT = %d, SCBPTR = %d\n", ahc_inb(ahc, CCHADDR) | (ahc_inb(ahc, CCHADDR+1) << 8) | (ahc_inb(ahc, CCHADDR+2) << 16) | (ahc_inb(ahc, CCHADDR+3) << 24), ahc_inb(ahc, CCHCNT) | (ahc_inb(ahc, CCHCNT+1) << 8) | (ahc_inb(ahc, CCHCNT+2) << 16), ahc_inb(ahc, SCBPTR)); printf("TRACEPOINT: WAITING_SCBH = %d\n", ahc_inb(ahc, WAITING_SCBH)); printf("TRACEPOINT: SCB_TAG = %d\n", ahc_inb(ahc, SCB_TAG)); #endif break; } #if NOT_YET  case MESG_BUFFER_BUSY: break; case MSGIN_PHASEMIS: break; #endif default: printf("ahc_intr: seqint, " "intstat == 0x%x, scsisigi = 0x%x\n", intstat, ahc_inb(ahc, SCSISIGI)); break; }  unpause:  unpause_sequencer(ahc); }  STATIC void ahc_handle_scsiint(ahc, intstat) struct ahc_softc *ahc; u_int intstat; { u_int	scb_index; u_int	status; struct	scb *scb; char	cur_channel; char	intr_channel;  if ((ahc->features & AHC_TWIN) != 0 && ((ahc_inb(ahc, SBLKCTL) & SELBUSB) != 0)) cur_channel = 'B'; else cur_channel = 'A'; intr_channel = cur_channel;  status = ahc_inb(ahc, SSTAT1); if (status == 0) { if ((ahc->features & AHC_TWIN) != 0) {  ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); status = ahc_inb(ahc, SSTAT1); ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB); intr_channel = (cur_channel == 'A') ? 'B' : 'A'; } if (status == 0) { printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc)); return; } }  scb_index = ahc_inb(ahc, SCB_TAG); if (scb_index < ahc->scb_data->numscbs) { scb = &ahc->scb_data->scbarray[scb_index]; if ((scb->flags & SCB_ACTIVE) == 0 || (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) == 0) scb = NULL; } else scb = NULL;  if ((status & SCSIRSTI) != 0) { printf("%s: Someone reset channel %c\n", ahc_name(ahc), intr_channel); ahc_reset_channel(ahc, intr_channel, FALSE); } else if ((status & SCSIPERR) != 0) {  u_int mesg_out; u_int curphase; u_int errorphase; u_int lastphase; int   i;  lastphase = ahc_inb(ahc, LASTPHASE); curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK; ahc_outb(ahc, CLRSINT1, CLRSCSIPERR);  if ((ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0 || curphase == P_DATAIN) errorphase = curphase; else errorphase = lastphase;  for (i = 0; i < num_phases; i++) { if (errorphase == phase_table[i].phase) break; } mesg_out = phase_table[i].mesg_out; if (scb != NULL) sc_print_addr(scb->xs->sc_link); else printf("%s:%c:%d: ", ahc_name(ahc), intr_channel, TCL_TARGET(ahc_inb(ahc, SAVED_TCL)));  printf("parity error detected %s. " "SEQADDR(0x%x) SCSIRATE(0x%x)\n", phase_table[i].phasemsg, ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8), ahc_inb(ahc, SCSIRATE));   if (mesg_out != MSG_NOOP) { if (ahc->msg_type != MSG_TYPE_NONE) ahc->send_msg_perror = TRUE; else ahc_outb(ahc, MSG_OUT, mesg_out); } ahc_outb(ahc, CLRINT, CLRSCSIINT); unpause_sequencer(ahc); } else if ((status & BUSFREE) != 0 && (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {  u_int lastphase = ahc_inb(ahc, LASTPHASE); u_int saved_tcl = ahc_inb(ahc, SAVED_TCL); u_int target = TCL_TARGET(saved_tcl); u_int initiator_role_id = TCL_SCSI_ID(ahc, saved_tcl); char channel = TCL_CHANNEL(ahc, saved_tcl); int printerror = 1;  ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP)); if (lastphase == P_MESGOUT) { u_int message; u_int tag;  message = ahc->msgout_buf[ahc->msgout_index - 1]; tag = SCB_LIST_NULL; switch (message) { case MSG_ABORT_TAG: tag = scb->hscb->tag;  case MSG_ABORT: sc_print_addr(scb->xs->sc_link); printf("SCB %d - Abort %s Completed.\n", scb->hscb->tag, tag == SCB_LIST_NULL ? "" : "Tag"); ahc_abort_scbs(ahc, target, channel, TCL_LUN(saved_tcl), tag, ROLE_INITIATOR, XS_DRIVER_STUFFUP); printerror = 0; break; case MSG_BUS_DEV_RESET: { struct ahc_devinfo devinfo;  if (scb != NULL && (scb->xs->flags & SCSI_RESET) && ahc_match_scb(scb, target, channel, TCL_LUN(saved_tcl), SCB_LIST_NULL, ROLE_INITIATOR)) { ahcsetccbstatus(scb->xs, XS_NOERROR); } ahc_compile_devinfo(&devinfo, initiator_role_id, target, TCL_LUN(saved_tcl), channel, ROLE_INITIATOR); ahc_handle_devreset(ahc, &devinfo, XS_RESET, "Bus Device Reset", 0); printerror = 0; break; } default: break; } } if (printerror != 0) { int i;  if (scb != NULL) { u_int tag;  if ((scb->hscb->control & TAG_ENB) != 0) tag = scb->hscb->tag; else tag = SCB_LIST_NULL; ahc_abort_scbs(ahc, target, channel, SCB_LUN(scb), tag, ROLE_INITIATOR, XS_DRIVER_STUFFUP); sc_print_addr(scb->xs->sc_link); } else {  printf("%s: ", ahc_name(ahc)); } for (i = 0; i < num_phases; i++) { if (lastphase == phase_table[i].phase) break; } printf("Unexpected busfree %s\n" "SEQADDR == 0x%x\n", phase_table[i].phasemsg, ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); } ahc_clear_msg_state(ahc); ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE); ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR); ahc_outb(ahc, CLRINT, CLRSCSIINT); restart_sequencer(ahc); } else if ((status & SELTO) != 0) { u_int scbptr;  scbptr = ahc_inb(ahc, WAITING_SCBH); ahc_outb(ahc, SCBPTR, scbptr); scb_index = ahc_inb(ahc, SCB_TAG);  if (scb_index < ahc->scb_data->numscbs) { scb = &ahc->scb_data->scbarray[scb_index]; if ((scb->flags & SCB_ACTIVE) == 0) scb = NULL; } else scb = NULL;  if (scb == NULL) { printf("%s: ahc_intr - referenced scb not " "valid during SELTO scb(%d, %d)\n", ahc_name(ahc), scbptr, scb_index); } else { u_int tag;  tag = SCB_LIST_NULL; if ((scb->hscb->control & MSG_SIMPLE_Q_TAG) != 0) tag = scb->hscb->tag;  ahc_abort_scbs(ahc, SCB_TARGET(scb), SCB_CHANNEL(scb), SCB_LUN(scb), tag, ROLE_INITIATOR, XS_SELTIMEOUT); }  ahc_outb(ahc, SCSISEQ, 0);   ahc_clear_msg_state(ahc);   ahc_outb(ahc, CLRSINT0, CLRSELINGO);   ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR); ahc_outb(ahc, CLRINT, CLRSCSIINT); restart_sequencer(ahc); } else { sc_print_addr(scb->xs->sc_link); printf("Unknown SCSIINT. Status = 0x%x\n", status); ahc_outb(ahc, CLRSINT1, status); ahc_outb(ahc, CLRINT, CLRSCSIINT); unpause_sequencer(ahc); } }  STATIC void ahc_build_transfer_msg(ahc, devinfo) struct ahc_softc *ahc; struct ahc_devinfo *devinfo; {  struct	ahc_initiator_tinfo *tinfo; struct	tmode_tstate *tstate; int	dowide; int	dosync;  tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, devinfo->target, &tstate); dowide = tinfo->current.width != tinfo->goal.width; dosync = tinfo->current.period != tinfo->goal.period;  if (!dowide && !dosync) { dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT; dosync = tinfo->goal.period != 0; }  if (dowide) { ahc_construct_wdtr(ahc, tinfo->goal.width); } else if (dosync) { struct	ahc_syncrate *rate; u_int	period; u_int	offset;  period = tinfo->goal.period; rate = ahc_devlimited_syncrate(ahc, &period); offset = tinfo->goal.offset; ahc_validate_offset(ahc, rate, &offset, tinfo->current.width); ahc_construct_sdtr(ahc, period, offset); } else { panic("ahc_intr: AWAITING_MSG for negotiation, " "but no negotiation needed\n"); } }  STATIC void ahc_setup_initiator_msgout(ahc, devinfo, scb) struct ahc_softc *ahc; struct ahc_devinfo *devinfo; struct scb *scb; {  ahc->msgout_index = 0; ahc->msgout_len = 0;  if ((scb->flags & SCB_DEVICE_RESET) == 0 && ahc_inb(ahc, MSG_OUT) == MSG_IDENTIFYFLAG) { u_int identify_msg;  identify_msg = MSG_IDENTIFYFLAG | SCB_LUN(scb); if ((scb->hscb->control & DISCENB) != 0) identify_msg |= MSG_IDENTIFY_DISCFLAG; ahc->msgout_buf[ahc->msgout_index++] = identify_msg; ahc->msgout_len++;  if ((scb->hscb->control & TAG_ENB) != 0) {  ahc->msgout_buf[ahc->msgout_index++] = MSG_SIMPLE_Q_TAG; ahc->msgout_buf[ahc->msgout_index++] = scb->hscb->tag; ahc->msgout_len += 2; } }  if (scb->flags & SCB_DEVICE_RESET) { ahc->msgout_buf[ahc->msgout_index++] = MSG_BUS_DEV_RESET; ahc->msgout_len++;  sc_print_addr(scb->xs->sc_link); printf("Bus Device Reset Message Sent\n"); } else if (scb->flags & SCB_ABORT) { if ((scb->hscb->control & TAG_ENB) != 0) ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT_TAG; else ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT; ahc->msgout_len++; sc_print_addr(scb->xs->sc_link); printf("Abort Message Sent\n"); } else if ((ahc->targ_msg_req & devinfo->target_mask) != 0) { ahc_build_transfer_msg(ahc, devinfo); } else { printf("ahc_intr: AWAITING_MSG for an SCB that " "does not have a waiting message"); panic("SCB = %d, SCB Control = %x, MSG_OUT = %x " "SCB flags = %x", scb->hscb->tag, scb->hscb->control, ahc_inb(ahc, MSG_OUT), scb->flags); }   ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE); ahc->msgout_index = 0; ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; }  STATIC void ahc_setup_target_msgin(ahc, devinfo) struct ahc_softc *ahc; struct ahc_devinfo *devinfo; {  ahc->msgout_index = 0; ahc->msgout_len = 0;  if ((ahc->targ_msg_req & devinfo->target_mask) != 0) ahc_build_transfer_msg(ahc, devinfo); else panic("ahc_intr: AWAITING target message with no message");  ahc->msgout_index = 0; ahc->msg_type = MSG_TYPE_TARGET_MSGIN; }  STATIC int ahc_handle_msg_reject(ahc, devinfo) struct ahc_softc *ahc; struct ahc_devinfo *devinfo; {  struct scb *scb; u_int scb_index; u_int last_msg; int   response = 0;  scb_index = ahc_inb(ahc, SCB_TAG); scb = &ahc->scb_data->scbarray[scb_index];   last_msg = ahc_inb(ahc, LAST_MSG);  if (ahc_sent_msg(ahc, MSG_EXT_WDTR, FALSE)) { struct ahc_initiator_tinfo *tinfo; struct tmode_tstate *tstate;   if (bootverbose) printf("%s:%c:%d: refuses WIDE negotiation.  Using " "8bit transfers\n", ahc_name(ahc), devinfo->channel, devinfo->target); ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, TRUE, TRUE);  tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, devinfo->target, &tstate); if (tinfo->goal.period) { u_int period;   period = tinfo->goal.period; ahc_devlimited_syncrate(ahc, &period); ahc->msgout_index = 0; ahc->msgout_len = 0; ahc_construct_sdtr(ahc, period, tinfo->goal.offset); ahc->msgout_index = 0; response = 1; } } else if (ahc_sent_msg(ahc, MSG_EXT_SDTR, FALSE)) {  ahc_set_syncrate(ahc, devinfo, NULL, 0, 0, AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, TRUE, TRUE); if (bootverbose) printf("%s:%c:%d: refuses synchronous negotiation. " "Using asynchronous transfers\n", ahc_name(ahc), devinfo->channel, devinfo->target); } else if ((scb->hscb->control & MSG_SIMPLE_Q_TAG) != 0) { if (bootverbose) printf("%s:%c:%d: refuses tagged commands.  Performing " "non-tagged I/O\n", ahc_name(ahc), devinfo->channel, devinfo->target);  ahc_set_tags(ahc, devinfo, FALSE);   ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MSG_SIMPLE_Q_TAG); scb->hscb->control &= ~MSG_SIMPLE_Q_TAG; ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG); ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);   ahc_search_qinfifo(ahc, SCB_TARGET(scb), SCB_CHANNEL(scb), SCB_LUN(scb), SCB_LIST_NULL, ROLE_INITIATOR, SCB_REQUEUE, SEARCH_COMPLETE); } else {  printf("%s:%c:%d: Message reject for %x -- ignored\n", ahc_name(ahc), devinfo->channel, devinfo->target, last_msg); } return (response); }  STATIC void ahc_clear_msg_state(ahc) struct ahc_softc *ahc; { ahc->msgout_len = 0; ahc->msgin_index = 0; ahc->msg_type = MSG_TYPE_NONE; ahc_outb(ahc, MSG_OUT, MSG_NOOP); }  STATIC void ahc_handle_message_phase(ahc, sc_link) struct ahc_softc *ahc; struct scsi_link *sc_link; { struct	ahc_devinfo devinfo; u_int	bus_phase; int	end_session;  ahc_fetch_devinfo(ahc, &devinfo); end_session = FALSE; bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;  reswitch: switch (ahc->msg_type) { case MSG_TYPE_INITIATOR_MSGOUT: { int lastbyte; int phasemis; int msgdone;  if (ahc->msgout_len == 0) panic("REQINIT interrupt with no active message");  phasemis = bus_phase != P_MESGOUT; if (phasemis) { if (bus_phase == P_MESGIN) {  ahc_outb(ahc, CLRSINT1, CLRATNO); ahc->send_msg_perror = FALSE; ahc->msg_type = MSG_TYPE_INITIATOR_MSGIN; ahc->msgin_index = 0; goto reswitch; } end_session = TRUE; break; }  if (ahc->send_msg_perror) { ahc_outb(ahc, CLRSINT1, CLRATNO); ahc_outb(ahc, CLRSINT1, CLRREQINIT); ahc_outb(ahc, SCSIDATL, MSG_PARITY_ERROR); break; }  msgdone	= ahc->msgout_index == ahc->msgout_len; if (msgdone) {  ahc->msgout_index = 0; ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO); }  lastbyte = ahc->msgout_index == (ahc->msgout_len - 1); if (lastbyte) {  ahc_outb(ahc, CLRSINT1, CLRATNO); }   ahc_outb(ahc, CLRSINT1, CLRREQINIT); ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); break; } case MSG_TYPE_INITIATOR_MSGIN: { int phasemis; int message_done;  phasemis = bus_phase != P_MESGIN;  if (phasemis) { ahc->msgin_index = 0; if (bus_phase == P_MESGOUT && (ahc->send_msg_perror == TRUE || (ahc->msgout_len != 0 && ahc->msgout_index == 0))) { ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT; goto reswitch; } end_session = TRUE; break; }   ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIBUSL);  message_done = ahc_parse_msg(ahc, sc_link, &devinfo);  if (message_done) {  ahc->msgin_index = 0;   if (ahc->msgout_len != 0) ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO); } else ahc->msgin_index++;   ahc_outb(ahc, CLRSINT1, CLRREQINIT); ahc_inb(ahc, SCSIDATL); break; } case MSG_TYPE_TARGET_MSGIN: { int msgdone; int msgout_request;  if (ahc->msgout_len == 0) panic("Target MSGIN with no active message");   if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0 && ahc->msgout_index > 0) msgout_request = TRUE; else msgout_request = FALSE;  if (msgout_request) {   ahc->msg_type = MSG_TYPE_TARGET_MSGOUT; ahc_outb(ahc, SCSISIGO, P_MESGOUT | BSYO); ahc->msgin_index = 0;  ahc_inb(ahc, SCSIDATL); ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN); break; }  msgdone = ahc->msgout_index == ahc->msgout_len; if (msgdone) { ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); end_session = TRUE; break; }   ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN); ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]); break; } case MSG_TYPE_TARGET_MSGOUT: { int lastbyte; int msgdone;   lastbyte = (ahc_inb(ahc, SCSISIGI) & ATNI) == 0;   ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) & ~SPIOEN); ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIDATL); msgdone = ahc_parse_msg(ahc, sc_link, &devinfo); if (msgdone == MSGLOOP_TERMINATED) {  return; }  ahc->msgin_index++;   if (msgdone == MSGLOOP_MSGCOMPLETE) { ahc->msgin_index = 0;   if (ahc->msgout_len != 0) { ahc_outb(ahc, SCSISIGO, P_MESGIN | BSYO); ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN); ahc->msg_type = MSG_TYPE_TARGET_MSGIN; ahc->msgin_index = 0; break; } }  if (lastbyte) end_session = TRUE; else {  ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN); }  break; } default: panic("Unknown REQINIT message type"); }  if (end_session) { ahc_clear_msg_state(ahc); ahc_outb(ahc, RETURN_1, EXIT_MSG_LOOP); } else ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP); }   STATIC int ahc_sent_msg(ahc, msgtype, full) struct ahc_softc *ahc; u_int msgtype; int full; { int found; int index;  found = FALSE; index = 0;  while (index < ahc->msgout_len) { if (ahc->msgout_buf[index] == MSG_EXTENDED) {   if (ahc->msgout_buf[index+2] == msgtype) { u_int end_index;  end_index = index + 1 + ahc->msgout_buf[index + 1]; if (full) { if (ahc->msgout_index > end_index) found = TRUE; } else if (ahc->msgout_index > index) found = TRUE; } break; } else if (ahc->msgout_buf[index] >= MSG_SIMPLE_Q_TAG && ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {   index += 2; } else {  index++; } } return (found); }  STATIC int ahc_parse_msg(ahc, sc_link, devinfo) struct ahc_softc *ahc; struct scsi_link *sc_link; struct ahc_devinfo *devinfo; { struct	ahc_initiator_tinfo *tinfo; struct	tmode_tstate *tstate; int	reject; int	done; int	response; u_int	targ_scsirate;  done = MSGLOOP_IN_PROG; response = FALSE; reject = FALSE; tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, devinfo->target, &tstate); targ_scsirate = tinfo->scsirate;   switch (ahc->msgin_buf[0]) { case MSG_MESSAGE_REJECT: response = ahc_handle_msg_reject(ahc, devinfo);  case MSG_NOOP: done = MSGLOOP_MSGCOMPLETE; break; case MSG_IGN_WIDE_RESIDUE: {  if (ahc->msgin_index >= 1) { if (ahc->msgin_buf[1] != 1 || tinfo->current.width == MSG_EXT_WDTR_BUS_8_BIT) { reject = TRUE; done = MSGLOOP_MSGCOMPLETE; } else ahc_handle_ign_wide_residue(ahc, devinfo); } break; } case MSG_EXTENDED: {  if (ahc->msgin_index < 2) break; switch (ahc->msgin_buf[2]) { case MSG_EXT_SDTR: { struct	 ahc_syncrate *syncrate; u_int	 period; u_int	 offset; u_int	 saved_offset;  if (ahc->msgin_buf[1] != MSG_EXT_SDTR_LEN) { reject = TRUE; break; }   if (ahc->msgin_index < (MSG_EXT_SDTR_LEN + 1)) break;  period = ahc->msgin_buf[3]; saved_offset = offset = ahc->msgin_buf[4]; syncrate = ahc_devlimited_syncrate(ahc, &period); ahc_validate_offset(ahc, syncrate, &offset, targ_scsirate & WIDEXFER); ahc_set_syncrate(ahc, devinfo, syncrate, period, offset, AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, TRUE, TRUE);   if (ahc_sent_msg(ahc, MSG_EXT_SDTR, TRUE)) {  if (saved_offset != offset) {  reject = TRUE; } } else {  if (bootverbose) printf("Sending SDTR!\n"); ahc->msgout_index = 0; ahc->msgout_len = 0; ahc_construct_sdtr(ahc, period, offset); ahc->msgout_index = 0; response = TRUE; } done = MSGLOOP_MSGCOMPLETE; break; } case MSG_EXT_WDTR: { u_int	bus_width; u_int	sending_reply;  sending_reply = FALSE; if (ahc->msgin_buf[1] != MSG_EXT_WDTR_LEN) { reject = TRUE; break; }   if (ahc->msgin_index < (MSG_EXT_WDTR_LEN + 1)) break;  bus_width = ahc->msgin_buf[3]; if (ahc_sent_msg(ahc, MSG_EXT_WDTR, TRUE)) {  switch (bus_width){ default:  reject = TRUE; printf("%s: target %d requested %dBit " "transfers.  Rejecting...\n", ahc_name(ahc), devinfo->target, 8 * (0x01 << bus_width));  case MSG_EXT_WDTR_BUS_8_BIT: bus_width = MSG_EXT_WDTR_BUS_8_BIT; break; case MSG_EXT_WDTR_BUS_16_BIT: break; } } else {  if (bootverbose) printf("Sending WDTR!\n"); switch (bus_width) { default: if (ahc->features & AHC_WIDE) {  bus_width = MSG_EXT_WDTR_BUS_16_BIT; break; }  case MSG_EXT_WDTR_BUS_8_BIT: bus_width = MSG_EXT_WDTR_BUS_8_BIT; break; } ahc->msgout_index = 0; ahc->msgout_len = 0; ahc_construct_wdtr(ahc, bus_width); ahc->msgout_index = 0; response = TRUE; sending_reply = TRUE; } ahc_set_width(ahc, devinfo, bus_width, AHC_TRANS_ACTIVE|AHC_TRANS_GOAL, TRUE, TRUE);   ahc_set_syncrate(ahc, devinfo, NULL, 0, 0, AHC_TRANS_ACTIVE, TRUE, FALSE); if (sending_reply == FALSE && reject == FALSE) {  if (tinfo->goal.period) { struct	ahc_syncrate *rate; u_int	period; u_int	offset;   period = tinfo->goal.period; rate = ahc_devlimited_syncrate(ahc, &period); offset = tinfo->goal.offset; ahc_validate_offset(ahc, rate, &offset, tinfo->current.width); ahc->msgout_index = 0; ahc->msgout_len = 0; ahc_construct_sdtr(ahc, period, offset); ahc->msgout_index = 0; response = TRUE; } } done = MSGLOOP_MSGCOMPLETE; break; } default:  reject = TRUE; break; } break; } case MSG_BUS_DEV_RESET: ahc_handle_devreset(ahc, devinfo, XS_RESET, "Bus Device Reset Received", 0); restart_sequencer(ahc); done = MSGLOOP_TERMINATED; break; case MSG_ABORT_TAG: case MSG_ABORT: case MSG_CLEAR_QUEUE:  if (devinfo->role != ROLE_TARGET) { reject = TRUE; break; } #if AHC_TARGET_MODE ahc_abort_scbs(ahc, devinfo->target, devinfo->channel, devinfo->lun, ahc->msgin_buf[0] == MSG_ABORT_TAG ? SCB_LIST_NULL : ahc_inb(ahc, INITIATOR_TAG), ROLE_TARGET, XS_DRIVER_STUFFUP);  tstate = ahc->enabled_targets[devinfo->our_scsiid]; if (tstate != NULL) { struct tmode_lstate* lstate;  lstate = tstate->enabled_luns[devinfo->lun]; if (lstate != NULL) { ahc_queue_lstate_event(ahc, lstate, devinfo->our_scsiid, ahc->msgin_buf[0], 0); ahc_send_lstate_events(ahc, lstate); } } done = MSGLOOP_MSGCOMPLETE; #else panic("ahc: got target mode message"); #endif break; case MSG_TERM_IO_PROC: default: reject = TRUE; break; }  if (reject) {  ahc->msgout_index = 0; ahc->msgout_len = 1; ahc->msgout_buf[0] = MSG_MESSAGE_REJECT; done = MSGLOOP_MSGCOMPLETE; response = TRUE; }  if (done != MSGLOOP_IN_PROG && !response)  ahc->msgout_len = 0;  return (done); }  STATIC void ahc_handle_ign_wide_residue(ahc, devinfo) struct ahc_softc *ahc; struct ahc_devinfo *devinfo; { u_int scb_index; struct scb *scb;  scb_index = ahc_inb(ahc, SCB_TAG); scb = &ahc->scb_data->scbarray[scb_index]; if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0 || !(scb->xs->flags & SCSI_DATA_IN)) {  } else {  u_int resid_sgcnt;  resid_sgcnt = ahc_inb(ahc, SCB_RESID_SGCNT); if (resid_sgcnt == 0 && ahc_inb(ahc, DATA_COUNT_ODD) == 1) {  } else { u_int data_cnt; u_int data_addr; u_int sg_index;  data_cnt = (ahc_inb(ahc, SCB_RESID_DCNT + 2) << 16) | (ahc_inb(ahc, SCB_RESID_DCNT + 1) << 8) | (ahc_inb(ahc, SCB_RESID_DCNT));  data_addr = (ahc_inb(ahc, SHADDR + 3) << 24) | (ahc_inb(ahc, SHADDR + 2) << 16) | (ahc_inb(ahc, SHADDR + 1) << 8) | (ahc_inb(ahc, SHADDR));  data_cnt += 1; data_addr -= 1;  sg_index = scb->sg_count - resid_sgcnt;  if (sg_index != 0 && (le32toh(scb->sg_list[sg_index].len) < data_cnt)) { u_int32_t sg_addr;  sg_index--; data_cnt = 1; data_addr = le32toh(scb->sg_list[sg_index].addr) + le32toh(scb->sg_list[sg_index].len) - 1;   sg_addr = scb->sg_list_phys + (sg_index* sizeof(*scb->sg_list)); ahc_outb(ahc, SG_NEXT + 3, sg_addr >> 24); ahc_outb(ahc, SG_NEXT + 2, sg_addr >> 16); ahc_outb(ahc, SG_NEXT + 1, sg_addr >> 8); ahc_outb(ahc, SG_NEXT, sg_addr); }  ahc_outb(ahc, SCB_RESID_DCNT + 2, data_cnt >> 16); ahc_outb(ahc, SCB_RESID_DCNT + 1, data_cnt >> 8); ahc_outb(ahc, SCB_RESID_DCNT, data_cnt);  ahc_outb(ahc, SHADDR + 3, data_addr >> 24); ahc_outb(ahc, SHADDR + 2, data_addr >> 16); ahc_outb(ahc, SHADDR + 1, data_addr >> 8); ahc_outb(ahc, SHADDR, data_addr); } } }  STATIC void ahc_handle_devreset(ahc, devinfo, status, message, verbose_level) struct ahc_softc *ahc; struct ahc_devinfo *devinfo; int status; char *message; int verbose_level; { int found;  found = ahc_abort_scbs(ahc, devinfo->target, devinfo->channel, ALL_LUNS, SCB_LIST_NULL, devinfo->role, status);   ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT, AHC_TRANS_CUR, TRUE, FALSE); ahc_set_syncrate(ahc, devinfo, NULL, 0, 0, AHC_TRANS_CUR, TRUE, FALSE);  if (message != NULL && (verbose_level <= bootverbose)) printf("%s: %s on %c:%d. %d SCBs aborted\n", ahc_name(ahc), message, devinfo->channel, devinfo->target, found); }   STATIC void ahc_done(ahc, scb) struct ahc_softc *ahc; struct scb *scb; { struct scsi_xfer *xs = scb->xs; struct scsi_link *sc_link = xs->sc_link; int requeue = 0; int target;  SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_done\n"));  LIST_REMOVE(scb, pend_links);  timeout_del(&scb->xs->stimeout);  #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOWCMDS) { sc_print_addr(sc_link); printf("ahc_done opcode %d tag %x\n", xs->cmdstore.opcode, scb->hscb->tag); } #endif  target = sc_link->target;  if (xs->datalen) { int op;  if ((xs->flags & SCSI_DATA_IN) != 0) op = BUS_DMASYNC_POSTREAD; else op = BUS_DMASYNC_POSTWRITE; bus_dmamap_sync(ahc->sc_dmat, scb->dmamap, 0, scb->dmamap->dm_mapsize, op); bus_dmamap_unload(ahc->sc_dmat, scb->dmamap); }   if (!(scb->hscb->control & TAG_ENB)) ahc_index_busy_tcl(ahc, scb->hscb->tcl, TRUE);   if ((scb->flags & SCB_RECOVERY_SCB) != 0) {  struct	scb *scbp;   scbp = ahc->pending_scbs.lh_first; while (scbp != NULL) { struct scsi_xfer *txs = scbp->xs;  if (!(txs->flags & SCSI_POLL)) timeout_add(&scbp->xs->stimeout, (scbp->xs->timeout * hz)/1000); scbp = LIST_NEXT(scbp, pend_links); }   ahc_search_qinfifo(ahc, SCB_TARGET(scb), SCB_CHANNEL(scb), SCB_LUN(scb), scb->hscb->tag, ROLE_INITIATOR, 0, SEARCH_REMOVE); if (xs->error != XS_NOERROR) ahcsetccbstatus(xs, XS_TIMEOUT); sc_print_addr(xs->sc_link); printf("no longer in timeout, status = %x\n", xs->status); }  if (xs->error != XS_NOERROR) {  } else if ((scb->flags & SCB_SENSE) != 0) {  bzero(&xs->sense, sizeof(struct scsi_sense)); bcopy(&ahc->scb_data->sense[scb->hscb->tag], &xs->sense, le32toh(scb->sg_list->len)); xs->error = XS_SENSE; } if (scb->flags & SCB_FREEZE_QUEUE) { ahc->devqueue_blocked[target]--; scb->flags &= ~SCB_FREEZE_QUEUE; }  requeue = scb->flags & SCB_REQUEUE; ahcfreescb(ahc, scb);  if (requeue) {  int s;  s = splbio();  ahc_list_insert_head(ahc, xs); splx(s); } else { xs->flags |= ITSDONE; ahc_check_tags(ahc, xs); scsi_done(xs); }   if ((xs = ahc->sc_xxxq.lh_first) != NULL) (void) ahc_scsi_cmd(xs); }   int ahc_probe_scbs(ahc) struct ahc_softc *ahc; { int i;  for (i = 0; i < AHC_SCB_MAX; i++) { ahc_outb(ahc, SCBPTR, i); ahc_outb(ahc, SCB_CONTROL, i); if (ahc_inb(ahc, SCB_CONTROL) != i) break; ahc_outb(ahc, SCBPTR, 0); if (ahc_inb(ahc, SCB_CONTROL) != 0) break; }  return (i); }   int ahc_init(ahc) struct ahc_softc *ahc; { int	  max_targ = 15; int	  i; int	  term; u_int	  scsi_conf; u_int	  scsiseq_template; u_int	  ultraenb; u_int	  discenable; u_int	  tagenable; size_t	  driver_data_size; u_int32_t physaddr; struct scb_data *scb_data = NULL;  #ifdef AHC_PRINT_SRAM printf("Scratch Ram:"); for (i = 0x20; i < 0x5f; i++) { if (((i % 8) == 0) && (i != 0)) { printf ("\n              "); } printf (" 0x%x", ahc_inb(ahc, i)); } if ((ahc->features & AHC_MORE_SRAM) != 0) { for (i = 0x70; i < 0x7f; i++) { if (((i % 8) == 0) && (i != 0)) { printf ("\n              "); } printf (" 0x%x", ahc_inb(ahc, i)); } } printf ("\n"); #endif  if (ahc->scb_data == NULL) { scb_data = malloc(sizeof (struct scb_data), M_DEVBUF, M_NOWAIT); if (scb_data == NULL) { printf("%s: cannot malloc scb_data!\n", ahc_name(ahc)); return (ENOMEM); } bzero(scb_data, sizeof(struct scb_data)); ahc->scb_data = scb_data; }  if ((ahc->flags & AHC_USEDEFAULTS) != 0) ahc->our_id = ahc->our_id_b = 7;   ahc->flags |= AHC_INITIATORMODE;   driver_data_size = 3 * 256 * sizeof(u_int8_t);  if (ahc_createdmamem(ahc, driver_data_size, &ahc->shared_data_dmamap, (caddr_t *)&ahc->qoutfifo, &ahc->shared_data_busaddr, &ahc->shared_data_seg, &ahc->shared_data_nseg, "shared data") < 0) return (ENOMEM);  ahc->init_level++;   if (ahc->scb_data->maxhscbs == 0) if (ahcinitscbdata(ahc) != 0) return (ENOMEM);  ahc->qinfifo = &ahc->qoutfifo[256]; ahc->untagged_scbs = &ahc->qinfifo[256];  for (i = 0; i < 256; i++) ahc->untagged_scbs[i] = SCB_LIST_NULL;   for (i = 0; i < 256; i++) ahc->qoutfifo[i] = SCB_LIST_NULL;  bus_dmamap_sync(ahc->sc_dmat, ahc->shared_data_dmamap, 0, driver_data_size, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);   if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) { printf("%s: unable to allocate tmode_tstate.  " "Failing attach\n", ahc_name(ahc)); return (-1); }  if ((ahc->features & AHC_TWIN) != 0) { if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) { printf("%s: unable to allocate tmode_tstate.  " "Failing attach\n", ahc_name(ahc)); return (-1); } printf("Twin Channel, A SCSI Id=%d, B SCSI Id=%d, primary %c, ", ahc->our_id, ahc->our_id_b, ahc->flags & AHC_CHANNEL_B_PRIMARY? 'B': 'A'); } else { if ((ahc->features & AHC_WIDE) != 0) { printf("Wide "); } else { printf("Single "); } printf("Channel %c, SCSI Id=%d, ", ahc->channel, ahc->our_id); }  ahc_outb(ahc, SEQ_FLAGS, 0);  if (ahc->scb_data->maxhscbs < AHC_SCB_MAX) { ahc->flags |= AHC_PAGESCBS; printf("%d/%d SCBs\n", ahc->scb_data->maxhscbs, AHC_SCB_MAX); } else { ahc->flags &= ~AHC_PAGESCBS; printf("%d SCBs\n", ahc->scb_data->maxhscbs); }  #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOWMISC) { printf("%s: hardware scb %d bytes; kernel scb %d bytes; " "ahc_dma %d bytes\n", ahc_name(ahc), sizeof(struct hardware_scb), sizeof(struct scb), sizeof(struct ahc_dma_seg)); } #endif    if (ahc->features & AHC_TWIN) {   term = (ahc->flags & AHC_TERM_ENB_B) != 0 ? STPWEN : 0; if ((ahc->features & AHC_ULTRA2) != 0) ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id_b); else ahc_outb(ahc, SCSIID, ahc->our_id_b); scsi_conf = ahc_inb(ahc, SCSICONF + 1); ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL)) |term|ENSTIMER|ACTNEGEN); ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);  if ((scsi_conf & RESET_SCSI) != 0 && (ahc->flags & AHC_INITIATORMODE) != 0) ahc->flags |= AHC_RESET_BUS_B;   ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB); } term = (ahc->flags & AHC_TERM_ENB_A) != 0 ? STPWEN : 0; if ((ahc->features & AHC_ULTRA2) != 0) ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id); else ahc_outb(ahc, SCSIID, ahc->our_id); scsi_conf = ahc_inb(ahc, SCSICONF); ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL)) |term |ENSTIMER|ACTNEGEN); ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR); ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);  if ((scsi_conf & RESET_SCSI) != 0 && (ahc->flags & AHC_INITIATORMODE) != 0) ahc->flags |= AHC_RESET_BUS_A;   ultraenb = 0; tagenable = ALL_TARGETS_MASK;   if (ahc->flags & AHC_USEDEFAULTS) { printf("%s: Host Adapter Bios disabled.  Using default SCSI " "device parameters\n", ahc_name(ahc)); ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B| AHC_TERM_ENB_A|AHC_TERM_ENB_B; discenable = ALL_TARGETS_MASK; if ((ahc->features & AHC_ULTRA) != 0) ultraenb = ALL_TARGETS_MASK; } else { discenable = ~((ahc_inb(ahc, DISC_DSB + 1) << 8) | ahc_inb(ahc, DISC_DSB)); if ((ahc->features & (AHC_ULTRA|AHC_ULTRA2)) != 0) ultraenb = (ahc_inb(ahc, ULTRA_ENB + 1) << 8) | ahc_inb(ahc, ULTRA_ENB); }  if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0) max_targ = 7;  for (i = 0; i <= max_targ; i++) { struct ahc_initiator_tinfo *tinfo; struct tmode_tstate *tstate; u_int our_id; u_int target_id; char channel;  channel = 'A'; our_id = ahc->our_id; target_id = i; if (i > 7 && (ahc->features & AHC_TWIN) != 0) { channel = 'B'; our_id = ahc->our_id_b; target_id = i % 8; } tinfo = ahc_fetch_transinfo(ahc, channel, our_id, target_id, &tstate);  bzero(tinfo, sizeof(*tinfo)); if (ahc->flags & AHC_USEDEFAULTS) { if ((ahc->features & AHC_WIDE) != 0) tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;   tinfo->user.period = ahc_syncrates->period; tinfo->user.offset = ~0; } else { u_int scsirate; u_int16_t mask;   scsirate = ahc_inb(ahc, TARG_SCSIRATE + i); mask = (0x01 << i); if ((ahc->features & AHC_ULTRA2) != 0) { u_int offset; u_int maxsync;  if ((scsirate & SOFS) == 0x0F) {  scsirate = (scsirate & SXFR) >> 4 | (ultraenb & mask) ? 0x08 : 0x0 | (scsirate & WIDEXFER); offset = MAX_OFFSET_ULTRA2; } else offset = ahc_inb(ahc, TARG_OFFSET + i); maxsync = AHC_SYNCRATE_ULTRA2; if ((ahc->features & AHC_DT) != 0) maxsync = AHC_SYNCRATE_DT; tinfo->user.period = ahc_find_period(ahc, scsirate, maxsync); if (offset == 0) tinfo->user.period = 0; else tinfo->user.offset = ~0; } else if ((scsirate & SOFS) != 0) { tinfo->user.period = ahc_find_period(ahc, scsirate, (ultraenb & mask) ? AHC_SYNCRATE_ULTRA : AHC_SYNCRATE_FAST); if (tinfo->user.period != 0) tinfo->user.offset = ~0; } if ((scsirate & WIDEXFER) != 0 && (ahc->features & AHC_WIDE) != 0) tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT; } tinfo->goal = tinfo->user;  tstate->ultraenb = ultraenb; tstate->discenable = discenable; tstate->tagenable = 0;  tstate->tagdisable = 0; } ahc->user_discenable = discenable; ahc->user_tagenable = tagenable;   physaddr = ahc->scb_data->hscb_busaddr; ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF); ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF); ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF); ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF);  physaddr = ahc->shared_data_busaddr; ahc_outb(ahc, SCBID_ADDR, physaddr & 0xFF); ahc_outb(ahc, SCBID_ADDR + 1, (physaddr >> 8) & 0xFF); ahc_outb(ahc, SCBID_ADDR + 2, (physaddr >> 16) & 0xFF); ahc_outb(ahc, SCBID_ADDR + 3, (physaddr >> 24) & 0xFF);   physaddr += 3 * 256 * sizeof(u_int8_t); ahc_outb(ahc, TMODE_CMDADDR, physaddr & 0xFF); ahc_outb(ahc, TMODE_CMDADDR + 1, (physaddr >> 8) & 0xFF); ahc_outb(ahc, TMODE_CMDADDR + 2, (physaddr >> 16) & 0xFF); ahc_outb(ahc, TMODE_CMDADDR + 3, (physaddr >> 24) & 0xFF);   ahc_outb(ahc, CMDSIZE_TABLE, 5); ahc_outb(ahc, CMDSIZE_TABLE + 1, 9); ahc_outb(ahc, CMDSIZE_TABLE + 2, 9); ahc_outb(ahc, CMDSIZE_TABLE + 3, 0); ahc_outb(ahc, CMDSIZE_TABLE + 4, 15); ahc_outb(ahc, CMDSIZE_TABLE + 5, 11); ahc_outb(ahc, CMDSIZE_TABLE + 6, 0); ahc_outb(ahc, CMDSIZE_TABLE + 7, 0);   ahc_outb(ahc, KERNEL_QINPOS, 0); ahc_outb(ahc, QINPOS, 0); ahc_outb(ahc, QOUTPOS, 0);  #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOWMISC) printf("DISCENABLE == 0x%x\nULTRAENB == 0x%x\n", discenable, ultraenb); #endif   ahc_outb(ahc, TARGET_MSG_REQUEST, 0); ahc_outb(ahc, TARGET_MSG_REQUEST + 1, 0);   if ((ahc->features & AHC_QUEUE_REGS) != 0) { ahc_outb(ahc, QOFF_CTLSTA, SCB_QSIZE_256); ahc_outb(ahc, SDSCB_QOFF, 0); ahc_outb(ahc, SNSCB_QOFF, 0); ahc_outb(ahc, HNSCB_QOFF, 0); }    ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL);   ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL);   ahc_outb(ahc, MSG_OUT, MSG_NOOP);   scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP; if ((ahc->flags & AHC_INITIATORMODE) != 0) scsiseq_template |= ENRSELI; ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template);   if (bootverbose) printf("%s: Downloading Sequencer Program...", ahc_name(ahc));  ahc_loadseq(ahc);   shutdownhook_establish(ahc_shutdown, ahc); return (0); }   STATIC INLINE void ahc_list_insert_before(ahc, xs, next_xs) struct ahc_softc *ahc; struct scsi_xfer *xs; struct scsi_xfer *next_xs; { LIST_INSERT_BEFORE(xs, next_xs, free_list);  }  STATIC INLINE void ahc_list_insert_head(ahc, xs) struct ahc_softc *ahc; struct scsi_xfer *xs; { if (ahc->sc_xxxq.lh_first == NULL) ahc->sc_xxxqlast = xs; LIST_INSERT_HEAD(&ahc->sc_xxxq, xs, free_list); return; }  STATIC INLINE void ahc_list_insert_tail(ahc, xs) struct ahc_softc *ahc; struct scsi_xfer *xs; { if (ahc->sc_xxxq.lh_first == NULL){ ahc->sc_xxxqlast = xs; LIST_INSERT_HEAD(&ahc->sc_xxxq, xs, free_list);
ahc_calc_residual(struct scb *scb){	struct hardware_scb *hscb;	struct status_pkt *spkt;	uint32_t sgptr;	uint32_t resid_sgptr;	uint32_t resid;	/*	 * 5 cases.	 * 1) No residual.	 *    SG_RESID_VALID clear in sgptr.	 * 2) Transferless command	 * 3) Never performed any transfers.	 *    sgptr has SG_FULL_RESID set.	 * 4) No residual but target did not	 *    save data pointers after the	 *    last transfer, so sgptr was	 *    never updated.	 * 5) We have a partial residual.	 *    Use residual_sgptr to determine	 *    where we are.	 */	hscb = scb->hscb;	sgptr = ahc_le32toh(hscb->sgptr);	if ((sgptr & SG_RESID_VALID) == 0)		/* Case 1 */		return;	sgptr &= ~SG_RESID_VALID;	if ((sgptr & SG_LIST_NULL) != 0)		/* Case 2 */		return;	spkt = &hscb->shared_data.status;	resid_sgptr = ahc_le32toh(spkt->residual_sg_ptr);	if ((sgptr & SG_FULL_RESID) != 0) {		/* Case 3 */		resid = ahc_get_transfer_length(scb);	} else if ((resid_sgptr & SG_LIST_NULL) != 0) {		/* Case 4 */		return;	} else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {		panic("Bogus resid sgptr value 0x%x\n", resid_sgptr);	} else {		struct ahc_dma_seg *sg;		/*		 * Remainder of the SG where the transfer		 * stopped.  		 */		resid = ahc_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK;		sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK);		/* The residual sg_ptr always points to the next sg */		sg--;		/*		 * Add up the contents of all residual		 * SG segments that are after the SG where		 * the transfer stopped.		 */		while ((ahc_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) {			sg++;			resid += ahc_le32toh(sg->len) & AHC_SG_LEN_MASK;		}	}	if ((scb->flags & SCB_SENSE) == 0)		ahc_set_residual(scb, resid);	else		ahc_set_sense_residual(scb, resid);#ifdef AHC_DEBUG	if (ahc_debug & AHC_SHOWMISC) {		ahc_print_path(scb->ahc_softc, scb);		printf("Handled Residual of %d bytes\n", resid);	}#endif}