Home | History | Annotate | Line # | Download | only in boot
sd.c revision 1.2
      1 /*	$NetBSD: sd.c,v 1.2 2013/01/13 04:39:28 tsutsui Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1992 OMRON Corporation.
      5  *
      6  * This code is derived from software contributed to Berkeley by
      7  * OMRON Corporation.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed by the University of
     20  *	California, Berkeley and its contributors.
     21  * 4. Neither the name of the University nor the names of its contributors
     22  *    may be used to endorse or promote products derived from this software
     23  *    without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  * SUCH DAMAGE.
     36  *
     37  *	@(#)sd.c	8.1 (Berkeley) 6/10/93
     38  */
     39 /*
     40  * Copyright (c) 1992, 1993
     41  *	The Regents of the University of California.  All rights reserved.
     42  *
     43  * This code is derived from software contributed to Berkeley by
     44  * OMRON Corporation.
     45  *
     46  * Redistribution and use in source and binary forms, with or without
     47  * modification, are permitted provided that the following conditions
     48  * are met:
     49  * 1. Redistributions of source code must retain the above copyright
     50  *    notice, this list of conditions and the following disclaimer.
     51  * 2. Redistributions in binary form must reproduce the above copyright
     52  *    notice, this list of conditions and the following disclaimer in the
     53  *    documentation and/or other materials provided with the distribution.
     54  * 3. Neither the name of the University nor the names of its contributors
     55  *    may be used to endorse or promote products derived from this software
     56  *    without specific prior written permission.
     57  *
     58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     68  * SUCH DAMAGE.
     69  *
     70  *	@(#)sd.c	8.1 (Berkeley) 6/10/93
     71  */
     72 
     73 /*
     74  * sd.c -- SCSI DISK device driver
     75  * by A.Fujita, FEB-26-1992
     76  */
     77 
     78 
     79 /*
     80  * SCSI CCS (Command Command Set) disk driver.
     81  */
     82 #include <sys/param.h>
     83 #include <sys/disklabel.h>
     84 #include <luna68k/stand/boot/samachdep.h>
     85 #include <luna68k/stand/boot/scsireg.h>
     86 #include <luna68k/stand/boot/device.h>
     87 
     88 struct	disklabel sdlabel[NSD];
     89 
     90 struct	sd_softc {
     91 	struct	hp_device *sc_hd;
     92 	struct	devqueue sc_dq;
     93 	int	sc_format_pid;	/* process using "format" mode */
     94 	short	sc_flags;
     95 	short	sc_type;	/* drive type */
     96 	short	sc_punit;	/* physical unit (scsi lun) */
     97 	u_short	sc_bshift;	/* convert device blocks to DEV_BSIZE blks */
     98 	u_int	sc_blks;	/* number of blocks on device */
     99 	int	sc_blksize;	/* device block size in bytes */
    100 	u_int	sc_wpms;	/* average xfer rate in 16 bit wds/sec. */
    101 };
    102 
    103 struct sd_devdata {
    104 	int	unit;		/* drive number */
    105 	int	part;		/* partition */
    106 };
    107 
    108 static int sdinit(void *);
    109 static int sdident(struct sd_softc *, struct hp_device *);
    110 
    111 struct	driver sddriver = {
    112 	sdinit, "sd", NULL,
    113 };
    114 
    115 struct sd_softc sd_softc[NSD];
    116 struct sd_devdata sd_devdata[NSD];
    117 
    118 /* sc_flags values */
    119 #define	SDF_ALIVE	0x1
    120 
    121 #define	sdunit(x)	((minor(x) >> 3) & 0x7)
    122 #define sdpart(x)	(minor(x) & 0x7)
    123 #define	sdpunit(x)	((x) & 7)
    124 
    125 static struct scsi_inquiry inqbuf;
    126 static struct scsi_fmt_cdb inq = {
    127 	6,
    128 	{ CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 }
    129 };
    130 
    131 static u_long capbuf[2];
    132 struct scsi_fmt_cdb cap = {
    133 	10,
    134 	{ CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    135 };
    136 
    137 int
    138 sdident(struct sd_softc *sc, struct hp_device *hd)
    139 {
    140 	char idstr[32];
    141 	int unit;
    142 	int ctlr, slave;
    143 	int i;
    144 	int tries = 10;
    145 
    146 	ctlr = hd->hp_ctlr;
    147 	slave = hd->hp_slave;
    148 	unit = sc->sc_punit;
    149 
    150 	/*
    151 	 * See if unit exists and is a disk then read block size & nblocks.
    152 	 */
    153 	while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
    154 		if (i < 0 || --tries < 0)
    155 			return (-1);
    156 		if (i == STS_CHECKCOND) {
    157 			u_char sensebuf[8];
    158 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
    159 
    160 			scsi_request_sense(ctlr, slave, unit, sensebuf, 8);
    161 			if (sp->class == 7 && sp->key == 6)
    162 				/* drive doing an RTZ -- give it a while */
    163 				DELAY(1000000);
    164 		}
    165 		DELAY(1000);
    166 	}
    167 	if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
    168 			       sizeof(inqbuf)) ||
    169 	    scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
    170 			       sizeof(capbuf)))
    171 		/* doesn't exist or not a CCS device */
    172 		return (-1);
    173 
    174 	switch (inqbuf.type) {
    175 	case 0:		/* disk */
    176 	case 4:		/* WORM */
    177 	case 5:		/* CD-ROM */
    178 	case 7:		/* Magneto-optical */
    179 		break;
    180 	default:	/* not a disk */
    181 		return (-1);
    182 	}
    183 	sc->sc_blks    = capbuf[0];
    184 	sc->sc_blksize = capbuf[1];
    185 
    186 	memcpy(idstr, &inqbuf.vendor_id, 28);
    187 	for (i = 27; i > 23; --i)
    188 		if (idstr[i] != ' ')
    189 			break;
    190 	idstr[i+1] = 0;
    191 	for (i = 23; i > 7; --i)
    192 		if (idstr[i] != ' ')
    193 			break;
    194 	idstr[i+1] = 0;
    195 	for (i = 7; i >= 0; --i)
    196 		if (idstr[i] != ' ')
    197 			break;
    198 	idstr[i+1] = 0;
    199 	printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
    200 	       &idstr[24]);
    201 
    202 	printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
    203 	if (sc->sc_blksize != DEV_BSIZE) {
    204 		if (sc->sc_blksize < DEV_BSIZE) {
    205 			printf("sd%d: need %d byte blocks - drive ignored\n",
    206 				unit, DEV_BSIZE);
    207 			return (-1);
    208 		}
    209 		for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
    210 			++sc->sc_bshift;
    211 		sc->sc_blks <<= sc->sc_bshift;
    212 	}
    213 	sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);	/* XXX */
    214 	return(inqbuf.type);
    215 }
    216 
    217 int
    218 sdinit(void *arg)
    219 {
    220 	struct hp_device *hd = arg;
    221 	struct sd_softc *sc = &sd_softc[hd->hp_unit];
    222 	struct disklabel *lp;
    223 	char *msg;
    224 
    225 #ifdef DEBUG
    226 	printf("sdinit: hd->hp_unit = %d\n", hd->hp_unit);
    227 	printf("sdinit: hd->hp_ctlr = %d, hd->hp_slave = %d\n",
    228 	       hd->hp_ctlr, hd->hp_slave);
    229 #endif
    230 	sc->sc_hd = hd;
    231 	sc->sc_punit = sdpunit(hd->hp_flags);
    232 	sc->sc_type = sdident(sc, hd);
    233 	if (sc->sc_type < 0)
    234 		return(0);
    235 
    236 	/*
    237 	 * Use the default sizes until we've read the label,
    238 	 * or longer if there isn't one there.
    239 	 */
    240 	lp = &sdlabel[hd->hp_unit];
    241 
    242 	if (lp->d_secpercyl == 0) {
    243 		lp->d_secsize = DEV_BSIZE;
    244 		lp->d_nsectors = 32;
    245 		lp->d_ntracks = 20;
    246 		lp->d_secpercyl = 32*20;
    247 		lp->d_npartitions = 1;
    248 		lp->d_partitions[0].p_offset = 0;
    249 		lp->d_partitions[0].p_size = LABELSECTOR + 1;
    250 	}
    251 
    252 	/*
    253 	 * read disklabel
    254 	 */
    255 	msg = readdisklabel(hd->hp_slave, sdstrategy, lp);
    256 	if (msg != NULL)
    257 		printf("sd%d: %s\n", hd->hp_unit, msg);
    258 
    259 	sc->sc_flags = SDF_ALIVE;
    260 	return(1);
    261 }
    262 
    263 int
    264 sdopen(struct open_file *f, ...)
    265 {
    266 	va_list ap;
    267 	struct sd_devdata *sd;
    268 	int unit, part;
    269 
    270 	va_start(ap, f);
    271 	unit = va_arg(ap, int);
    272 	part = va_arg(ap, int);
    273 	va_end(ap);
    274 
    275 	if (unit < 0 || unit >= NSD)
    276 		return(-1);
    277 	if (part < 0 || part >= 8)
    278 		return(-1);
    279 
    280 	sd = &sd_devdata[unit];
    281 	sd->unit = unit;
    282 	sd->part = part;
    283 	f->f_devdata = (void *)sd;
    284 
    285 	return 0;
    286 }
    287 
    288 int
    289 sdclose(struct open_file *f)
    290 {
    291 	struct sd_devdata *sd = f->f_devdata;
    292 
    293 	sd->unit = -1;
    294 	sd->part = -1;
    295 	f->f_devdata = NULL;
    296 
    297 	return 0;
    298 }
    299 
    300 static struct scsi_fmt_cdb cdb_read = {
    301 	10,
    302 	{ CMD_READ_EXT,  0, 0, 0, 0, 0, 0, 0, 0, 0 }
    303 };
    304 
    305 static struct scsi_fmt_cdb cdb_write = {
    306 	6,
    307 	{ CMD_WRITE_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    308 };
    309 
    310 int
    311 sdstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf,
    312     size_t *rsize)
    313 {
    314 	struct sd_devdata *sd = devdata;
    315 	struct disklabel *lp;
    316 	uint8_t *buf = v_buf;
    317 	int unit = sd->unit;
    318 	int part = sd->part;
    319 	struct sd_softc *sc = &sd_softc[unit];
    320 	struct scsi_fmt_cdb *cdb;
    321 	daddr_t blk;
    322 	u_int nblk  = size >> sc->sc_bshift;
    323 	int stat, ctlr, slave;
    324 #ifdef DEBUG
    325 	int i;
    326 #endif
    327 
    328 	if (unit < 0 || unit >= NSD)
    329 		return(-1);
    330 
    331 	ctlr  = sc->sc_hd->hp_ctlr;
    332 	slave = sc->sc_hd->hp_slave;
    333 
    334 	lp = &sdlabel[unit];
    335 	blk = dblk + (lp->d_partitions[part].p_offset >> sc->sc_bshift);
    336 
    337 	if (func == F_READ)
    338 		cdb = &cdb_read;
    339 	else
    340 		cdb = &cdb_write;
    341 
    342 	cdb->cdb[2] = (blk & 0xff000000) >> 24;
    343 	cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
    344 	cdb->cdb[4] = (blk & 0x0000ff00) >>  8;
    345 	cdb->cdb[5] = (blk & 0x000000ff);
    346 
    347 	cdb->cdb[7] = ((nblk >> DEV_BSHIFT) & 0xff00) >> 8;
    348 	cdb->cdb[8] = ((nblk >> DEV_BSHIFT) & 0x00ff);
    349 
    350 #ifdef DEBUG
    351 	printf("sdstrategy: unit = %d\n", unit);
    352 	printf("sdstrategy: blk = %lu (0x%lx), nblk = %u (0x%x)\n", (u_long)blk, (long)blk, nblk, nblk);
    353 	for (i = 0; i < 10; i++)
    354 		printf("sdstrategy: cdb[%d] = 0x%x\n", i, cdb->cdb[i]);
    355 	printf("sdstrategy: ctlr = %d, slave = %d\n", ctlr, slave);
    356 #endif
    357 	stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb, buf, size);
    358 	if (rsize)
    359 		*rsize = size;
    360 
    361 	return 0;
    362 }
    363 
    364 #if 0
    365 int
    366 sdread(dev_t dev, u_int blk, u_int nblk, u_char *buff, u_int len)
    367 {
    368 	int unit = sdunit(dev);
    369 	int part = sdpart(dev);
    370 	struct sd_softc *sc = &sd_softc[unit];
    371 	struct scsi_fmt_cdb *cdb;
    372 	int stat, ctlr, slave;
    373 
    374 	ctlr  = sc->sc_hd->hp_ctlr;
    375 	slave = sc->sc_hd->hp_slave;
    376 
    377 	cdb = &cdb_read;
    378 
    379 	cdb->cdb[2] = (blk & 0xff000000) >> 24;
    380 	cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
    381 	cdb->cdb[4] = (blk & 0x0000ff00) >>  8;
    382 	cdb->cdb[5] = (blk & 0x000000ff);
    383 
    384 	cdb->cdb[7] = (nblk & 0xff00) >> 8;
    385 	cdb->cdb[8] = (nblk & 0x00ff);
    386 
    387 	stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb,  buff, len);
    388 
    389 	if (stat == 0)
    390 		return(1);
    391 	else
    392 		return(0);
    393 }
    394 
    395 int
    396 sdioctl(dev_t dev, u_long data[])
    397 {
    398 	int unit = sdunit(dev);
    399 	int part = sdpart(dev);
    400 	struct disklabel *lp;
    401 
    402 	if (unit < 0 || unit >= NSD)
    403 		return(0);
    404 
    405 	if (part < 0 || part >= MAXPARTITIONS)
    406 		return(0);
    407 
    408 	lp = &sdlabel[unit];
    409 	data[0] = lp->d_partitions[part].p_offset;
    410 	data[1] = lp->d_partitions[part].p_size;
    411 
    412 	return(1);
    413 }
    414 #endif
    415