⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ata_wdc.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
		printf("%s:%d:%d: bad state %d in wdc_ata_bio_intr\n",		    chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,		    drvp->state);		panic("wdc_ata_bio_intr: bad state\n");	}#ifndef PMON	if (xfer->c_flags & C_DMA) {		dma_flags = (ata_bio->flags & ATA_READ) ?  WDC_DMA_READ : 0;		dma_flags |= (ata_bio->flags & ATA_POLL) ?  WDC_DMA_POLL : 0;	}#endif	/*	 * if we missed an interrupt in a PIO transfer, reset and restart.	 * Don't try to continue transfer, we may have missed cycles.	 */	if ((xfer->c_flags & (C_TIMEOU | C_DMA)) == C_TIMEOU) {		ata_bio->error = TIMEOUT;		wdc_ata_bio_done(chp, xfer);		return 1;	}	/* Ack interrupt done by wait_for_unbusy */	if (wait_for_unbusy(chp,	    (irq == 0) ? ATA_DELAY : 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);#ifndef PMON		/* if we were using DMA, turn off DMA channel */		if (xfer->c_flags & C_DMA) {			(*chp->wdc->dma_finish)(chp->wdc->dma_arg,			    chp->channel, xfer->drive, dma_flags);			drvp->n_dmaerrs++;		}#endif		ata_bio->error = TIMEOUT;		wdc_ata_bio_done(chp, xfer);		return 1;	}		drv_err = wdc_ata_err(drvp, ata_bio);#ifndef PMON	/* If we were using DMA, Turn off the DMA channel and check for error */	if (xfer->c_flags & C_DMA) {		if (ata_bio->flags & ATA_POLL) {			/*			 * IDE drives deassert WDCS_BSY before transfer is			 * complete when using DMA. Polling for DRQ to deassert			 * is not enouth DRQ is not required to be			 * asserted for DMA transfers, so poll for DRDY.			 */			if (wdcwait(chp, WDCS_DRDY | WDCS_DRQ, WDCS_DRDY,			    ATA_DELAY) < 0) {				printf("%s:%d:%d: polled transfer timed out "				    "(st=0x%x)\n", chp->wdc->sc_dev.dv_xname,				    chp->channel, xfer->drive, chp->ch_status);				ata_bio->error = TIMEOUT;				drv_err = WDC_ATA_ERR;			}		}		if ((*chp->wdc->dma_finish)(chp->wdc->dma_arg,		    chp->channel, xfer->drive, dma_flags) != 0) {			if (drv_err != WDC_ATA_ERR) {				ata_bio->error = ERR_DMA;				drv_err = WDC_ATA_ERR;			}		}		if (chp->ch_status & WDCS_DRQ) {			if (drv_err != WDC_ATA_ERR) {				printf("%s:%d:%d: intr with DRQ (st=0x%x)\n",				    chp->wdc->sc_dev.dv_xname, chp->channel,				    xfer->drive, chp->ch_status);				ata_bio->error = TIMEOUT;				drv_err = WDC_ATA_ERR;			}		}		if (drv_err != WDC_ATA_ERR)			goto end;		drvp->n_dmaerrs++;	}#endif	/* if we had an error, end */	if (drv_err == WDC_ATA_ERR) {		wdc_ata_bio_done(chp, xfer);		return 1;	}	/* If this was a read and not using DMA, fetch the data. */	if ((ata_bio->flags & ATA_READ) != 0) {		if ((chp->ch_status & WDCS_DRQ) != WDCS_DRQ) {			printf("%s:%d:%d: read intr before drq\n",			    chp->wdc->sc_dev.dv_xname, chp->channel,			    xfer->drive);			ata_bio->error = TIMEOUT;			wdc_ata_bio_done(chp, xfer);			return 1;		}		wdc_input_bytes(drvp, (char *)xfer->databuf + xfer->c_skip,		    ata_bio->nbytes);	}#ifndef PMONend:#endif	ata_bio->blkno += ata_bio->nblks;	ata_bio->blkdone += ata_bio->nblks;	xfer->c_skip += ata_bio->nbytes;	xfer->c_bcount -= ata_bio->nbytes;	/* See if this transfer is complete. */	if (xfer->c_bcount > 0) {		if ((ata_bio->flags & ATA_POLL) == 0) {			/* Start the next operation */			_wdc_ata_bio_start(chp, xfer);		} else {			/* Let _wdc_ata_bio_start do the loop */			return 1;		}	} else { /* Done with this transfer */		ata_bio->error = NOERROR;		wdc_ata_bio_done(chp, xfer);	}	return 1;}voidwdc_ata_bio_kill_xfer(chp, xfer)	struct channel_softc *chp;	struct wdc_xfer *xfer;{	struct ata_bio *ata_bio = xfer->cmd;#ifndef PMON	untimeout(wdctimeout, chp);#endif	/* remove this command from xfer queue */	wdc_free_xfer(chp, xfer);	ata_bio->flags |= ATA_ITSDONE;	ata_bio->error = ERR_NODEV;	ata_bio->r_error = WDCE_ABRT;	if ((ata_bio->flags & ATA_POLL) == 0) {		WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);		wddone(ata_bio->wd);	}}voidwdc_ata_bio_done(chp, xfer)	struct channel_softc *chp;	struct wdc_xfer *xfer;{	struct ata_bio *ata_bio = xfer->cmd;	int drive = xfer->drive;	struct ata_drive_datas *drvp = &chp->ch_drive[drive];	WDCDEBUG_PRINT(("wdc_ata_bio_done %s:%d:%d: flags 0x%x\n",	    chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, 	    (u_int)xfer->c_flags),	    DEBUG_XFERS);#ifndef PMON	untimeout(wdctimeout, chp);#endif	if (ata_bio->error == NOERROR)		drvp->n_dmaerrs = 0;	else if (drvp->n_dmaerrs >= NERRS_MAX) {		wdc_downgrade_mode(drvp);	}	/* feed back residual bcount to our caller */	ata_bio->bcount = xfer->c_bcount;	/* remove this command from xfer queue */	wdc_free_xfer(chp, xfer);	ata_bio->flags |= ATA_ITSDONE;	if ((ata_bio->flags & ATA_POLL) == 0) {		WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);		wddone(ata_bio->wd);	}	WDCDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",	    chp->ch_flags), DEBUG_XFERS);	wdcstart(chp);}/* * Implement operations needed before read/write. */intwdc_ata_ctrl_intr(chp, xfer, irq)	struct channel_softc *chp;	struct wdc_xfer *xfer;	int irq;{	struct ata_bio *ata_bio = xfer->cmd;	struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];	char *errstring = NULL;	int delay = (irq == 0) ? ATA_DELAY : 0;	WDCDEBUG_PRINT(("wdc_ata_ctrl_intr: state %d\n", drvp->state),	    DEBUG_FUNCS);again:	switch (drvp->state) {	case RECAL:    /* Should not be in this state here */		panic("wdc_ata_ctrl_intr: state==RECAL");		break;	case RECAL_WAIT:		errstring = "recal";		if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))			goto timeout;		if (chp->ch_status & (WDCS_ERR | WDCS_DWF))			goto error;	/* fall through */	case PIOMODE:		/* Don't try to set modes if controller can't be adjusted */		if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)			goto geometry;		/* Also don't try if the drive didn't report its mode */		if ((drvp->drive_flags & DRIVE_MODE) == 0)			goto geometry;		wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,		    0x08 | drvp->PIO_mode, WDSF_SET_MODE);		drvp->state = PIOMODE_WAIT;		break;	case PIOMODE_WAIT:		errstring = "piomode";		if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))			goto timeout;		if (chp->ch_status & (WDCS_ERR | WDCS_DWF))			goto error;	/* 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 geometry;		}			drvp->state = DMAMODE_WAIT;		break;	case DMAMODE_WAIT:		errstring = "dmamode";		if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))			goto timeout;		if (chp->ch_status & (WDCS_ERR | WDCS_DWF))			goto error;	/* fall through */	case GEOMETRY:	geometry:		if (ata_bio->flags & ATA_LBA)			goto multimode;		wdccommand(chp, xfer->drive, WDCC_IDP,		    ata_bio->lp->d_ncylinders,		    ata_bio->lp->d_ntracks - 1, 0, ata_bio->lp->d_nsectors,		    (ata_bio->lp->d_type == DTYPE_ST506) ?			ata_bio->lp->d_precompcyl / 4 : 0);		drvp->state = GEOMETRY_WAIT;		break;	case GEOMETRY_WAIT:		errstring = "geometry";		if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))			goto timeout;		if (chp->ch_status & (WDCS_ERR | WDCS_DWF))			goto error;		/* fall through */	case MULTIMODE:	multimode:		if (ata_bio->multi == 1)			goto ready;		wdccommand(chp, xfer->drive, WDCC_SETMULTI, 0, 0, 0,		    ata_bio->multi, 0);		drvp->state = MULTIMODE_WAIT;		break;	case MULTIMODE_WAIT:		errstring = "setmulti";		if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))			goto timeout;		if (chp->ch_status & (WDCS_ERR | WDCS_DWF))			goto error;		/* fall through */	case READY:	ready:		drvp->state = READY;		/*		 * The drive is usable now		 */		xfer->c_intr = wdc_ata_bio_intr;		_wdc_ata_bio_start(chp, xfer); 		return 1;	}	if ((ata_bio->flags & ATA_POLL) == 0) {		chp->ch_flags |= WDCF_IRQ_WAIT;	} else {		goto again;	}	return 1;timeout:	if (irq && (xfer->c_flags & C_TIMEOU) == 0) {		return 0; /* IRQ was not for us */	}	printf("%s:%d:%d: %s timed out\n",	    chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);	ata_bio->error = TIMEOUT;	drvp->state = 0;	wdc_ata_bio_done(chp, xfer);	return 0;error:	printf("%s:%d:%d: %s ",	    chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,	    errstring);	if (chp->ch_status & WDCS_DWF) {		printf("drive fault\n");		ata_bio->error = ERR_DF;	} else {		printf("error (%x)\n", chp->ch_error);		ata_bio->r_error = chp->ch_error;		ata_bio->error = ERROR;	}	drvp->state = 0;	wdc_ata_bio_done(chp, xfer);	return 1;}intwdc_ata_err(drvp, ata_bio)	struct ata_drive_datas *drvp;	struct ata_bio *ata_bio;{	struct channel_softc *chp = drvp->chnl_softc;	ata_bio->error = 0;	if (chp->ch_status & WDCS_BSY) {		ata_bio->error = TIMEOUT;		return WDC_ATA_ERR;	}	if (chp->ch_status & WDCS_DWF) {		ata_bio->error = ERR_DF;		return WDC_ATA_ERR;	}	if (chp->ch_status & WDCS_ERR) {		ata_bio->error = ERROR;		ata_bio->r_error = chp->ch_error;		if (drvp->drive_flags & DRIVE_UDMA &&		    (ata_bio->r_error & WDCE_CRC)) {			/*			 * Record the CRC error, to avoid downgrading to			 * multiword DMA			 */			drvp->drive_flags |= DRIVE_DMAERR;		}		if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |		    WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))			return WDC_ATA_ERR;		return WDC_ATA_NOERR;	}	if (chp->ch_status & WDCS_CORR)		ata_bio->flags |= ATA_CORR;	return WDC_ATA_NOERR;}#if 0intwdc_ata_addref(drvp)	struct ata_drive_datas *drvp;{	struct channel_softc *chp = drvp->chnl_softc;	return (wdc_addref(chp));}voidwdc_ata_delref(drvp)	struct ata_drive_datas *drvp;{	struct channel_softc *chp = drvp->chnl_softc;	wdc_delref(chp);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -