drvp->state = PIOMODE;
wdccommandshort(chp, drvp->drive, ATAPI_DEVICE_RESET); drvp->state = ATAPI_DEVICE_RESET_WAIT_STATE; ret->delay = 500; ret->timeout = ATAPI_RESET_WAIT; break;
wdc_atapi_ctrl(chp, xfer, timeout, ret)	struct channel_softc *chp;	struct wdc_xfer *xfer;	int timeout;	struct atapi_return_args *ret;{	struct scsi_xfer *sc_xfer = xfer->cmd;	struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];	char *errstring = NULL;	switch (drvp->state) {	case IDENTIFY:	case IDENTIFY_WAIT:		errstring = "IDENTIFY";		break;			case PIOMODE:		errstring = "Post IDENTIFY";		break;	case PIOMODE_WAIT:		errstring = "PIOMODE";		break;	case DMAMODE_WAIT:		errstring = "dmamode";		break;	default:		errstring = "unknown state";		break;	}	if (timeout) {		if (drvp->state != IDENTIFY)			goto timeout;		else {#ifdef DIAGNOSTIC			printf ("wdc_atapi_ctrl: timeout before IDENTIFY."			    "Should not happen\n");#endif			sc_xfer->error = XS_DRIVER_STUFFUP;			xfer->next = wdc_atapi_done;			return;		}	}	wdc_atapi_update_status(chp);	if (chp->ch_status & WDCS_BSY)		return;	if (!wdc_atapi_drive_selected(chp, xfer->drive))	{		CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (xfer->drive << 4));		delay (1);		return;	}	ret->claim_irq = -1;	WDCDEBUG_PRINT(("wdc_atapi_ctrl %s:%d:%d state %d\n",	    chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive, drvp->state),	    DEBUG_INTR | DEBUG_FUNCS);	switch (drvp->state) {		/* You need to send an ATAPI drive an ATAPI-specific		   command to revive it after a hard reset. Identify		   is about the most innocuous thing you can do		   that's guaranteed to be there */	case IDENTIFY:		wdccommandshort(chp, drvp->drive, ATAPI_IDENTIFY_DEVICE);		drvp->state = IDENTIFY_WAIT;		ret->timeout = ATAPI_CTRL_WAIT;		ret->expect_irq = 1;		break;		case IDENTIFY_WAIT:		if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)			chp->wdc->irqack(chp);		/* We don't really care if this operation failed.		   It's just there to wake the drive from its stupor. */		if (!(chp->ch_status & WDCS_ERR)) {			wdcbit_bucket(chp, 512);				ret->timeout = 100;			drvp->state = PIOMODE;			break;		}		drvp->state = PIOMODE;	case PIOMODE:piomode:		/* Don't try to set mode if controller can't be adjusted */		if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)			goto ready;		/* Also don't try if the drive didn't report its mode */		if ((drvp->drive_flags & DRIVE_MODE) == 0)			goto ready;		wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,		    0x08 | drvp->PIO_mode, WDSF_SET_MODE);		drvp->state = PIOMODE_WAIT;		ret->timeout = ATAPI_CTRL_WAIT;		ret->expect_irq = 1;		break;	case PIOMODE_WAIT:		if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)			chp->wdc->irqack(chp);		if (chp->ch_status & WDCS_ERR) {			if (drvp->PIO_mode < 3) {				drvp->PIO_mode = 3;				goto piomode;			}			/* 			 * All ATAPI drives are supposed to support			 * PIO mode 3 or greater. 			 *			 * If the drive fails the set PIO mode command,			 * assume it just doesn't support the set PIO mode			 * command.			 *			 * Ideally, we would program the channel controller			 * to run at PIO mode 3. However, the channel			 * controller is only running faster than PIO mode 3			 * if the drive said it supported that. 			 */			drvp->PIO_mode = 3;		}	/* fall through */	case DMAMODE:		if (drvp->drive_flags & DRIVE_UDMA) {			wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,			    0x40 | drvp->UDMA_mode, WDSF_SET_MODE);		} else if (drvp->drive_flags & DRIVE_DMA) {			wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,			    0x20 | drvp->DMA_mode, WDSF_SET_MODE);		} else {			goto ready;		}		drvp->state = DMAMODE_WAIT;		ret->timeout = ATAPI_CTRL_WAIT;		ret->expect_irq = 1;		break;	case DMAMODE_WAIT:		if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)			chp->wdc->irqack(chp);		if (chp->ch_status & WDCS_ERR)			drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);	/* fall through */	case READY:	ready:		drvp->state = READY;		xfer->next = wdc_atapi_real_start;		break;	}	return;timeout:	printf("%s:%d:%d: %s timed out\n",	    chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);	sc_xfer->error = XS_TIMEOUT;	xfer->next = wdc_atapi_reset;	return;}