xref: /netbsd-src/sys/arch/luna68k/stand/boot/sd.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: sd.c,v 1.5 2013/01/22 15:48:40 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 bytes/sect x %d sectors\n", sc->sc_blksize, sc->sc_blks);
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_ctlr, hd->hp_slave, 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