Home | History | Annotate | Line # | Download | only in boot
sd.c revision 1.8
      1 /*	$NetBSD: sd.c,v 1.8 2014/01/03 07:17:19 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 	short	sc_flags;
     93 	short	sc_type;	/* drive type */
     94 	short	sc_punit;	/* physical unit (scsi lun) */
     95 	u_short	sc_bshift;	/* convert device blocks to DEV_BSIZE blks */
     96 	u_int	sc_blks;	/* number of blocks on device */
     97 	int	sc_blksize;	/* device block size in bytes */
     98 };
     99 
    100 struct sd_devdata {
    101 	int	unit;		/* drive number */
    102 	int	part;		/* partition */
    103 };
    104 
    105 static int sdinit(void *);
    106 static int sdident(struct sd_softc *, struct hp_device *);
    107 
    108 struct	driver sddriver = {
    109 	sdinit, "sd", NULL,
    110 };
    111 
    112 struct sd_softc sd_softc[NSD];
    113 struct sd_devdata sd_devdata[NSD];
    114 
    115 /* sc_flags values */
    116 #define	SDF_ALIVE	0x1
    117 
    118 #define	sdunit(x)	((minor(x) >> 3) & 0x7)
    119 #define sdpart(x)	(minor(x) & 0x7)
    120 
    121 static struct scsi_inquiry inqbuf;
    122 static struct scsi_generic_cdb inq = {
    123 	6,
    124 	{ CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 }
    125 };
    126 
    127 static u_long capbuf[2];
    128 struct scsi_generic_cdb cap = {
    129 	10,
    130 	{ CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    131 };
    132 
    133 int
    134 sdident(struct sd_softc *sc, struct hp_device *hd)
    135 {
    136 	char idstr[32];
    137 	int unit;
    138 	int ctlr, slave;
    139 	int i;
    140 	int tries = 10;
    141 
    142 	ctlr = hd->hpd_ctlr;
    143 	slave = hd->hpd_slave;
    144 	unit = sc->sc_punit;
    145 
    146 	/*
    147 	 * See if unit exists and is a disk then read block size & nblocks.
    148 	 */
    149 	while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
    150 		if (i < 0 || --tries < 0)
    151 			return (-1);
    152 		if (i == STS_CHECKCOND) {
    153 			u_char sensebuf[8];
    154 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
    155 
    156 			scsi_request_sense(ctlr, slave, unit, sensebuf, 8);
    157 			if (sp->class == 7 && sp->key == 6)
    158 				/* drive doing an RTZ -- give it a while */
    159 				DELAY(1000000);
    160 		}
    161 		DELAY(1000);
    162 	}
    163 	if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
    164 			       sizeof(inqbuf)) ||
    165 	    scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
    166 			       sizeof(capbuf)))
    167 		/* doesn't exist or not a CCS device */
    168 		return (-1);
    169 
    170 	switch (inqbuf.type) {
    171 	case 0:		/* disk */
    172 	case 4:		/* WORM */
    173 	case 5:		/* CD-ROM */
    174 	case 7:		/* Magneto-optical */
    175 		break;
    176 	default:	/* not a disk */
    177 		return (-1);
    178 	}
    179 	sc->sc_blks    = capbuf[0];
    180 	sc->sc_blksize = capbuf[1];
    181 
    182 	memcpy(idstr, &inqbuf.vendor_id, 28);
    183 	for (i = 27; i > 23; --i)
    184 		if (idstr[i] != ' ')
    185 			break;
    186 	idstr[i+1] = 0;
    187 	for (i = 23; i > 7; --i)
    188 		if (idstr[i] != ' ')
    189 			break;
    190 	idstr[i+1] = 0;
    191 	for (i = 7; i >= 0; --i)
    192 		if (idstr[i] != ' ')
    193 			break;
    194 	idstr[i+1] = 0;
    195 	printf("sd%d: %s %s rev %s", hd->hpd_unit, idstr, &idstr[8],
    196 	       &idstr[24]);
    197 
    198 	printf(", %d bytes/sect x %d sectors\n", sc->sc_blksize, sc->sc_blks);
    199 	if (sc->sc_blksize != DEV_BSIZE) {
    200 		if (sc->sc_blksize < DEV_BSIZE) {
    201 			printf("sd%d: need %d byte blocks - drive ignored\n",
    202 				unit, DEV_BSIZE);
    203 			return (-1);
    204 		}
    205 		for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
    206 			++sc->sc_bshift;
    207 		sc->sc_blks <<= sc->sc_bshift;
    208 	}
    209 	return(inqbuf.type);
    210 }
    211 
    212 int
    213 sdinit(void *arg)
    214 {
    215 	struct hp_device *hd = arg;
    216 	struct sd_softc *sc = &sd_softc[hd->hpd_unit];
    217 	struct disklabel *lp;
    218 	char *msg;
    219 
    220 #ifdef DEBUG
    221 	printf("sdinit: hd->hpd_unit = %d\n", hd->hpd_unit);
    222 	printf("sdinit: hd->hpd_ctlr = %d, hd->hpd_slave = %d\n",
    223 	       hd->hpd_ctlr, hd->hpd_slave);
    224 #endif
    225 	sc->sc_hd = hd;
    226 	sc->sc_punit = 0;	/* XXX no LUN support yet */
    227 	sc->sc_type = sdident(sc, hd);
    228 	if (sc->sc_type < 0)
    229 		return(0);
    230 
    231 	/*
    232 	 * Use the default sizes until we've read the label,
    233 	 * or longer if there isn't one there.
    234 	 */
    235 	lp = &sdlabel[hd->hpd_unit];
    236 
    237 	if (lp->d_secpercyl == 0) {
    238 		lp->d_secsize = DEV_BSIZE;
    239 		lp->d_nsectors = 32;
    240 		lp->d_ntracks = 20;
    241 		lp->d_secpercyl = 32*20;
    242 		lp->d_npartitions = 1;
    243 		lp->d_partitions[0].p_offset = 0;
    244 		lp->d_partitions[0].p_size = LABELSECTOR + 1;
    245 	}
    246 
    247 	/*
    248 	 * read disklabel
    249 	 */
    250 	msg = readdisklabel(hd->hpd_ctlr, hd->hpd_slave, lp);
    251 	if (msg != NULL)
    252 		printf("sd%d: %s\n", hd->hpd_unit, msg);
    253 
    254 	sc->sc_flags = SDF_ALIVE;
    255 	return(1);
    256 }
    257 
    258 int
    259 sdopen(struct open_file *f, ...)
    260 {
    261 	va_list ap;
    262 	struct sd_devdata *sd;
    263 	int unit, part;
    264 
    265 	va_start(ap, f);
    266 	unit = va_arg(ap, int);
    267 	part = va_arg(ap, int);
    268 	va_end(ap);
    269 
    270 	if (unit < 0 || unit >= NSD)
    271 		return(-1);
    272 	if (part < 0 || part >= 8)
    273 		return(-1);
    274 
    275 	sd = &sd_devdata[unit];
    276 	sd->unit = unit;
    277 	sd->part = part;
    278 	f->f_devdata = (void *)sd;
    279 
    280 	return 0;
    281 }
    282 
    283 int
    284 sdclose(struct open_file *f)
    285 {
    286 	struct sd_devdata *sd = f->f_devdata;
    287 
    288 	sd->unit = -1;
    289 	sd->part = -1;
    290 	f->f_devdata = NULL;
    291 
    292 	return 0;
    293 }
    294 
    295 static struct scsi_generic_cdb cdb_read = {
    296 	10,
    297 	{ CMD_READ_EXT,  0, 0, 0, 0, 0, 0, 0, 0, 0 }
    298 };
    299 
    300 static struct scsi_generic_cdb cdb_write = {
    301 	6,
    302 	{ CMD_WRITE_EXT, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    303 };
    304 
    305 int
    306 sdstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf,
    307     size_t *rsize)
    308 {
    309 	struct sd_devdata *sd = devdata;
    310 	struct disklabel *lp;
    311 	uint8_t *buf = v_buf;
    312 	int unit = sd->unit;
    313 	int part = sd->part;
    314 	struct sd_softc *sc = &sd_softc[unit];
    315 	struct scsi_generic_cdb *cdb;
    316 	daddr_t blk;
    317 	u_int nblk  = size >> sc->sc_bshift;
    318 	int stat, ctlr, slave;
    319 #ifdef DEBUG
    320 	int i;
    321 #endif
    322 
    323 	if (unit < 0 || unit >= NSD)
    324 		return(-1);
    325 
    326 	ctlr  = sc->sc_hd->hpd_ctlr;
    327 	slave = sc->sc_hd->hpd_slave;
    328 
    329 	lp = &sdlabel[unit];
    330 	blk = dblk + (lp->d_partitions[part].p_offset >> sc->sc_bshift);
    331 
    332 	if (func == F_READ)
    333 		cdb = &cdb_read;
    334 	else
    335 		cdb = &cdb_write;
    336 
    337 	cdb->cdb[2] = (blk & 0xff000000) >> 24;
    338 	cdb->cdb[3] = (blk & 0x00ff0000) >> 16;
    339 	cdb->cdb[4] = (blk & 0x0000ff00) >>  8;
    340 	cdb->cdb[5] = (blk & 0x000000ff);
    341 
    342 	cdb->cdb[7] = ((nblk >> DEV_BSHIFT) & 0xff00) >> 8;
    343 	cdb->cdb[8] = ((nblk >> DEV_BSHIFT) & 0x00ff);
    344 
    345 #ifdef DEBUG
    346 	printf("sdstrategy: unit = %d\n", unit);
    347 	printf("sdstrategy: blk = %lu (0x%lx), nblk = %u (0x%x)\n", (u_long)blk, (long)blk, nblk, nblk);
    348 	for (i = 0; i < 10; i++)
    349 		printf("sdstrategy: cdb[%d] = 0x%x\n", i, cdb->cdb[i]);
    350 	printf("sdstrategy: ctlr = %d, slave = %d\n", ctlr, slave);
    351 #endif
    352 	stat = scsi_immed_command(ctlr, slave, sc->sc_punit, cdb, buf, size);
    353 	if (rsize)
    354 		*rsize = size;
    355 
    356 	return 0;
    357 }
    358