xref: /original-bsd/sys/luna68k/dev/sd.c (revision f51da917)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992, 1993
4  *	The Regents of the University of California.  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	8.3 (Berkeley) 12/07/93
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/screg.h>
34 #include <luna68k/dev/scvar.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 = sc_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 			sc_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  * Close
252  */
253 
254 int
255 sdclose(dev, flag, mode, p)
256 	dev_t dev;
257 	int flag, mode;
258 	struct proc *p;
259 {
260 	return(0);
261 }
262 
263 /*
264  * Strategy
265  */
266 
267 int
268 sdstrategy(bp)
269 	register struct buf *bp;
270 {
271 	register int unit = sdunit(bp->b_dev);
272 	register int part = sdpart(bp->b_dev);
273 	register struct sd_softc *sc = &sd_softc[unit];
274 	register struct disklabel *lp = &sdlabel[unit];
275 	register struct partition *pp = &(lp->d_partitions[part]);
276 	register struct buf *dp = &sdtab[unit];
277 	register daddr_t bn;
278 	register int sz, s;
279 
280 	bn = bp->b_blkno;
281 	sz = howmany(bp->b_bcount, DEV_BSIZE);
282 
283 	/* check that tracsfer is within a drive's partition */
284 
285 	if (bn < 0 || (bn + sz) > pp->p_size) {
286 		sz = pp->p_size - bn;
287 		if (sz == 0) {
288 			bp->b_resid = bp->b_bcount;
289 			goto done;
290 		}
291 		if (sz < 0) {
292 			bp->b_error = EINVAL;
293 			bp->b_flags |= B_ERROR;
294 			goto done;
295 		}
296 		bp->b_bcount = dbtob(sz);
297 	}
298 
299 	/* calculate LBA for transfer */
300 
301 	bp->b_lba = bn + pp->p_offset;
302 
303 	/* raise priority to block sdintr */
304 
305 	s = splbio();
306 
307 	/* call disksort to sort request into drive queue */
308 
309 	disksort(dp, bp);
310 
311 	if (dp->b_active == 0) {			/*  */
312 		dp->b_active = 1;
313 		sdustart(unit);
314 	}
315 
316 	/* lower priority */
317 
318 	splx(s);
319 
320 	return;
321 
322 done:
323 	biodone(bp);
324 }
325 
326 int
327 sdustart(unit)
328 	register int unit;
329 {
330 	register struct sd_softc *sc = &sd_softc[unit];
331 	register struct hp_device *hp = sc->sc_hd;
332 	register struct scsi_queue *dq = &sc->sc_dq;
333 	register struct buf *bp = sdtab[unit].b_actf;
334 	register struct scsi_fmt_cdb *cmd;
335 
336 	cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
337 	*(int *)(&cmd->cdb[2]) = bp->b_lba;
338 	*(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE);
339 
340 	dq->dq_cdb   = cmd;
341 	dq->dq_bp    = bp;
342 	dq->dq_flags = DQ_DISCONNECT;	/* SCSI Disconnect */
343 
344 	if (screq(dq))
345 		sdstart(unit);
346 }
347 
348 int
349 sdstart(unit)
350 	register int unit;
351 {
352 	register struct sd_softc *sc = &sd_softc[unit];
353 	register struct hp_device *hp = sc->sc_hd;
354 
355 	if (hp->hp_dk >= 0) {
356 		dk_busy |= 1 << hp->hp_dk;
357 	}
358 
359 	scstart(hp->hp_ctlr);
360 }
361 
362 
363 /*
364  * Return:
365  *	0	if not really an error
366  *	<0	if we should do a retry
367  *	>0	if a fatal error
368  */
369 static int
370 sderror(unit, sc, hp, stat)
371 	int unit, stat;
372 	register struct sd_softc *sc;
373 	register struct hp_device *hp;
374 {
375 	int cond = 1;
376 
377 	sdsense[unit].status = stat;
378 	if (stat & STS_CHECKCOND) {
379 		struct scsi_xsense *sp;
380 
381 		sc_request_sense(hp->hp_ctlr, hp->hp_slave,
382 				   sc->sc_punit, sdsense[unit].sense,
383 				   sizeof(sdsense[unit].sense));
384 		sp = (struct scsi_xsense *)sdsense[unit].sense;
385 		printf("sd%d: scsi sense class %d, code %d", unit,
386 			sp->class, sp->code);
387 		if (sp->class == 7) {
388 			printf(", key %d", sp->key);
389 			if (sp->valid)
390 				printf(", blk %d", *(int *)&sp->info1);
391 			switch (sp->key) {
392 			/* no sense, try again */
393 			case 0:
394 				cond = -1;
395 				break;
396 			/* recovered error, not a problem */
397 			case 1:
398 				cond = 0;
399 				break;
400 			}
401 		}
402 		printf("\n");
403 	}
404 	return(cond);
405 }
406 
407 /*
408  * Interrupt
409  */
410 
411 int
412 sdintr(unit, stat)
413 	register int unit;
414 	int stat;
415 {
416 	register struct sd_softc *sc = &sd_softc[unit];
417 	register struct hp_device *hp = sc->sc_hd;
418 	register struct scsi_queue *dq = &sc->sc_dq;
419 	register struct buf *bp = dq->dq_bp;
420 	int cond;
421 
422 	if (stat == SC_IO_TIMEOUT) {
423 		printf("sdintr: sd%d timeout error\n", unit, stat);
424 	}
425 
426 	if (hp->hp_dk >= 0) {
427 		dk_busy &=~ (1 << hp->hp_dk);
428 		if (stat == 0) {
429 			++dk_seek[hp->hp_dk];
430 			++dk_xfer[hp->hp_dk];
431 			dk_wds[hp->hp_dk] += bp->b_bcount >> 6;
432 		}
433 	}
434 
435 	if (bp->b_flags & B_READ) {
436 		sd_iostat[unit].imin = min(dq->dq_imin, sd_iostat[unit].imin);
437 		if (dq->dq_imax > sd_iostat[unit].imax) {
438 			sd_iostat[unit].imax = dq->dq_imax;
439 #ifdef SD_IOSTAT
440 			printf("sdintr: sd%d  INPUT	MAX = %d, MIN = %d\n",
441 			       unit, sd_iostat[unit].imax, sd_iostat[unit].imin);
442 #endif
443 		}
444 	} else {
445 		sd_iostat[unit].omin = min(dq->dq_omin, sd_iostat[unit].omin);
446 		if (dq->dq_omax > sd_iostat[unit].omax) {
447 			sd_iostat[unit].omax = dq->dq_omax;
448 #ifdef SD_IOSTAT
449 			printf("sdintr: sd%d  OUTPUT	MAX = %d, MIN = %d\n",
450 			       unit, sd_iostat[unit].omax, sd_iostat[unit].omin);
451 #endif
452 		}
453 	}
454 
455 	if (stat != 0) {
456 		if (stat > 0) {
457 #ifdef DEBUGPRINT
458 			dbgprintall();
459 			printf("\n");
460 #endif
461 			cond = sderror(unit, sc, hp, stat);
462 			if (cond) {
463 				if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
464 					sdstart(unit);
465 					return;
466 				}
467 			}
468 		} else {
469 			if (sdtab[unit].b_errcnt++ < SDRETRY) {
470 				printf("sdintr: sd%d restart IO request\n", unit);
471 				sdstart(unit);
472 				return;
473 			}
474 		}
475 		bp->b_flags |= B_ERROR;
476 		bp->b_error = EIO;
477 	}
478 
479 	sdtab[unit].b_errcnt = 0;
480 	sdtab[unit].b_actf = bp->b_actf;
481 
482 	bp->b_resid = 0;
483 
484 	biodone(bp);
485 
486 	scfree(dq);
487 
488 	if (sdtab[unit].b_actf) {
489 		sdustart(unit);
490 	} else {
491 		sdtab[unit].b_active = 0;
492 	}
493 }
494 
495 
496 /*
497  * RAW Device Routines
498  */
499 
500 int
501 sdread(dev, uio, flags)
502 	dev_t dev;
503 	struct uio *uio;
504 	int flags;
505 {
506 	register int unit = sdunit(dev);
507 
508 	return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));
509 }
510 
511 int
512 sdwrite(dev, uio, flags)
513 	dev_t dev;
514 	struct uio *uio;
515 	int flags;
516 {
517 	register int unit = sdunit(dev);
518 
519 	return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));
520 }
521 
522 int
523 sdioctl(dev, cmd, data, flag, p)
524 	dev_t dev;
525 	int cmd;
526 	caddr_t data;
527 	int flag;
528 	struct proc *p;
529 {
530 	int unit = sdunit(dev);
531 	register struct sd_softc *sc = &sd_softc[unit];
532 	register struct disklabel *lp = &sdlabel[unit];
533 	int error = 0;
534 
535 	switch (cmd) {
536 
537 	case DIOCGDINFO:
538 		*(struct disklabel *)data = *lp;
539 		break;
540 
541 	case DIOCGPART:
542 		((struct partinfo *)data)->disklab = lp;
543 		((struct partinfo *)data)->part =
544 		    &lp->d_partitions[sdpart(dev)];
545 		break;
546 
547         case DIOCWLABEL:
548         case DIOCSDINFO:
549         case DIOCWDINFO:
550 		break;
551 
552 	default:
553 		error = ENOTTY;
554 		break;
555 	}
556 	return (error);
557 }
558 
559 
560 /*
561  * Size
562  */
563 
564 int
565 sdsize(dev)
566 	dev_t dev;
567 {
568 	register int unit = sdunit(dev);
569 	register struct sd_softc *sc = &sd_softc[unit];
570 
571 	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
572 		return(-1);
573 
574 	return(sdlabel[unit].d_partitions[sdpart(dev)].p_size);
575 }
576 
577 
578 /*
579  * Dump
580  */
581 
582 int
583 sddump(dev)
584 	dev_t dev;
585 {
586 }
587 
588 /*
589  * Disk Subs
590  */
591 
592 /*
593  * Attempt to read a disk label from a device
594  * using the indicated stategy routine.
595  * The label must be partly set up before this:
596  * secpercyl and anything required in the strategy routine
597  * (e.g., sector size) must be filled in before calling us.
598  * Returns null on success and an error string on failure.
599  */
600 char *
601 sdreadlabel(dev, strat, lp)
602 	dev_t dev;
603 	int (*strat)();
604 	register struct disklabel *lp;
605 {
606 	register struct buf *bp;
607 	struct disklabel *dlp;
608 	char *msg = NULL;
609 
610 	if (lp->d_secperunit == 0)
611 		lp->d_secperunit = 0x1fffffff;
612 	lp->d_npartitions = 1;
613 	if (lp->d_partitions[0].p_size == 0)
614 		lp->d_partitions[0].p_size = 0x1fffffff;
615 	lp->d_partitions[0].p_offset = 0;
616 
617 	bp = geteblk((int)lp->d_secsize);
618 	bp->b_dev = dev;
619 	bp->b_blkno = LABELSECTOR;
620 	bp->b_bcount = lp->d_secsize;
621 	bp->b_flags = B_BUSY | B_READ;
622 	(*strat)(bp);
623 	if (biowait(bp)) {
624 		msg = "I/O error";
625 	} else {
626 		for (dlp = (struct disklabel *)bp->b_un.b_addr;
627 		     dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
628 		     dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
629 			if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
630 				if (msg == NULL)
631 					msg = "no disk label";
632 			} else if (dlp->d_npartitions > MAXPARTITIONS ||
633 				   dkcksum(dlp) != 0)
634 				msg = "disk label corrupted";
635 			else {
636 				*lp = *dlp;
637 				msg = NULL;
638 				break;
639 			}
640 		}
641 	}
642 	bp->b_flags = B_INVAL | B_AGE;
643 	brelse(bp);
644 	return (msg);
645 }
646 
647 #ifdef notyet
648 
649 /*
650  * Checksum routine for OMRON native disklabel
651  */
652 
653 #define	OMRON_LBLSIZE	512
654 
655 u_short
656 omcksum(omp)
657 	register char *omp;
658 {
659 	register u_short *start, *end;
660 	register u_short sum = 0;
661 
662 	start = (u_short *) omp;
663 	end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)];
664 	while (start < end)
665 		sum ^= *start++;
666 
667 	printf("omcksum: saved  ... 0x%s\n", hexstr(*end, 4));
668 	printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4));
669 
670 	return (sum);
671 }
672 
673 /*
674  * Write disk label back to device after modification.
675  */
676 sdwritelabel(dev, strat, lp)
677 	dev_t dev;
678 	int (*strat)();
679 	register struct disklabel *lp;
680 {
681 	struct buf *bp;
682 	struct disklabel *dlp;
683 	int labelpart;
684 	int error = 0;
685 
686 	labelpart = sdpart(dev);
687 	if (lp->d_partitions[labelpart].p_offset != 0) {
688 		if (lp->d_partitions[0].p_offset != 0)
689 			return (EXDEV);			/* not quite right */
690 		labelpart = 0;
691 	}
692 
693 	bp = geteblk((int)lp->d_secsize);
694 	bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart));
695 	bp->b_blkno = LABELSECTOR;
696 	bp->b_bcount = lp->d_secsize;
697 	bp->b_flags = B_READ;
698 	(*strat)(bp);
699 	if (error = biowait(bp))
700 		goto done;
701 
702 	for (dlp = (struct disklabel *)bp->b_un.b_addr;
703 	    dlp <= (struct disklabel *)
704 	      (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
705 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
706 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
707 		    dkcksum(dlp) == 0) {
708 			omcksum(bp->b_un.b_addr);
709 /*
710 			*dlp = *lp;
711 			bp->b_flags = B_WRITE;
712 			(*strat)(bp);
713 			error = biowait(bp);
714 			goto done;
715  */
716 		}
717 	}
718 	error = ESRCH;
719 done:
720 	brelse(bp);
721 	return (error);
722 }
723 #endif
724 
725 #endif
726