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