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