ahc_calc_residual(struct scb *scb) {
STATIC void	ahc_calc_residual __P((struct scb *scb));  STATIC void	ahc_update_pending_syncrates __P((struct ahc_softc *ahc));  STATIC void	ahc_set_recoveryscb __P((struct ahc_softc *ahc, struct scb *scb)); STATIC void ahc_timeout __P((void *));  static __inline int  sequencer_paused __P((struct ahc_softc *ahc)); static __inline void pause_sequencer __P((struct ahc_softc *ahc)); static __inline void unpause_sequencer __P((struct ahc_softc *ahc)); STATIC void restart_sequencer __P((struct ahc_softc *ahc)); static __inline u_int ahc_index_busy_tcl __P((struct ahc_softc *ahc, u_int tcl, int unbusy));  static __inline void	ahc_busy_tcl __P((struct ahc_softc *ahc, struct scb *scb)); static __inline int	ahc_isbusy_tcl __P((struct ahc_softc *ahc, struct scb *scb)); static __inline void ahc_freeze_ccb __P((struct scb* scb)); static __inline void ahcsetccbstatus __P((struct scsi_xfer *xs, int status)); STATIC void ahc_run_qoutfifo __P((struct ahc_softc *ahc));  static __inline struct ahc_initiator_tinfo * ahc_fetch_transinfo __P((struct ahc_softc *ahc, char channel, u_int our_id, u_int target, struct tmode_tstate **tstate)); STATIC void ahcfreescb __P((struct ahc_softc *ahc, struct scb *scb)); static __inline struct scb *ahcgetscb __P((struct ahc_softc *ahc)); int    ahc_createdmamem __P((struct ahc_softc *ahc, int size, bus_dmamap_t *mapp, caddr_t *vaddr, bus_addr_t *baddr, bus_dma_segment_t *segs, int *nseg, const char *what)); STATIC void ahc_freedmamem __P((bus_dma_tag_t tag, int size, bus_dmamap_t map, caddr_t vaddr, bus_dma_segment_t *seg, int nseg)); STATIC void ahcminphys __P((struct buf *bp));  STATIC INLINE	struct scsi_xfer *ahc_first_xs __P((struct ahc_softc *)); STATIC INLINE	void   ahc_list_insert_before __P((struct ahc_softc *ahc, struct scsi_xfer *xs, struct scsi_xfer *next_xs)); STATIC INLINE	void   ahc_list_insert_head __P((struct ahc_softc *ahc, struct scsi_xfer *xs)); STATIC INLINE	void   ahc_list_insert_tail __P((struct ahc_softc *ahc, struct scsi_xfer *xs)); STATIC INLINE	void   ahc_list_remove __P((struct ahc_softc *ahc, struct scsi_xfer *xs)); STATIC INLINE	struct scsi_xfer *ahc_list_next __P((struct ahc_softc *ahc, struct scsi_xfer *xs)); STATIC int32_t ahc_scsi_cmd __P((struct scsi_xfer *xs)); static __inline void ahc_swap_hscb __P((struct hardware_scb *)); static __inline void ahc_swap_sg __P((struct ahc_dma_seg *));  struct cfdriver ahc_cd = { NULL, "ahc", DV_DULL };  static struct scsi_adapter ahc_switch = { ahc_scsi_cmd, ahcminphys, 0, 0, };   static struct scsi_device ahc_dev = { NULL,  NULL,  NULL,  NULL,  };  static __inline void ahc_swap_hscb(struct hardware_scb *hscb) { hscb->SG_pointer = htole32(hscb->SG_pointer); hscb->data = htole32(hscb->data); hscb->datalen = htole32(hscb->datalen);  }  static __inline void ahc_swap_sg(struct ahc_dma_seg *sg) { sg->addr = htole32(sg->addr); sg->len = htole32(sg->len); }  STATIC void ahcminphys(bp) struct buf *bp; {  if (bp->b_bcount > ((AHC_NSEG - 1) * PAGE_SIZE)) { bp->b_bcount = ((AHC_NSEG - 1) * PAGE_SIZE); } minphys(bp); }   static __inline u_int32_t ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index) { return (ahc->scb_data->hscb_busaddr + (sizeof(struct hardware_scb) * index)); }  #define AHC_BUSRESET_DELAY	25	  static __inline int sequencer_paused(ahc) struct ahc_softc *ahc; { return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0); }  static __inline void pause_sequencer(ahc) struct ahc_softc *ahc; { ahc_outb(ahc, HCNTRL, ahc->pause);   while (sequencer_paused(ahc) == 0) ; }  static __inline void unpause_sequencer(ahc) struct ahc_softc *ahc; { if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0) ahc_outb(ahc, HCNTRL, ahc->unpause); }   STATIC void restart_sequencer(ahc) struct ahc_softc *ahc; { u_int i;  pause_sequencer(ahc);   ahc_outb(ahc, FREE_SCBH, SCB_LIST_NULL); for (i = 0; i < ahc->scb_data->maxhscbs; i++) {  ahc_outb(ahc, SCBPTR, i); if (ahc_inb(ahc, SCB_TAG) == SCB_LIST_NULL) ahc_add_curscb_to_free_list(ahc); } ahc_outb(ahc, SEQCTL, FASTMODE|SEQRESET); unpause_sequencer(ahc); }  static __inline u_int ahc_index_busy_tcl(ahc, tcl, unbusy) struct ahc_softc *ahc; u_int tcl; int unbusy; { u_int scbid;  scbid = ahc->untagged_scbs[tcl]; if (unbusy) { ahc->untagged_scbs[tcl] = SCB_LIST_NULL; bus_dmamap_sync(ahc->sc_dmat, ahc->shared_data_dmamap, UNTAGGEDSCB_OFFSET * 256, 256, BUS_DMASYNC_PREWRITE); }  return (scbid); }  static __inline void ahc_busy_tcl(ahc, scb) struct ahc_softc *ahc; struct scb *scb; { ahc->untagged_scbs[scb->hscb->tcl] = scb->hscb->tag; bus_dmamap_sync(ahc->sc_dmat, ahc->shared_data_dmamap, UNTAGGEDSCB_OFFSET * 256, 256, BUS_DMASYNC_PREWRITE); }  static __inline int ahc_isbusy_tcl(ahc, scb) struct ahc_softc *ahc; struct scb *scb; { return ahc->untagged_scbs[scb->hscb->tcl] != SCB_LIST_NULL; }  static __inline void ahc_freeze_ccb(scb) struct scb *scb; { struct scsi_xfer *xs = scb->xs; struct ahc_softc *ahc = (struct ahc_softc *)xs->sc_link->adapter_softc; int target;  target = xs->sc_link->target; if (!(scb->flags & SCB_FREEZE_QUEUE)) { ahc->devqueue_blocked[target]++; scb->flags |= SCB_FREEZE_QUEUE; } }  static __inline void ahcsetccbstatus(xs, status) struct scsi_xfer *xs; int status; { xs->error = status; }  static __inline struct ahc_initiator_tinfo * ahc_fetch_transinfo(ahc, channel, our_id, remote_id, tstate) struct ahc_softc *ahc; char channel; u_int our_id; u_int remote_id; struct tmode_tstate **tstate; {  if (channel == 'B') our_id += 8; *tstate = ahc->enabled_targets[our_id]; return (&(*tstate)->transinfo[remote_id]); }  STATIC void ahc_run_qoutfifo(ahc) struct ahc_softc *ahc; { struct scb *scb; u_int  scb_index;  bus_dmamap_sync(ahc->sc_dmat, ahc->shared_data_dmamap, 0, 256, BUS_DMASYNC_POSTREAD);  while (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) { scb_index = ahc->qoutfifo[ahc->qoutfifonext]; ahc->qoutfifo[ahc->qoutfifonext++] = SCB_LIST_NULL;  scb = &ahc->scb_data->scbarray[scb_index]; if (scb_index >= ahc->scb_data->numscbs || (scb->flags & SCB_ACTIVE) == 0) { printf("%s: WARNING no command for scb %d " "(cmdcmplt)\nQOUTPOS = %d\n", ahc_name(ahc), scb_index, ahc->qoutfifonext - 1); continue; }   if (scb->hscb->residual_SG_count != 0) ahc_calc_residual(scb); else scb->xs->resid = 0; ahc_done(ahc, scb); } }    STATIC void ahcfreescb(ahc, scb) struct ahc_softc *ahc; struct scb *scb; {
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}