xref: /original-bsd/sys/luna68k/dev/sd.c (revision 8bb6539f)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * OMRON Corporation.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)sd.c	7.2 (Berkeley) 07/13/92
12  */
13 
14 /*
15  * sd.c -- SCSI Disk Device Driver
16  * remaked by A.Fujita, MAR-22-1992
17  */
18 
19 /*
20  * SCSI CCS (Command Command Set) disk driver.
21  */
22 #include "sd.h"
23 #if NSD > 0
24 
25 #include "sys/param.h"
26 #include "sys/buf.h"
27 #include "sys/dkstat.h"
28 #include "sys/proc.h"
29 #include "sys/disklabel.h"
30 
31 #include "device.h"
32 #include "scsireg.h"
33 #include "scsivar.h"
34 
35 int	sdinit(), sdstrategy(), sdstart(), sdintr();
36 
37 struct	driver sddriver = {
38 	sdinit, "sd", sdstart, (int (*)()) 0, sdintr, (int (*)()) 0
39 };
40 
41 struct	disklabel sdlabel[NSD];
42 
43 struct	sd_softc {
44 	struct	hp_device *sc_hd;
45 	struct	scsi_queue sc_dq;
46 	short	sc_flags;
47 	short	sc_type;	/* drive type */
48 	short	sc_punit;	/* physical unit (scsi lun) */
49 	u_int	sc_blks;	/* number of blocks on device */
50 	int	sc_blksize;	/* device block size in bytes */
51 	u_int	sc_wpms;	/* average xfer rate in 16 bit wds/sec. */
52 } sd_softc[NSD];
53 
54 /* sc_flags values */
55 #define	SDF_ALIVE	0x1
56 
57 struct	buf sdtab[NSD];
58 struct	scsi_fmt_sense sdsense[NSD];
59 
60 static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
61 static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
62 
63 #define	sdunit(x)	((minor(x) >> 3) & 0x7)
64 #define sdpart(x)	(minor(x) & 0x7)
65 #define	sdpunit(x)	((x) & 7)
66 #define sdminor(unit, part)	(((unit) << 3) | (part))
67 
68 #define	b_lba		b_resid
69 
70 #define	SDRETRY		3	/* IO retry count */
71 
72 struct sd_iostat {
73 	int imax;
74 	int imin;
75 	int omax;
76 	int omin;
77 };
78 
79 struct sd_iostat sd_iostat[NSD] = {
80 	{ 14000, -1, 100, -1 },
81 };
82 
83 /*
84  * Initialize
85  */
86 
87 int
88 sdinit(hd)
89 	register struct hp_device *hd;
90 {
91 	register struct sd_softc *sc = &sd_softc[hd->hp_unit];
92 	register struct disklabel *lp;
93 	char *msg, *sdreadlabel();
94 
95 	sc->sc_hd = hd;
96 	sc->sc_punit = sdpunit(hd->hp_flags);
97 	sc->sc_type = sdident(sc, hd);
98 	if (sc->sc_type < 0)
99 		return(0);
100 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
101 	sc->sc_dq.dq_unit = hd->hp_unit;
102 	sc->sc_dq.dq_slave = hd->hp_slave;
103 	sc->sc_dq.dq_driver = &sddriver;
104 
105 	/*
106 	 * Use the default sizes until we've read the label,
107 	 * or longer if there isn't one there.
108 	 */
109 	lp = &sdlabel[hd->hp_unit];
110 
111 	if (lp->d_secpercyl == 0) {
112 		lp->d_secsize = DEV_BSIZE;
113 		lp->d_nsectors = 32;
114 		lp->d_ntracks = 20;
115 		lp->d_secpercyl = 32*20;
116 		lp->d_npartitions = 1;
117 		lp->d_partitions[0].p_offset = 0;
118 		lp->d_partitions[0].p_size = LABELSECTOR + 1;
119 	}
120 
121 	/*
122 	 * read disklabel
123 	 */
124 	if (msg = sdreadlabel(makedev(4, (hd->hp_unit<<3)), sdstrategy, lp)) {
125 		if (msg != NULL) {
126 			printf("sd%d: %s\n", hd->hp_unit, msg);
127 			return(0);
128 		}
129 	}
130 
131 	sc->sc_flags = SDF_ALIVE;
132 	return(1);
133 }
134 
135 static struct scsi_inquiry inqbuf;
136 static struct scsi_fmt_cdb inq = {
137 	6,
138 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
139 };
140 
141 static u_long capbuf[2];
142 struct scsi_fmt_cdb cap = {
143 	10,
144 	CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
145 };
146 
147 int
148 sdident(sc, hd)
149 	struct sd_softc *sc;
150 	struct hp_device *hd;
151 {
152 	char idstr[32];
153 	int unit;
154 	register int ctlr, slave;
155 	register int i;
156 	register int tries = 10;
157 
158 	ctlr = hd->hp_ctlr;
159 	slave = hd->hp_slave;
160 	unit = sc->sc_punit;
161 
162 	/*
163 	 * See if unit exists and is a disk then read block size & nblocks.
164 	 */
165 	while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
166 		if (i < 0 || --tries < 0)
167 			return (-1);
168 		if (i == STS_CHECKCOND) {
169 			u_char sensebuf[8];
170 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
171 
172 			scsi_request_sense(ctlr, slave, unit, sensebuf, 8);
173 			if (sp->class == 7 && sp->key == 6)
174 				/* drive doing an RTZ -- give it a while */
175 				DELAY(1000000);
176 		}
177 		DELAY(1000);
178 	}
179 	if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
180 			       sizeof(inqbuf)) ||
181 	    scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
182 			       sizeof(capbuf)))
183 		/* doesn't exist or not a CCS device */
184 		return (-1);
185 
186 	switch (inqbuf.type) {
187 	case 0:		/* disk */
188 	case 4:		/* WORM */
189 	case 5:		/* CD-ROM */
190 	case 7:		/* Magneto-optical */
191 		break;
192 	default:	/* not a disk */
193 		return (-1);
194 	}
195 	sc->sc_blks    = capbuf[0];
196 	sc->sc_blksize = capbuf[1];
197 
198 	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
199 	for (i = 27; i > 23; --i)
200 		if (idstr[i] != ' ')
201 			break;
202 	idstr[i+1] = 0;
203 	for (i = 23; i > 7; --i)
204 		if (idstr[i] != ' ')
205 			break;
206 	idstr[i+1] = 0;
207 	for (i = 7; i >= 0; --i)
208 		if (idstr[i] != ' ')
209 			break;
210 	idstr[i+1] = 0;
211 	printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
212 	       &idstr[24]);
213 
214 	printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
215 	if (sc->sc_blksize != DEV_BSIZE) {
216 		printf("sd%d: need %d byte blocks - drive ignored\n", unit, DEV_BSIZE);
217 		return(1);
218 	}
219 
220 	sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);	/* XXX */
221 	return(inqbuf.type);
222 }
223 
224 
225 /*
226  * Open
227  */
228 
229 int
230 sdopen(dev, flags, mode, p)
231 	dev_t dev;
232 	int flags, mode;
233 	struct proc *p;
234 {
235 	register int unit = sdunit(dev);
236 	register struct sd_softc *sc = &sd_softc[unit];
237 
238 	if (unit >= NSD)
239 		return(ENXIO);
240 	if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
241 		return(ENXIO);
242 
243 	if (sc->sc_hd->hp_dk >= 0)
244 		dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms;
245 	return(0);
246 }
247 
248 
249 /*
250  * Strategy
251  */
252 
253 int
254 sdstrategy(bp)
255 	register struct buf *bp;
256 {
257 	register int unit = sdunit(bp->b_dev);
258 	register int part = sdpart(bp->b_dev);
259 	register struct sd_softc *sc = &sd_softc[unit];
260 	register struct disklabel *lp = &sdlabel[unit];
261 	register struct partition *pp = &(lp->d_partitions[part]);
262 	register struct buf *dp = &sdtab[unit];
263 	register daddr_t bn;
264 	register int sz, s;
265 
266 #ifdef DEBUG
267 	printf("sdstrategy: bp->b_blkno = %d, bp->bcount = %d\n",
268 	       bp->b_blkno, bp->b_bcount);
269 #endif
270 	bn = bp->b_blkno;
271 	sz = howmany(bp->b_bcount, DEV_BSIZE);
272 
273 	/* check that tracsfer is within a drive's partition */
274 
275 	if (bn < 0 || (bn + sz) > pp->p_size) {
276 		sz = pp->p_size - bn;
277 		if (sz == 0) {
278 			bp->b_resid = bp->b_bcount;
279 			goto done;
280 		}
281 		if (sz < 0) {
282 			bp->b_error = EINVAL;
283 			bp->b_flags |= B_ERROR;
284 			goto done;
285 		}
286 		bp->b_bcount = dbtob(sz);
287 	}
288 
289 	/* calculate LBA for transfer */
290 
291 	bp->b_lba = bn + pp->p_offset;
292 
293 	/* raise priority to block sdintr */
294 
295 	s = splbio();
296 
297 	/* call disksort to sort request into drive queue */
298 
299 	disksort(dp, bp);
300 
301 #ifdef DEBUG
302 	printf("sdstrategy: dp->b_active = %d\n", dp->b_active);
303 #endif
304 	if (dp->b_active == 0) {			/*  */
305 		dp->b_active = 1;
306 		sdustart(unit);
307 	}
308 
309 	/* lower priority */
310 
311 	splx(s);
312 
313 	return;
314 
315 done:
316 	biodone(bp);
317 }
318 
319 int
320 sdustart(unit)
321 	register int unit;
322 {
323 	register struct sd_softc *sc = &sd_softc[unit];
324 	register struct hp_device *hp = sc->sc_hd;
325 	register struct scsi_queue *dq = &sc->sc_dq;
326 	register struct buf *bp = sdtab[unit].b_actf;
327 	register struct scsi_fmt_cdb *cmd;
328 
329 	cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
330 	*(int *)(&cmd->cdb[2]) = bp->b_lba;
331 	*(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE);
332 
333 	dq->dq_cdb   = cmd;
334 	dq->dq_bp    = bp;
335 	dq->dq_flags = DQ_DISCONNECT;	/* SCSI Disconnect */
336 
337 	if (screq(dq))
338 		sdstart(unit);
339 }
340 
341 int
342 sdstart(unit)
343 	register int unit;
344 {
345 	register struct sd_softc *sc = &sd_softc[unit];
346 	register struct hp_device *hp = sc->sc_hd;
347 
348 	if (hp->hp_dk >= 0) {
349 		dk_busy |= 1 << hp->hp_dk;
350 	}
351 
352 	scstart(hp->hp_ctlr);
353 }
354 
355 
356 /*
357  * Return:
358  *	0	if not really an error
359  *	<0	if we should do a retry
360  *	>0	if a fatal error
361  */
362 static int
363 sderror(unit, sc, hp, stat)
364 	int unit, stat;
365 	register struct sd_softc *sc;
366 	register struct hp_device *hp;
367 {
368 	int cond = 1;
369 
370 	sdsense[unit].status = stat;
371 	if (stat & STS_CHECKCOND) {
372 		struct scsi_xsense *sp;
373 
374 		scsi_request_sense(hp->hp_ctlr, hp->hp_slave,
375 				   sc->sc_punit, sdsense[unit].sense,
376 				   sizeof(sdsense[unit].sense));
377 		sp = (struct scsi_xsense *)sdsense[unit].sense;
378 		printf("sd%d: scsi sense class %d, code %d", unit,
379 			sp->class, sp->code);
380 		if (sp->class == 7) {
381 			printf(", key %d", sp->key);
382 			if (sp->valid)
383 				printf(", blk %d", *(int *)&sp->info1);
384 			switch (sp->key) {
385 			/* no sense, try again */
386 			case 0:
387 				cond = -1;
388 				break;
389 			/* recovered error, not a problem */
390 			case 1:
391 				cond = 0;
392 				break;
393 			}
394 		}
395 		printf("\n");
396 	}
397 	return(cond);
398 }
399 
400 /*
401  * Interrupt
402  */
403 
404 int
405 sdintr(unit, stat)
406 	register int unit;
407 	int stat;
408 {
409 	register struct sd_softc *sc = &sd_softc[unit];
410 	register struct hp_device *hp = sc->sc_hd;
411 	register struct scsi_queue *dq = &sc->sc_dq;
412 	register struct buf *bp = dq->dq_bp;
413 	int cond;
414 
415 #ifdef DEBUG
416 	printf("sdintr(unit = %d, stat = %d)\n", unit, stat);
417 #endif
418 
419 	if (stat == SC_IO_TIMEOUT) {
420 		printf("sdintr: sd%d timeout error\n", unit, stat);
421 	}
422 
423 	if (hp->hp_dk >= 0) {
424 		dk_busy &=~ (1 << hp->hp_dk);
425 		if (stat == 0) {
426 			++dk_seek[hp->hp_dk];
427 			++dk_xfer[hp->hp_dk];
428 			dk_wds[hp->hp_dk] += bp->b_bcount >> 6;
429 		}
430 	}
431 
432 	if (bp->b_flags & B_READ) {
433 		sd_iostat[unit].imin = min(dq->dq_imin, sd_iostat[unit].imin);
434 		if (dq->dq_imax > sd_iostat[unit].imax) {
435 			sd_iostat[unit].imax = dq->dq_imax;
436 #ifdef SD_IOSTAT
437 			printf("sdintr: sd%d  INPUT	MAX = %d, MIN = %d\n",
438 			       unit, sd_iostat[unit].imax, sd_iostat[unit].imin);
439 #endif
440 		}
441 	} else {
442 		sd_iostat[unit].omin = min(dq->dq_omin, sd_iostat[unit].omin);
443 		if (dq->dq_omax > sd_iostat[unit].omax) {
444 			sd_iostat[unit].omax = dq->dq_omax;
445 #ifdef SD_IOSTAT
446 			printf("sdintr: sd%d  OUTPUT	MAX = %d, MIN = %d\n",
447 			       unit, sd_iostat[unit].omax, sd_iostat[unit].omin);
448 #endif
449 		}
450 	}
451 
452 	if (stat != 0) {
453 		if (stat > 0) {
454 #ifdef DEBUGPRINT
455 			dbgprintall();
456 			printf("\n");
457 #endif
458 			cond = sderror(unit, sc, hp, stat);
459 			if (cond) {
460 				if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
461 					sdstart(unit);
462 					return;
463 				}
464 			}
465 		} else {
466 			if (sdtab[unit].b_errcnt++ < SDRETRY) {
467 				printf("sdintr: sd%d restart IO request\n", unit);
468 				sdstart(unit);
469 				return;
470 			}
471 		}
472 		bp->b_flags |= B_ERROR;
473 		bp->b_error = EIO;
474 	}
475 
476 	sdtab[unit].b_errcnt = 0;
477 	sdtab[unit].b_actf = bp->b_actf;
478 
479 	bp->b_resid = 0;
480 
481 	biodone(bp);
482 
483 	scfree(dq);
484 
485 	if (sdtab[unit].b_actf) {
486 		sdustart(unit);
487 	} else {
488 		sdtab[unit].b_active = 0;
489 	}
490 }
491 
492 
493 /*
494  * RAW Device Routines
495  */
496 
497 int
498 sdread(dev, uio, flags)
499 	dev_t dev;
500 	struct uio *uio;
501 	int flags;
502 {
503 	register int unit = sdunit(dev);
504 
505 	return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));
506 }
507 
508 int
509 sdwrite(dev, uio, flags)
510 	dev_t dev;
511 	struct uio *uio;
512 	int flags;
513 {
514 	register int unit = sdunit(dev);
515 
516 	return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));
517 }
518 
519 int
520 sdioctl(dev, cmd, data, flag, p)
521 	dev_t dev;
522 	int cmd;
523 	caddr_t data;
524 	int flag;
525 	struct proc *p;
526 {
527 	int unit = sdunit(dev);
528 	register struct sd_softc *sc = &sd_softc[unit];
529 	register struct disklabel *lp = &sdlabel[unit];
530 	int error = 0;
531 
532 	switch (cmd) {
533 
534 	case DIOCGDINFO:
535 		*(struct disklabel *)data = *lp;
536 		break;
537 
538 	case DIOCGPART:
539 		((struct partinfo *)data)->disklab = lp;
540 		((struct partinfo *)data)->part =
541 		    &lp->d_partitions[sdpart(dev)];
542 		break;
543 
544 	default:
545 		error = ENOTTY;
546 		break;
547 	}
548 	return (error);
549 }
550 
551 
552 /*
553  * Size
554  */
555 
556 int
557 sdsize(dev)
558 	dev_t dev;
559 {
560 	register int unit = sdunit(dev);
561 	register struct sd_softc *sc = &sd_softc[unit];
562 
563 	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
564 		return(-1);
565 
566 	return(sdlabel[unit].d_partitions[sdpart(dev)].p_size);
567 }
568 
569 
570 /*
571  * Dump
572  */
573 
574 int
575 sddump(dev)
576 	dev_t dev;
577 {
578 }
579 
580 /*
581  * Disk Subs
582  */
583 
584 /*
585  * Attempt to read a disk label from a device
586  * using the indicated stategy routine.
587  * The label must be partly set up before this:
588  * secpercyl and anything required in the strategy routine
589  * (e.g., sector size) must be filled in before calling us.
590  * Returns null on success and an error string on failure.
591  */
592 char *
593 sdreadlabel(dev, strat, lp)
594 	dev_t dev;
595 	int (*strat)();
596 	register struct disklabel *lp;
597 {
598 	register struct buf *bp;
599 	struct disklabel *dlp;
600 	char *msg = NULL;
601 
602 	if (lp->d_secperunit == 0)
603 		lp->d_secperunit = 0x1fffffff;
604 	lp->d_npartitions = 1;
605 	if (lp->d_partitions[0].p_size == 0)
606 		lp->d_partitions[0].p_size = 0x1fffffff;
607 	lp->d_partitions[0].p_offset = 0;
608 
609 	bp = geteblk((int)lp->d_secsize);
610 	bp->b_dev = dev;
611 	bp->b_blkno = LABELSECTOR;
612 	bp->b_bcount = lp->d_secsize;
613 	bp->b_flags = B_BUSY | B_READ;
614 	(*strat)(bp);
615 	if (biowait(bp)) {
616 		msg = "I/O error";
617 	} else {
618 		for (dlp = (struct disklabel *)bp->b_un.b_addr;
619 		     dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
620 		     dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
621 			if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
622 				if (msg == NULL)
623 					msg = "no disk label";
624 			} else if (dlp->d_npartitions > MAXPARTITIONS ||
625 				   dkcksum(dlp) != 0)
626 				msg = "disk label corrupted";
627 			else {
628 				*lp = *dlp;
629 				msg = NULL;
630 				break;
631 			}
632 		}
633 	}
634 	bp->b_flags = B_INVAL | B_AGE;
635 	brelse(bp);
636 	return (msg);
637 }
638 
639 #ifdef notyet
640 
641 /*
642  * Checksum routine for OMRON native disklabel
643  */
644 
645 #define	OMRON_LBLSIZE	512
646 
647 u_short
648 omcksum(omp)
649 	register char *omp;
650 {
651 	register u_short *start, *end;
652 	register u_short sum = 0;
653 
654 	start = (u_short *) omp;
655 	end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)];
656 	while (start < end)
657 		sum ^= *start++;
658 
659 	printf("omcksum: saved  ... 0x%s\n", hexstr(*end, 4));
660 	printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4));
661 
662 	return (sum);
663 }
664 
665 /*
666  * Write disk label back to device after modification.
667  */
668 sdwritelabel(dev, strat, lp)
669 	dev_t dev;
670 	int (*strat)();
671 	register struct disklabel *lp;
672 {
673 	struct buf *bp;
674 	struct disklabel *dlp;
675 	int labelpart;
676 	int error = 0;
677 
678 	labelpart = sdpart(dev);
679 	if (lp->d_partitions[labelpart].p_offset != 0) {
680 		if (lp->d_partitions[0].p_offset != 0)
681 			return (EXDEV);			/* not quite right */
682 		labelpart = 0;
683 	}
684 
685 	bp = geteblk((int)lp->d_secsize);
686 	bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart));
687 	bp->b_blkno = LABELSECTOR;
688 	bp->b_bcount = lp->d_secsize;
689 	bp->b_flags = B_READ;
690 	(*strat)(bp);
691 	if (error = biowait(bp))
692 		goto done;
693 
694 	for (dlp = (struct disklabel *)bp->b_un.b_addr;
695 	    dlp <= (struct disklabel *)
696 	      (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
697 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
698 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
699 		    dkcksum(dlp) == 0) {
700 			omcksum(bp->b_un.b_addr);
701 /*
702 			*dlp = *lp;
703 			bp->b_flags = B_WRITE;
704 			(*strat)(bp);
705 			error = biowait(bp);
706 			goto done;
707  */
708 		}
709 	}
710 	error = ESRCH;
711 done:
712 	brelse(bp);
713 	return (error);
714 }
715 #endif
716 
717 #endif
718