switch (phase) { case PHASE_CMDOUT: if (xfer->c_flags & C_SENSE) { bzero(cmd_reqsense, sizeof(struct scsi_generic)); cmd_reqsense->opcode = REQUEST_SENSE; cmd_reqsense->length = xfer->c_bcount; bcopy(cmd_reqsense, cmd, sizeof(struct scsi_generic)); } else { bcopy(sc_xfer->cmd, cmd, sc_xfer->cmdlen); } WDCDEBUG_PRINT(("PHASE_CMDOUT\n"), DEBUG_INTR);  if (xfer->c_flags & C_DMA) { if ((*chp->wdc->dma_init)(chp->wdc->dma_arg, chp->channel, xfer->drive, xfer->databuf, xfer->c_bcount, dma_flags) != 0) { sc_xfer->error = XS_DRIVER_STUFFUP; break; } }
as->protocol_phase = as_none;
wdc_atapi_intr(chp, xfer, irq)	struct channel_softc *chp;	struct wdc_xfer *xfer;	int irq;{	struct scsi_xfer *sc_xfer = xfer->cmd;	struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];	int len, phase, i, retries=0;	int ire, dma_err = 0;	int dma_flags = 0;	struct scsi_generic _cmd_reqsense;	struct scsi_sense *cmd_reqsense =	    (struct scsi_sense *)&_cmd_reqsense;	u_int32_t cmd[4];	int cmdlen = (drvp->atapi_cap & ACAP_LEN) ? 16 : 12;	bzero(cmd, sizeof(cmd));	WDCDEBUG_PRINT(("wdc_atapi_intr %s:%d:%d\n",	    chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive), DEBUG_INTR);	/* Is it not a transfer, but a control operation? */	if (drvp->state < READY) {		printf("%s:%d:%d: bad state %d in wdc_atapi_intr\n",		    chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,		    drvp->state);		panic("wdc_atapi_intr: bad state\n");	}	/* We should really wait_for_unbusy here too before 	   switching drives. */	bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,	    WDSD_IBM | (xfer->drive << 4));	/* Ack interrupt done in wait_for_unbusy */	if (wait_for_unbusy(chp,	    (irq == 0) ? sc_xfer->timeout : 0) != 0) {		if (irq && (xfer->c_flags & C_TIMEOU) == 0)			return (0); /* IRQ was not for us */		printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n",		    chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,		    xfer->c_bcount, xfer->c_skip);		if (xfer->c_flags & C_DMA)			drvp->n_dmaerrs++;		sc_xfer->error = XS_TIMEOUT;		wdc_atapi_reset(chp, xfer);		return (1);	}	/* If we missed an IRQ and were using DMA, flag it as a DMA error */	if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA))		drvp->n_dmaerrs++;	/* 	 * if the request sense command was aborted, report the short sense	 * previously recorded, else continue normal processing	 */	if ((xfer->c_flags & C_SENSE) != 0 &&	    (chp->ch_status & WDCS_ERR) != 0 &&	    (chp->ch_error & WDCE_ABRT) != 0) {		WDCDEBUG_PRINT(("wdc_atapi_intr: request_sense aborted, "		    "calling wdc_atapi_done()"		    ), DEBUG_INTR);		wdc_atapi_done(chp, xfer);		return (1);	}	if (xfer->c_flags & C_DMA) {		dma_flags = ((sc_xfer->flags & SCSI_DATA_IN) ||		    (xfer->c_flags & C_SENSE)) ?  WDC_DMA_READ : 0;		dma_flags |= ((sc_xfer->flags & SCSI_POLL) ||		   (drvp->atapi_cap & ACAP_DSC)) ? WDC_DMA_POLL : 0;	}again:	len = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo) +	    256 * bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_hi);	ire = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_ireason);	phase = (ire & (WDCI_CMD | WDCI_IN)) | (chp->ch_status & WDCS_DRQ);	WDCDEBUG_PRINT(("wdc_atapi_intr: c_bcount %d len %d st 0x%x err 0x%x "	    "ire 0x%x :", xfer->c_bcount,	    len, chp->ch_status, chp->ch_error, ire), DEBUG_INTR);	switch (phase) {	case PHASE_CMDOUT:		if (xfer->c_flags & C_SENSE) {			bzero(cmd_reqsense, sizeof(struct scsi_generic));			cmd_reqsense->opcode = REQUEST_SENSE;			cmd_reqsense->length = xfer->c_bcount;			bcopy(cmd_reqsense, cmd, sizeof(struct scsi_generic));		} else {			bcopy(sc_xfer->cmd, cmd, sc_xfer->cmdlen);		}		WDCDEBUG_PRINT(("PHASE_CMDOUT\n"), DEBUG_INTR);		/* Init the DMA channel if necessary */		if (xfer->c_flags & C_DMA) {			if ((*chp->wdc->dma_init)(chp->wdc->dma_arg,			    chp->channel, xfer->drive,			    xfer->databuf, xfer->c_bcount, dma_flags) != 0) {				sc_xfer->error = XS_DRIVER_STUFFUP;				break;			}		}		/* send packet command */		/* Commands are 12 or 16 bytes long. It's 32-bit aligned */		if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM)) {			if (drvp->drive_flags & DRIVE_CAP32) {				bus_space_write_multi_4(chp->data32iot,				    chp->data32ioh, 0,				    (u_int32_t *)cmd,				    cmdlen >> 2);			} else {				bus_space_write_multi_2(chp->cmd_iot,				    chp->cmd_ioh, wd_data,				    (u_int16_t *)cmd,				    cmdlen >> 1);			}		} else {			if (drvp->drive_flags & DRIVE_CAP32) {				bus_space_write_multi_stream_4(chp->data32iot,				    chp->data32ioh, 0,				    (u_int32_t *)cmd,				    cmdlen >> 2);			} else {				bus_space_write_multi_stream_2(chp->cmd_iot,				    chp->cmd_ioh, wd_data,				    (u_int16_t *)cmd,				    cmdlen >> 1);			}		}		/* Start the DMA channel if necessary */		if (xfer->c_flags & C_DMA) {			(*chp->wdc->dma_start)(chp->wdc->dma_arg,			    chp->channel, xfer->drive, dma_flags);		}		if ((sc_xfer->flags & SCSI_POLL) == 0 &&		    (drvp->atapi_cap & ACAP_DSC) == 0) {			chp->ch_flags |= WDCF_IRQ_WAIT;			timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);		}		/* If we read/write to a tape we will get into buffer		   availability mode.  */		if (drvp->atapi_cap & ACAP_DSC) {			if (!(drvp->drive_flags & DRIVE_DSCBA) &&			    (sc_xfer->cmd->opcode == READ ||			    sc_xfer->cmd->opcode == WRITE)) {				drvp->drive_flags |= DRIVE_DSCBA;				WDCDEBUG_PRINT(("set DSCBA\n"), DEBUG_DSC);			}			if (sc_xfer->cmd->opcode == READ)				drvp->drive_flags |= DRIVE_DSCWAIT;		} 		return (1);	 case PHASE_DATAOUT:		/* write data */		WDCDEBUG_PRINT(("PHASE_DATAOUT\n"), DEBUG_INTR);		if ((sc_xfer->flags & SCSI_DATA_OUT) == 0 ||		    (xfer->c_flags & C_DMA) != 0) {			printf("wdc_atapi_intr: bad data phase DATAOUT\n");			if (xfer->c_flags & C_DMA) {				(*chp->wdc->dma_finish)(chp->wdc->dma_arg,				    chp->channel, xfer->drive, dma_flags);				drvp->n_dmaerrs++;			}			sc_xfer->error = XS_TIMEOUT;			wdc_atapi_reset(chp, xfer);			return (1);		}		if (xfer->c_bcount < len) {			printf("wdc_atapi_intr: warning: write only "			    "%d of %d requested bytes\n", xfer->c_bcount, len);			if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM)) {				bus_space_write_multi_2(chp->cmd_iot,				    chp->cmd_ioh, wd_data,				    (u_int16_t *)				    ((char *)xfer->databuf + xfer->c_skip),				    xfer->c_bcount >> 1);			} else {				bus_space_write_multi_stream_2(chp->cmd_iot,				    chp->cmd_ioh, wd_data,				    (u_int16_t *)				    ((char *)xfer->databuf + xfer->c_skip),				    xfer->c_bcount >> 1);			}			for (i = xfer->c_bcount; i < len; i += 2)				bus_space_write_2(chp->cmd_iot, chp->cmd_ioh,				    wd_data, 0);			xfer->c_skip += xfer->c_bcount;			xfer->c_bcount = 0;		} else {			if (drvp->drive_flags & DRIVE_CAP32) {				if ((chp->wdc->cap &				    WDC_CAPABILITY_ATAPI_NOSTREAM))					bus_space_write_multi_4(chp->data32iot,					    chp->data32ioh, 0,					    (u_int32_t *)					    ((char *)xfer->databuf +					    xfer->c_skip),					    len >> 2);				else					bus_space_write_multi_stream_4(					    chp->data32iot, chp->data32ioh,					    wd_data,					    (u_int32_t *)					    ((char *)xfer->databuf +					    xfer->c_skip),					    len >> 2);				xfer->c_skip += len & 0xfffffffc;				xfer->c_bcount -= len & 0xfffffffc;				len = len & 0x03;			}			if (len > 0) {				if ((chp->wdc->cap &				    WDC_CAPABILITY_ATAPI_NOSTREAM))					bus_space_write_multi_2(chp->cmd_iot,					    chp->cmd_ioh, wd_data,					    (u_int16_t *)					    ((char *)xfer->databuf +					    xfer->c_skip),					    len >> 1);				else					bus_space_write_multi_stream_2(					    chp->cmd_iot, chp->cmd_ioh,					    wd_data,					    (u_int16_t *)					    ((char *)xfer->databuf +					    xfer->c_skip),					    len >> 1);				xfer->c_skip += len;				xfer->c_bcount -= len;			}		}		if ((sc_xfer->flags & SCSI_POLL) == 0 &&		    (drvp->atapi_cap & ACAP_DSC) == 0) {			chp->ch_flags |= WDCF_IRQ_WAIT;			timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);		} else if (drvp->atapi_cap & ACAP_DSC)			drvp->drive_flags |= DRIVE_DSCWAIT;		return (1);	case PHASE_DATAIN:		/* Read data */		WDCDEBUG_PRINT(("PHASE_DATAIN\n"), DEBUG_INTR);		if (((sc_xfer->flags & SCSI_DATA_IN) == 0 &&		    (xfer->c_flags & C_SENSE) == 0) || 		    (xfer->c_flags & C_DMA) != 0) {			printf("wdc_atapi_intr: bad data phase DATAIN\n");			if (xfer->c_flags & C_DMA) {				(*chp->wdc->dma_finish)(chp->wdc->dma_arg,				    chp->channel, xfer->drive, dma_flags);				drvp->n_dmaerrs++;			}			sc_xfer->error = XS_TIMEOUT;			wdc_atapi_reset(chp, xfer);			return (1);		}		if (xfer->c_bcount < len) {			printf("wdc_atapi_intr: warning: reading only "			    "%d of %d bytes\n", xfer->c_bcount, len);			if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM)) {				bus_space_read_multi_2(chp->cmd_iot,				    chp->cmd_ioh, wd_data,				    (u_int16_t *)				    ((char *)xfer->databuf + xfer->c_skip),				    xfer->c_bcount >> 1);			} else {				bus_space_read_multi_stream_2(chp->cmd_iot,				    chp->cmd_ioh, wd_data,				    (u_int16_t *)				    ((char *)xfer->databuf + xfer->c_skip),				    xfer->c_bcount >> 1);			}			wdcbit_bucket(chp, len - xfer->c_bcount);			xfer->c_skip += xfer->c_bcount;			xfer->c_bcount = 0;		} else {			if (drvp->drive_flags & DRIVE_CAP32) {				if ((chp->wdc->cap &				    WDC_CAPABILITY_ATAPI_NOSTREAM))					bus_space_read_multi_4(chp->data32iot,					    chp->data32ioh, 0,					    (u_int32_t *)					    ((char *)xfer->databuf +					    xfer->c_skip),					    len >> 2);				else					bus_space_read_multi_stream_4(					    chp->data32iot, chp->data32ioh,					    wd_data,					    (u_int32_t *)					    ((char *)xfer->databuf +					    xfer->c_skip),					    len >> 2);								xfer->c_skip += len & 0xfffffffc;				xfer->c_bcount -= len & 0xfffffffc;				len = len & 0x03;			}			if (len > 0) {				if ((chp->wdc->cap &				    WDC_CAPABILITY_ATAPI_NOSTREAM))					bus_space_read_multi_2(chp->cmd_iot,					    chp->cmd_ioh, wd_data,					    (u_int16_t *)					    ((char *)xfer->databuf +				            xfer->c_skip), 					    len >> 1);				else					bus_space_read_multi_stream_2(					    chp->cmd_iot, chp->cmd_ioh,					    wd_data,					    (u_int16_t *)					    ((char *)xfer->databuf +					    xfer->c_skip), 					    len >> 1);				xfer->c_skip += len;				xfer->c_bcount -=len;			}		}		if ((sc_xfer->flags & SCSI_POLL) == 0 &&		    (drvp->atapi_cap & ACAP_DSC) == 0) {			chp->ch_flags |= WDCF_IRQ_WAIT;			timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);		}		return (1);	case PHASE_ABORTED:	case PHASE_COMPLETED:		WDCDEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR);		/* turn off DMA channel */		if (xfer->c_flags & C_DMA) {			dma_err = (*chp->wdc->dma_finish)(chp->wdc->dma_arg,			    chp->channel, xfer->drive, dma_flags);			if (xfer->c_flags & C_SENSE)				xfer->c_bcount -=				    sizeof(sc_xfer->sense);			else				xfer->c_bcount -= sc_xfer->datalen;		}		if (xfer->c_flags & C_SENSE) {			if ((chp->ch_status & WDCS_ERR) || dma_err < 0) {				/*				 * request sense failed ! it's not suppossed				 * to be possible				 */				if (dma_err < 0)					drvp->n_dmaerrs++;				sc_xfer->error = XS_RESET;				wdc_atapi_reset(chp, xfer);				return (1);			} else if (xfer->c_bcount <			    sizeof(sc_xfer->sense)) {				/* use the sense we just read */				sc_xfer->error = XS_SENSE;			} else {				/*				 * command completed, but no data was read.				 * use the short sense we saved previsouly.				 */				sc_xfer->error = XS_SHORTSENSE;			}		} else {			sc_xfer->resid = xfer->c_bcount;			if (chp->ch_status & WDCS_ERR) {				/* save the short sense */				sc_xfer->error = XS_SHORTSENSE;				atapi_to_scsi_sense(sc_xfer, chp->ch_error);				if ((sc_xfer->sc_link->quirks &				    ADEV_NOSENSE) == 0) {					/*					 * let the driver issue a					 * 'request sense'					 */					xfer->databuf = &sc_xfer->sense;					xfer->c_bcount =					    sizeof(sc_xfer->sense);					xfer->c_skip = 0;					xfer->c_flags |= C_SENSE;					wdc_atapi_start(chp, xfer);					return (1);				}			} else if (dma_err < 0) {				drvp->n_dmaerrs++;				sc_xfer->error = XS_RESET;				wdc_atapi_reset(chp, xfer);				return (1);			}		}		if (xfer->c_bcount != 0) {			WDCDEBUG_PRINT(("wdc_atapi_intr: bcount value is "			    "%d after io\n", xfer->c_bcount), DEBUG_XFERS);		}#ifdef DIAGNOSTIC		if (xfer->c_bcount < 0) {			printf("wdc_atapi_intr warning: bcount value "			    "is %d after io\n", xfer->c_bcount);		}#endif		break;	default:		if (++retries<500) {			DELAY(100);			chp->ch_status = bus_space_read_1(chp->cmd_iot,			    chp->cmd_ioh, wd_status);			chp->ch_error = bus_space_read_1(chp->cmd_iot,			    chp->cmd_ioh, wd_error);			goto again;		}		printf("wdc_atapi_intr: unknown phase 0x%x\n", phase);		if (chp->ch_status & WDCS_ERR) {			sc_xfer->error = XS_SHORTSENSE;			atapi_to_scsi_sense(sc_xfer, chp->ch_error);		} else {			sc_xfer->error = XS_RESET;			wdc_atapi_reset(chp, xfer);			return (1);		}	}	WDCDEBUG_PRINT(("wdc_atapi_intr: wdc_atapi_done() (end), error 0x%x "	    "\n", sc_xfer->error),	    DEBUG_INTR);	wdc_atapi_done(chp, xfer);	return (1);}