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

📄 sd.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		 * This is a totally bogus geometry- really need to do a mode		 * sense.		 */		label = 0;		bzero((caddr_t) &un->un_g, sizeof (struct dk_geom));		un->un_g.dkg_pcyl = un->un_capacity >> 5;		un->un_g.dkg_ncyl = un->un_g.dkg_pcyl - 2;		un->un_g.dkg_acyl = 2;		un->un_g.dkg_nhead = 1;		un->un_g.dkg_nsect = 32;		un->un_g.dkg_intrlv = 1;		un->un_g.dkg_rpm = 3000;		bzero((caddr_t)un->un_map, NDKMAP * (sizeof (struct dk_map)));		un->un_map['c'-'a'].dkl_cylno = 0;		un->un_map['c'-'a'].dkl_nblk = un->un_capacity;		inq_fill(devp->sd_inq->inq_vid, 8, labelstring);		printf("sd%d: <%s %d blocks>\n",		    unit, labelstring, un->un_capacity);	}	if (un->un_state == SD_STATE_NIL) {		New_state(un, SD_STATE_CLOSED);		/*		 * print out a message indicating who and what we are		 * if the geometry is valid, print the label string,		 * else print vendor and product info, if available		 */		if (un->un_gvalid && label) {			printf("sd%d: <%s>\n", unit, label);		} else {			inq_fill(devp->sd_inq->inq_vid, 8, labelstring);			inq_fill(devp->sd_inq->inq_pid, 16, &labelstring[64]);			printf("sd%d: Vendor '%s', product '%s'",			    unit, labelstring, &labelstring[64]);			if (un->un_capacity > 0) {				printf(", %d %d byte blocks\n",				    un->un_capacity, un->un_lbasize);			} else				printf(", (unknown capacity)\n");		}	}}/* * Check the label for righteousity, and snarf yummos from validated label. * Marks the geometyr of the unit as being valid. */static voidsd_uselabel(devp, l)struct scsi_device *devp;struct dk_label *l;{	static char *geom = "Label says %d blocks, Drive says %d blocks";	static char *badlab = "corrupt label - %s";	short *sp, sum, count;	struct scsi_disk *un = UPTR;	long capacity;	/*	 * Check magic number of the label	 */	if (l->dkl_magic != DKL_MAGIC) {		if (UPTR->un_state == SD_STATE_NIL)			sdlog(devp, LOG_ERR, badlab, "wrong magic number");		return;	}	/*	 * Check the checksum of the label	 */	sp = (short *)l;	sum = 0;	count = sizeof (struct dk_label) / sizeof (short);	while (count--)  {		sum ^= *sp++;	}	if (sum) {		if (un->un_state == SD_STATE_NIL)			sdlog(devp, LOG_ERR, badlab, "label checksum failed");		return;	}	/*	 * Fill in disk geometry from label.	 */	un->un_g.dkg_ncyl = l->dkl_ncyl;	un->un_g.dkg_acyl = l->dkl_acyl;	un->un_g.dkg_bcyl = 0;	un->un_g.dkg_nhead = l->dkl_nhead;	un->un_g.dkg_bhead = l->dkl_bhead;	un->un_g.dkg_nsect = l->dkl_nsect;	un->un_g.dkg_gap1 = l->dkl_gap1;	un->un_g.dkg_gap2 = l->dkl_gap2;	un->un_g.dkg_intrlv = l->dkl_intrlv;	un->un_g.dkg_pcyl = l->dkl_pcyl;	un->un_g.dkg_rpm = l->dkl_rpm;	/*	 * If labels don't have pcyl in them, make a guess at it.	 * The right thing, of course, to do, is to do a MODE SENSE	 * on the Rigid Disk Geometry mode page and check the	 * information with that. Won't work for non-CCS though.	 */	if (un->un_g.dkg_pcyl == 0)		un->un_g.dkg_pcyl = un->un_g.dkg_ncyl + un->un_g.dkg_acyl;	/*	 * Fill in partition table.	 */	bcopy((caddr_t) l->dkl_map, (caddr_t) un->un_map,	    NDKMAP * sizeof (struct dk_map));	/*	 * dk instrumentation	 */#ifdef	OPENPROMS	if ((u_char) un->un_dkn == (u_char) -1) {		int i = newdk("sd", DUNIT);		if (i >= 0) {			un->un_dkn = i;			i = un->un_g.dkg_intrlv;			if (i <= 0 || i >= un->un_g.dkg_nsect) {				i = 1;			}			dk_bps[un->un_dkn] =			    (SECSIZE * 60 * un->un_g.dkg_nsect) / i;		}	}#else	OPENPROMS	if ((u_char) un->un_dkn == (u_char) -1 &&	    devp->sd_dev->md_dk == 1 && dkn < DK_NDRIVE) {		int intrlv = un->un_g.dkg_intrlv;		if (intrlv <= 0 || intrlv >= un->un_g.dkg_nsect) {			intrlv = 1;		}		devp->sd_dev->md_dk = un->un_dkn = dkn++;		dk_bps[un->un_dkn] =			(SECSIZE * 60 * un->un_g.dkg_nsect) / intrlv;	} else {		devp->sd_dev->md_dk = -1;	}#endif	OPENPROMS	un->un_gvalid = 1;			/* "it's here..." */	capacity = un->un_g.dkg_ncyl * un->un_g.dkg_nhead * un->un_g.dkg_nsect;	if (un->un_g.dkg_acyl)		capacity +=  (un->un_g.dkg_nhead * un->un_g.dkg_nsect);	if (un->un_capacity > 0) {		if (capacity > un->un_capacity &&		    un->un_state == SD_STATE_NIL) {			sdlog(devp, LOG_ERR, badlab, "bad geometry");			sdlog(devp, LOG_ERR, geom, capacity, un->un_capacity);			un->un_gvalid = 0;	/* "No it's not!.." */		} else if (DEBUGGING_ALL) {			sdlog(devp, LOG_INFO, geom, capacity, un->un_capacity);		}	} else {		/*		 * We have a situation where the target didn't give us a		 * good 'read capacity' command answer, yet there appears		 * to be a valid label. In this case, we'll		 * fake the capacity.		 */		un->un_capacity = capacity;	}}/* * Unix Entry Points */intsdopen(dev, flag)dev_t dev;int flag;{	register struct scsi_device *devp;	register struct scsi_disk *un;	register int unit, s;	if ((unit = SDUNIT(dev)) >= SD_MAXUNIT) {		return (ENXIO);	}	if (!(devp = sdunits[unit])) {		struct scsi_address *sa = sdsvdaddr[unit];		if (sa) {			if (scsi_add_device(sa, &DRIVER, "sd", unit) == 0) {				return (ENXIO);			}			devp = sdunits[unit];			if (!devp) {				return (ENXIO);			}			(void) kmem_free((caddr_t) sa, sizeof (*sa));			sdsvdaddr[unit] = (struct scsi_address *) 0;		} else {			return (ENXIO);		}	} else if (!devp->sd_present) {		s = splr(sdpri);		if (sd_findslave(devp, 1) > 0) {			printf("sd%d at %s%d target %d lun %d\n", unit,			    CNAME, CUNIT, Tgt(devp), Lun(devp));			sd_doattach(devp, SLEEP_FUNC);		} else {			(void) splx(s);			return (ENXIO);		}		(void) splx(s);	}	un = UPTR;	if (un->un_gvalid == 0) {		s = splr(sdpri);		sd_doattach(devp, SLEEP_FUNC);		(void) splx(s);	}	/*	 * no, don't put an else here: sdattach may validate the geometry....	 */	if (un->un_gvalid == 0 || un->un_map[SDPART(dev)].dkl_nblk <= 0) {		/*		 * Are we opening this for format(8)?		 */		if ((flag & (FNDELAY|FNBIO)) == 0 || !SD_ISCDEV(dev)) {			return (ENXIO);		}	}	if (un->un_state == SD_STATE_DETACHING) {		if (sd_unit_ready(dev) == 0) {			return (ENXIO);		}		/*		 * disk now back on line...		 */		New_state(un, SD_STATE_OPENING);		sdlog(devp, LOG_INFO, diskokay);	} else if (un->un_state == SD_STATE_CLOSED) {		New_state(un, SD_STATE_OPENING);		if (sd_unit_ready(dev) == 0) {			sd_offline(devp, 1);			return (ENXIO);		}		/*		 * If this is a removable media device, try and send		 * a PREVENT MEDIA REMOVAL command, but don't get upset		 * if it fails.		 */		if (devp->sd_inq->inq_rmb) {			sd_lock_unlock(dev, 1);		}	}	New_state(un, SD_STATE_OPEN);	SD_SET_OMAP(un, &dev);	return (0);}intsdclose(dev)dev_t dev;{	register struct scsi_device *devp;	register struct scsi_disk *un;	int unit;	if ((unit = SDUNIT(dev)) >= SD_MAXUNIT) {		return (ENXIO);	} else if (!(devp = sdunits[unit]) || !devp->sd_present) {		return (ENXIO);	} else if (!(un = UPTR) || un->un_state < SD_STATE_OPEN) {		return (ENXIO);	}	DPRINTF(devp, "last close on dev %d.%d", major(dev), minor(dev));	SD_CLR_OMAP(un, &dev);	if (un->un_omap == 0) {		if (un->un_state == SD_STATE_DETACHING) {			sd_offline(devp, 1);		} else {			New_state(un, SD_STATE_CLOSED);			/*			 * If this is a removable media device, try and send			 * an ALLOW MEDIA REMOVAL command, but don't get upset			 * if it fails.			 *			 * For now, if it is a removable media device,			 * invalidate the geometry.			 *			 * XXX: Later investigate whether or not it			 * XXX: would be a good idea to invalidate			 * XXX: the geometry for all devices.			 */			if (devp->sd_inq->inq_rmb) {				sd_lock_unlock(dev, 0);				un->un_gvalid = 0;			}		}	}	return (0);}static voidsd_offline(devp, bechatty)register struct scsi_device *devp;int bechatty;{	register struct scsi_disk *un = UPTR;	if (bechatty)		sdlog(devp, LOG_WARNING, "offline");#ifdef	OPENPROMS	(void) remdk((int) un->un_dkn);#endif	/* OPENPROMS */	free_pktiopb(un->un_rqs, (caddr_t)devp->sd_sense, SENSE_LENGTH);	(void) kmem_free((caddr_t) un->un_sbufp,		(unsigned) (sizeof (struct buf)));	(void) kmem_free((caddr_t) un,		(unsigned) (sizeof (struct scsi_disk)));	devp->sd_private = (opaque_t) 0;	IOPBFREE (devp->sd_inq, SUN_INQSIZE);	devp->sd_inq = (struct scsi_inquiry *) 0;	devp->sd_sense = 0;	devp->sd_present = 0;}intsdsize(dev)dev_t dev;{	struct scsi_device *devp;	int unit;	if ((unit = SDUNIT(dev)) >= SD_MAXUNIT) {		return (-1);	} else if (!(devp = sdunits[unit]) || !devp->sd_present ||	    !UPTR->un_gvalid) {		return (-1);	}	return ((int)UPTR->un_map[SDPART(dev)].dkl_nblk);}/* * These routines perform raw i/o operations. */sdread(dev, uio)dev_t dev;struct uio *uio;{	return (sdrw(dev, uio, B_READ));}sdwrite(dev, uio)dev_t dev;struct uio *uio;{	return (sdrw(dev, uio, B_WRITE));}static voidsdmin(bp)struct buf *bp;{	if (bp->b_bcount > sdmaxphys)		bp->b_bcount = sdmaxphys;}static intsdrw(dev, uio, flag)dev_t dev;struct uio *uio;int flag;{	struct scsi_device *devp;	register int unit;	if ((unit = SDUNIT(dev)) >= SD_MAXUNIT) {		return (ENXIO);	} else if (!(devp = sdunits[unit]) || !devp->sd_present ||	    !UPTR->un_gvalid) {		return (ENXIO);	} else if ((uio->uio_fmode & FSETBLK) == 0 &&	    (uio->uio_offset & (DEV_BSIZE - 1))) {		DPRINTF(devp, "file offset not modulo %d", DEV_BSIZE);		return (EINVAL);	} else if (uio->uio_iov->iov_len & (DEV_BSIZE - 1)) {		DPRINTF(devp, "block length not modulo %d", DEV_BSIZE);		return (EINVAL);	}	return (physio(sdstrategy, (struct buf *) 0, dev, flag, sdmin, uio));}/* * strategy routine */int (*sdstrategy_tstpoint)();intsdstrategy(bp)register struct buf *bp;{	register struct scsi_device *devp;	register struct scsi_disk *un;	register struct diskhd *dp;	register s;	if (sdstrategy_tstpoint != NULL) {		if ((*sdstrategy_tstpoint)(bp)) {			return;		}	}	devp = sdunits[SDUNIT(bp->b_dev)];	if (!devp || !devp->sd_present || !(un = UPTR) ||	    un->un_state == SD_STATE_DUMPING) {nothere:		bp->b_resid = bp->b_bcount;		bp->b_flags |= B_ERROR;		bp->b_error = ENXIO;		iodone(bp);		return;	}	if (bp != un->un_sbufp && un->un_state == SD_STATE_DETACHING) {		if (sd_unit_ready(bp->b_dev) == 0) {			goto nothere;		}		/*		 * disk now back on line...		 */		New_state(un, SD_STATE_OPEN);		sdlog(devp, LOG_INFO, diskokay);	}	bp->b_flags &= ~(B_DONE|B_ERROR);	bp->av_forw = 0;	dp = &un->un_utab;	if (bp != un->un_sbufp) {		if (un->un_gvalid == 0) {			sdlog(devp, LOG_ERR, "i/o to invalid geometry");			bp->b_flags |= B_ERROR;		} else {			struct dk_map *lp = &un->un_map[SDPART(bp->b_dev)];			register daddr_t bn = dkblock(bp);			/*			 * Use s to note whether we are			 * either done and/or in error.			 */			s = 0;			if (bn < 0) {				s = -1;			} else if (bn >= lp->dkl_nblk) {				/*				 * if bn == lp->dkl_nblk,				 * Not an error, resid == count				 */				if (bn > lp->dkl_nblk) {					s = -1;				} else {					s = 1;				}			} else if (bp->b_bcount & (SECSIZE-1)) {				/*				 * This should really be:				 *				 * ... if (bp->b_bcount & (un->un_lbasize-1))				 *				 */				s = -1;			} else {				/*				 * sort by absolute block number.				 * note that b_resid is used to store				 * sort key and to return the transfer				 * resid.				 */				bp->b_resid = bn + lp->dkl_cylno *				    un->un_g.dkg_nhead * un->un_g.dkg_nsect;				/*				 * zero out av_back - this will be a signal				 * to sdstart to go and fetch the resources				 */				BP_PKT(bp) = 0;			}			/*			 * Check to see whether or not we are done (with			 * or without errors), then reuse s for tmp var			 * calculations for stats gathering.			 */			if (s != 0) {				bp->b_resid = bp->b_bcount;				if (s < 0) {					bp->b_flags |= B_ERROR;				} else {					iodone(bp);				}			}		}	} else {		/*		 * For internal cmds, we just zero out the sort key		 */		bp->b_resid = 0;	}	if ((s = (bp->b_flags & (B_DONE|B_ERROR))) == 0) {		s = splr(sdpri);		/*		 * We are doing it a bit non-standard. That is, the		 * head of the b_actf chain is *not* the active command-		 * it is just the head of the wait queue. The reason		 * we do this is that the head of the b_actf chain is		 * guaranteed to not be moved by disksort(), so that		 * our actual current active command (pointed to by		 * b_forw) and the head of the wait queue (b_actf) can		 * have resources granted without it getting lost in		 * the queue at some later point (where we would have		 * to go and look for it).		 */#ifdef	B_KLUSTER		if (klustsort(dp, bp, sdmaxphys)) {			bp = dp->b_actf;			if (BP_PKT(bp) && (bp->b_flags & B_KLUSTER)) {				scsi_resfree(BP_PKT(bp));				BP_PKT(bp) = NULL;			}		}#else	/* B_KLUSTER */		disksort(dp, bp);#endif	/* B_KLUSTER */		if ((++dp->b_bcount) > un->un_sds.sds_hiqlen)			un->un_sds.sds_hiqlen = dp->b_bcount;		if (dp->b_forw == NULL) { /* this device inactive? */			sdstart(devp);		} else if (BP_PKT(dp->b_actf) == 0) {			/*			 * try and map this one			 */			make_sd_cmd(devp, dp->b_actf, NULL_FUNC);		}		(void) splx(s);	} else if ((s & B_DONE) == 0) {		iodone(bp);	}

⌨️ 快捷键说明

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