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