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

📄 sd.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
	int s;	SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy "));	SC_DEBUG(sd->sc_link, SDEV_DB1,	    ("%ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));	/*	 * The transfer must be a whole number of blocks.	 */	if ((bp->b_bcount % sd->sd_secsize) != 0) {		bp->b_error = EINVAL;		goto bad;	}	/*	 * If the device has been made invalid, error out	 */	if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {		bp->b_error = EIO;		goto bad;	}	/*	 * If it's a null transfer, return immediatly	 */	if (bp->b_bcount == 0)		goto done;	s = splbio();	/*	 * Place it in the queue of disk activities for this disk	 */	disksort(&sd->buf_queue, bp);	/*	 * Tell the device to get going on the transfer if it's	 * not doing anything, otherwise just wait for completion	 */	sdstart(sd);	splx(s);	return;bad:	bp->b_flags |= B_ERROR;done:	/*	 * Correctly set the buf to indicate a completed xfer	 */	bp->b_resid = bp->b_bcount;	biodone(bp);}/* * sdstart looks to see if there is a buf waiting for the device * and that the device is not already busy. If both are true, * It dequeues the buf and creates a scsi command to perform the * transfer in the buf. The transfer request will call scsi_done * on completion, which will in turn call this routine again * so that the next queued transfer is performed. * The bufs are queued by the strategy routine (sdstrategy) * * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. * * must be called at the correct (highish) spl level * sdstart() is called at splbio from sdstrategy and scsi_done */void sdstart(v)	register void *v;{	register struct sd_softc *sd = v;	register struct	scsi_link *sc_link = sd->sc_link;	struct buf *bp = 0;	struct buf *dp;	struct scsi_rw_big cmd_big;	struct scsi_rw cmd_small;	struct scsi_generic *cmdp;	int blkno, nblks, cmdlen, error;	SC_DEBUG(sc_link, SDEV_DB2, ("sdstart "));	/*	 * Check if the device has room for another command	 */	while (sc_link->openings > 0) {		/*		 * there is excess capacity, but a special waits		 * It'll need the adapter as soon as we clear out of the		 * way and let it run (user level wait).		 */		if (sc_link->flags & SDEV_WAITING) {			sc_link->flags &= ~SDEV_WAITING;			wakeup((caddr_t)sc_link);			return;		}		/*		 * See if there is a buf with work for us to do..		 */		dp = &sd->buf_queue;		if ((bp = dp->b_actf) == NULL)	/* yes, an assign */			return;		dp->b_actf = bp->b_actf;		/*		 * If the device has become invalid, abort all the		 * reads and writes until all files have been closed and		 * re-opened		 */		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {			bp->b_error = EIO;			bp->b_flags |= B_ERROR;			bp->b_resid = bp->b_bcount;			biodone(bp);			continue;		}		/*		 * We have a buf, now we should make a command		 *		 * First, translate the block to absolute and put it in terms		 * of the logical blocksize of the device.		 */		blkno = bp->b_blkno / (sd->sd_secsize / DEV_BSIZE);		nblks = howmany(bp->b_bcount, sd->sd_secsize);		/*		 *  Fill out the scsi command.  If the transfer will		 *  fit in a "small" cdb, use it.		 */		if (((blkno & 0x1fffff) == blkno) &&		    ((nblks & 0xff) == nblks)) {			/*			 * We can fit in a small cdb.			 */			bzero(&cmd_small, sizeof(cmd_small));			cmd_small.opcode = (bp->b_flags & B_READ) ?			    READ_COMMAND : WRITE_COMMAND;			_lto3b(blkno, cmd_small.addr);			cmd_small.length = nblks & 0xff;			cmdlen = sizeof(cmd_small);			cmdp = (struct scsi_generic *)&cmd_small;		} else {			/*			 * Need a large cdb.			 */			bzero(&cmd_big, sizeof(cmd_big));			cmd_big.opcode = (bp->b_flags & B_READ) ?			    READ_BIG : WRITE_BIG;			_lto4b(blkno, cmd_big.addr);			_lto2b(nblks, cmd_big.length);			cmdlen = sizeof(cmd_big);			cmdp = (struct scsi_generic *)&cmd_big;		}		/*		 * Call the routine that chats with the adapter.		 * Note: we cannot sleep as we may be an interrupt		 */		error = scsi_scsi_cmd(sc_link, cmdp, cmdlen,		    (u_char *)bp->b_data, bp->b_bcount,		    SDRETRIES, 60000, bp, SCSI_NOSLEEP |		    ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT));		if (error) {			printf("%s: not queued, error %d\n",			    sd->sc_dev.dv_xname, error);		}	}}voidsddone(xs)	struct scsi_xfer *xs;{}intsdread(dev, uio, ioflag)	dev_t dev;	struct uio *uio;	int ioflag;{	return (physio(sdstrategy, NULL, dev, B_READ, NULL, uio));}intsdwrite(dev, uio, ioflag)	dev_t dev;	struct uio *uio;	int ioflag;{	return (physio(sdstrategy, NULL, dev, B_WRITE, NULL, uio));}static intsd_mode_sense(sd, scsi_sense, page, flags)	struct sd_softc *sd;	struct scsi_mode_sense_data *scsi_sense;	int page, flags;{	struct scsi_mode_sense scsi_cmd;	/*	 * Make sure the sense buffer is clean before we do	 * the mode sense, so that checks for bogus values of	 * 0 will work in case the mode sense fails.	 */	bzero(scsi_sense, sizeof(*scsi_sense));	bzero(&scsi_cmd, sizeof(scsi_cmd));	scsi_cmd.opcode = MODE_SENSE;	scsi_cmd.page = page;	scsi_cmd.length = 0x20;	/*	 * If the command worked, use the results to fill out	 * the parameter structure	 */	return scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd,	    sizeof(scsi_cmd), (u_char *)scsi_sense, sizeof(*scsi_sense),	    SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN | SCSI_SILENT);}intsd_get_optparms(sd, flags, dp)	struct sd_softc *sd;	int flags;	struct disk_parms *dp;{	struct scsi_mode_sense scsi_cmd;	struct scsi_mode_sense_data {		struct scsi_mode_header header;		struct scsi_blk_desc blk_desc;		union disk_pages pages;	} scsi_sense;	u_long sectors;	int error;	dp->blksize = DEV_BSIZE;	if ((sectors = scsi_size(sd->sc_link, flags)) == 0)		return 1;	/* XXX	 * It is better to get the following params from the	 * mode sense page 6 only (optical device parameter page).	 * However, there are stupid optical devices which does NOT	 * support the page 6. Ghaa....	 */	bzero(&scsi_cmd, sizeof(scsi_cmd));	scsi_cmd.opcode = MODE_SENSE;	scsi_cmd.page = 0x3f;	/* all pages */	scsi_cmd.length = sizeof(struct scsi_mode_header) +	    sizeof(struct scsi_blk_desc);	if ((error = scsi_scsi_cmd(sd->sc_link,  	    (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd),  	    (u_char *)&scsi_sense, sizeof(scsi_sense), SDRETRIES,	    6000, NULL, flags | SCSI_DATA_IN)) != 0)		return error;	dp->blksize = _3btol(scsi_sense.blk_desc.blklen);	if (dp->blksize == 0) 		dp->blksize = DEV_BSIZE;	/*	 * Create a pseudo-geometry.	 */	dp->heads = 64;	dp->sectors = 32;	dp->cyls = sectors / (dp->heads * dp->sectors);	dp->disksize = sectors;	return 0;}/* * Get the scsi driver to send a full inquiry to the * device and use the * results to fill out the disk parameter structure. */intsd_get_parms(sd, flags)	struct sd_softc *sd;	int flags;{	struct disk_parms *dp = &sd->params;	struct scsi_mode_sense_data scsi_sense;	u_long sectors;	int page;	int error;	if (sd->type == T_OPTICAL) {		if ((error = sd_get_optparms(sd, flags, dp)) != 0)			sd->sc_link->flags &= ~SDEV_MEDIA_LOADED;		return error;	}	if ((error = sd_mode_sense(sd, &scsi_sense, page = 4, flags)) == 0) {		SC_DEBUG(sd->sc_link, SDEV_DB3,		    ("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",		    _3btol(scsi_sense.pages.rigid_geometry.ncyl),		    scsi_sense.pages.rigid_geometry.nheads,		    _2btol(scsi_sense.pages.rigid_geometry.st_cyl_wp),		    _2btol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),		    _2btol(scsi_sense.pages.rigid_geometry.land_zone)));		/*		 * KLUDGE!! (for zone recorded disks)		 * give a number of sectors so that sec * trks * cyls		 * is <= disk_size		 * can lead to wasted space! THINK ABOUT THIS !		 */		dp->heads = scsi_sense.pages.rigid_geometry.nheads;		dp->cyls = _3btol(scsi_sense.pages.rigid_geometry.ncyl);		dp->blksize = _3btol(scsi_sense.blk_desc.blklen);		if (dp->heads == 0 || dp->cyls == 0)			goto fake_it;		if (dp->blksize == 0)			dp->blksize = DEV_BSIZE;		sectors = scsi_size(sd->sc_link, flags);		dp->disksize = sectors;		sectors /= (dp->heads * dp->cyls);		dp->sectors = sectors;	/* XXX dubious on SCSI */		return 0;	}	if ((error = sd_mode_sense(sd, &scsi_sense, page = 5, flags)) == 0) {		dp->heads = scsi_sense.pages.flex_geometry.nheads;		dp->cyls = _2btol(scsi_sense.pages.flex_geometry.ncyl);		dp->blksize = _3btol(scsi_sense.blk_desc.blklen);		dp->sectors = scsi_sense.pages.flex_geometry.ph_sec_tr;		dp->disksize = dp->heads * dp->cyls * dp->sectors;		if (dp->disksize == 0)			goto fake_it;		if (dp->blksize == 0)			dp->blksize = DEV_BSIZE;		return 0;	}fake_it:	if ((sd->sc_link->quirks & SDEV_NOMODESENSE) == 0) {		if (error == 0)			printf("%s: mode sense (%d) returned nonsense",			    sd->sc_dev.dv_xname, page);		else			printf("%s: could not mode sense (4/5)",			    sd->sc_dev.dv_xname);		printf("; using fictitious geometry\n");	}	/*	 * use adaptec standard fictitious geometry	 * this depends on which controller (e.g. 1542C is	 * different. but we have to put SOMETHING here..)	 */	sectors = scsi_size(sd->sc_link, flags);	dp->heads = 64;	dp->sectors = 32;	dp->cyls = sectors / (64 * 32);	dp->blksize = DEV_BSIZE;	dp->disksize = sectors;	return 0;}/* * Copy up to len chars from src to dst, ignoring non-printables. * Must be room for len+1 chars in dst so we can write the NUL. * Does not assume src is NUL-terminated. */voidviscpy(dst, src, len)	u_char *dst;	u_char *src;	int len;{	while (len > 0 && *src != '\0') {		if (*src < 0x20 || *src >= 0x80) {			src++;			continue;		}		*dst++ = *src++;		len--;	}	*dst = '\0';}

⌨️ 快捷键说明

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