xref: /original-bsd/sys/news3400/iodev/sd.c (revision a6d8c59f)
1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7  *
8  * %sccs.include.redist.c%
9  *
10  * from: $Hdr: sd.c,v 4.300 91/06/27 20:42:56 root Rel41 $ SONY
11  *
12  *	@(#)sd.c	7.3 (Berkeley) 12/17/92
13  */
14 #define	dkblock(bp)	bp->b_blkno
15 
16 /*
17  * Copyright (c) 1987-1991 by SONY Corporation.
18  */
19 
20 #include "sd.h"
21 #if NSD > 0
22 
23 #include <machine/fix_machine_type.h>
24 
25 #include <sys/param.h>
26 #include <sys/buf.h>
27 #include <sys/proc.h>
28 #include <sys/user.h>
29 #include <sys/dkstat.h>
30 #include <sys/uio.h>
31 #include <sys/kernel.h>
32 #include <sys/reboot.h>
33 #include <sys/ioctl.h>
34 #include <sys/systm.h>
35 #include <sys/mtio.h>
36 #include <sys/stat.h>
37 #include <sys/disklabel.h>
38 #include <vm/vm.h>
39 #include <sys/syslog.h>
40 
41 #include <ufs/ffs/fs.h>
42 
43 # include <machine/cpu.h>
44 
45 #ifdef IPC_MRX
46 # include "../iop/iopvar.h"
47 # include "../ipc/newsipc.h"
48 #endif
49 
50 #ifdef CPU_SINGLE
51 # include <news3400/hbdev/hbvar.h>
52 # include <news3400/iodev/ioptohb.h>
53 #endif
54 
55 #include <news3400/iodev/scsireg.h>
56 #include <news3400/iodev/scu.h>
57 #include <news3400/iodev/dkio.h>
58 #include <news3400/iodev/sdreg.h>
59 /* #ifdef DISKINFO KU:XXX */
60 #include <news3400/iodev/diskinfo.h>
61 /* #endif /* DISKINFO */
62 
63 #define	sce_sdecode	sce_hdecode
64 
65 #define	dev2unit(x)	((minor(x) & ~0x80) >> 3)
66 #define	dev2part(x)	(minor(x) & 0x7)
67 
68 /* /sys/sys/file.h */
69 #define	FREAD		00001		/* descriptor read/receive'able */
70 #define	FWRITE		00002		/* descriptor write/send'able */
71 
72 #define	PART_A		0
73 #define	PART_B		1
74 #define	PART_C		2
75 #define	PART_D		3
76 #define	PART_E		4
77 #define	PART_F		5
78 #define	PART_G		6
79 #define	PART_H		7
80 
81 #define	MAXPROBERETRY	100
82 #define	NRETRY		10
83 #define	MAXHRDERR	100
84 #define	MAXRETRYCNT	16
85 
86 #define	SDBSIZE1K	(DEV_BSIZE * 2)
87 #define	MAXSDPHYS	((NSCMAP - 1) * NBPG)
88 
89 #define	D100MSEC	100000
90 
91 #if OD_STOPTIME < 1
92 # define	OD_STOPTIME	5
93 #endif /* OD_STOPTIME < 1 */
94 
95 #define FORMAT_MODE_CORRUPTED	0x31
96 #define	ONLY_ONE	1
97 
98 /************** PARTITIONS *************************************/
99 
100 #define	PART_UNUSED	(0)
101 #define	PART_SPEC	(-1)
102 #define	PART_CALCF	(-2)
103 #define	PART_CALCG	(-3)
104 
105 struct defpart {
106 	int range_min;
107 	int range_max;
108 	int partsize[PNUM];
109 };
110 
111 struct defpart defpart_std[] = {
112 	{
113 		0,		/* range_min */
114 		20,		/* range_max */
115 
116 		  PART_SPEC,		/* A: */
117 		PART_UNUSED,		/* B: */
118 		  PART_SPEC,		/* C: */
119 		PART_UNUSED,		/* D: */
120 		PART_UNUSED,		/* E: */
121 		PART_UNUSED,		/* F: */
122 		PART_UNUSED,		/* G: */
123 		PART_UNUSED,		/* H: */
124 	},
125 	{
126 		20,		/* range_min */
127 		61,		/* range_max */
128 
129 		      15884,		/* A: */
130 		      10032,		/* B: */
131 		  PART_SPEC,		/* C: */
132 		      15884,		/* D: */
133 		PART_UNUSED,		/* E: */
134 		 PART_CALCF,		/* F: */
135 		 PART_CALCG,		/* G: */
136 		PART_UNUSED,		/* H: */
137 	},
138 	{
139 		61,		/* range_min */
140 		206,		/* range_max */
141 
142 		      15884,		/* A: */
143 		      33440,		/* B: */
144 		  PART_SPEC,		/* C: */
145 		      15884,		/* D: */
146 		      55936,		/* E: */
147 		 PART_CALCF,		/* F: */
148 		 PART_CALCG,		/* G: */
149 		PART_UNUSED,		/* H: */
150 	},
151 	{
152 		206,		/* range_min */
153 		356,		/* range_max */
154 
155 		      15884,		/* A: */
156 		      33440,		/* B: */
157 		  PART_SPEC,		/* C: */
158 		      15884,		/* D: */
159 		      55936,		/* E: */
160 		 PART_CALCF,		/* F: */
161 		 PART_CALCG,		/* G: */
162 		     291346,		/* H: */
163 	},
164 	{
165 		356,		/* range_min */
166 		99999999,	/* range_max */
167 
168 		      15884,		/* A: */
169 		      66880,		/* B: */
170 		  PART_SPEC,		/* C: */
171 		      15884,		/* D: */
172 		     307200,		/* E: */
173 		 PART_CALCF,		/* F: */
174 		 PART_CALCG,		/* G: */
175 		     291346,		/* H: */
176 	},
177 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
178 };
179 
180 
181 
182 /************* ADDITIONAL SENSE ERROR CODES *************************/
183 
184 struct msg_list {
185 	int	ml_code;		/* message code */
186 	int	ml_msglvl;		/* message level */
187 	char	*ml_msgstr;		/* message string */
188 };
189 
190 #define	sdskeylist	skeylist
191 
192 struct msg_list ecodelist_mo[] = {
193 	{ 0x80, 0, NULL },
194 	{ 0x81, 0, NULL },
195 	{ 0x82, 0, NULL },
196 	{ 0x83, 0, NULL },
197 
198 	{ -1,   0, NULL }
199 };
200 
201 /************** Ref. sd_var.c ********************************/
202 
203 extern struct iop/**/_ctlr *sdminfo[];
204 extern struct iop/**/_device *sddinfo[];
205 extern struct iop/**/_device *sdip[][MAXSLAVE];
206 
207 extern struct buf rsdbuf[];		/* buffer for raw I/O */
208 extern struct buf csdbuf[];		/* buffer for controll */
209 extern struct buf sdutab[];		/* per drive buffers */
210 
211 extern struct sdc_softc sdc_softc[];
212 extern struct sdd_softc sdd_softc[];
213 extern u_char sd_b_openf[][PNUM];
214 extern u_char sd_c_openf[][PNUM];
215 
216 extern struct scsi kernscsi[];
217 extern struct sdst sdstdrv[];
218 extern struct disklabel sdlabel[];
219 extern struct size sdsizedrv[][PNUM];
220 
221 extern u_char sdc_rsense[][RSEN_CNT];
222 
223 extern struct sync_param sd_sync_param[];
224 
225 extern int nsd;
226 extern int nsdc;
227 
228 /************** Ref. sddefs.c *********************************/
229 
230 extern struct sddevinfo sddevinfo[];
231 
232 /**************************************************************/
233 
234 extern struct msg_list skeylist[];
235 extern struct msg_list ecodelist[];
236 
237 extern int	boothowto;
238 extern int	rsense_msg_disp;	/* RSENSE-message display flag */
239 extern int	mo_disp_format;		/* MO format mode display flag */
240 
241 int sd_ignore_error;
242 
243 static int re_init_done;
244 
245 static u_char sdwork[2340];		/* buffer for error recovery */
246 static u_char sdtmp[DEV_BSIZE];		/* buffer for temporary */
247 #ifdef mips
248 volatile static int sdtmp_stat = 0;	/* status of sdtmp */
249 #else
250 static int sdtmp_stat = 0;		/* status of sdtmp */
251 #endif
252 
253 char	pname[] = "abcdefgh";
254 
255 struct scsi *get_scsi();
256 struct sc_map *get_sc_map();
257 struct sc_inq *get_sc_inq();
258 
259 int	sdprobe(), sdslave(), sdattach(), sddgo(), sdintr();
260 int	sdwstart, sdwatch(), sdstop();	/* Have started guardian */
261 void	sdexec();
262 
263 static sd_check(), sd_tstdrv(), sd_other_pages(), sd_err_rcv(), sd_synctr_on();
264 static disklabel2sdst(), sdst2disklabel(), sd_scu_exec();
265 
266 #ifdef CPU_SINGLE
267 struct hb_driver sdcdriver =
268     {sdprobe, sdslave, sdattach, sddgo, sdintr, "sd", sddinfo, "sdc", sdminfo};
269 #else
270 struct iop_driver sdcdriver =
271     {sdprobe, sdslave, sdattach, sddgo, "sd", sddinfo, "sdc", sdminfo};
272 #endif
273 
274 /*ARGSUSED*/
275 sdprobe(im)
276 	struct iop/**/_ctlr *im;
277 {
278 	static int sdd_init = 0;
279 	register struct sc_inq *sci;
280 	register int ctlr;
281 	register int fw;
282 	int i;
283 
284 	if (sdd_init == 0) {
285 		sdd_init++;
286 		for (i = 0; i < nsd; i++)
287 			sdd_softc[i].sdd_start = -2;
288 	}
289 
290 	sci = get_sc_inq(im->im_intr);
291 	ctlr = im->im_ctlr;
292 	/*
293 	 * Check device type
294 	 *	0x00: Direct access device.
295 	 *	0x01: Sequential access device.
296 	 *	0x04: Write-once read-multiple device.
297 	 *	0x05: Read-only Direct-access device.
298 	 *	0x7f: Specified device is nonexistent.
299 	 */
300 	fw = sdc_softc[ctlr].sdc_firmware & ~SDCFW_DEVMASK;
301 
302 	switch (sci->sci_devtype) {
303 
304 	case 0x00:
305 		/*
306 		 * Assumed that the device is HD.
307 		 *	Later, distinguish MO from HD.
308 		 */
309 		sdc_softc[ctlr].sdc_firmware = fw | SDCFW_HD;
310 		break;
311 
312 	default:
313 		/*
314 		 * device type mis-match
315 		 */
316 		return (0);
317 	}
318 
319 	/*
320 	 * Set interrupt handler routine
321 	 */
322 	if (set_inthandler(im, sdintr) == 0)
323 		return (0);
324 
325 	return (1);
326 }
327 
328 
329 /*ARGSUSED*/
330 sdslave(ii, reg, intr)
331 	register struct iop/**/_device *ii;
332 	caddr_t reg;
333 	int intr;
334 {
335 	register struct scsi *sc;
336 
337 	sc = get_scsi(intr);
338 	sdip[ii->ii_ctlr][ii->ii_slave] = ii;
339 	ii->ii_intr = intr;
340 
341 	/*
342 	 * check what the device is.
343 	 */
344 	if ((ii->ii_type = sd_check(ii, sc)) < 0)
345 		goto bad_slave;
346 
347 	/*
348 	 * set up ERROR RECOVERY PARAMETERS
349 	 */
350 	if (sd_err_rcv(ii, sc) < 0)
351 		goto bad_slave;
352 
353 	/*
354 	 * set up OTHER PARAMETERS
355 	 */
356 	if (sd_other_pages(ii, sc) < 0)
357 		goto bad_slave;
358 
359 	/*
360 	 * set up Synchronous Transfer
361 	 */
362 	sd_synctr_on(ii, sc);
363 
364 	return (1);
365 
366 bad_slave:
367 	/*
368 	 * no such slave
369 	 */
370 	ii->ii_intr = -1;
371 	return (0);
372 }
373 
374 identity_check(sci, capacity, unit)
375 	register struct sc_inq *sci;
376 	int capacity;
377 	int unit;
378 {
379 	register struct sddevinfo *sdi;
380 	register u_char *id_name;
381 	register int index;
382 	register int i;
383 	int id_pass;
384 
385 	id_name = sci->sci_vendid;
386 	while (*id_name == ' ')
387 		id_name++;
388 
389 	index = UNKNOWN_DISK;
390 	id_pass = 0;
391 	for (sdi = sddevinfo; sdi->id_len >= 0; sdi++) {
392 		/*
393 		 * check vendor & product ID
394 		 */
395 		if (strncmp(id_name, sdi->id_name, sdi->id_len) != 0)
396 			continue;
397 		id_pass = sdi - sddevinfo;
398 
399 		/*
400 		 * check revision
401 		 */
402 		if (strncmp(sdi->revs, sci->sci_revision, 4) == 0)
403 			index = id_pass;
404 		else {
405 			for (i = 0; i < 4; i++) {
406 				if (*(sdi->revs + i) == '?')
407 					continue;
408 				if (*(sdi->revs + i) != sci->sci_revision[i])
409 					break;
410 			}
411 			if (i < 4)
412 				continue;
413 		}
414 
415 		/*
416 		 * check capacity
417 		 */
418 		if (capacity == -1)
419 			break;
420 		if (sdi->capacity == -1) {
421 			printf("sd%d: capacity=0x%x(%d)\n",
422 				unit, capacity, capacity);
423 			break;
424 		}
425 		if (capacity == sdi->capacity)
426 			break;
427 	}
428 	if (index == 0)
429 		index = id_pass;
430 
431 	return (index);
432 }
433 
434 search_index(type)
435 	register int type;
436 {
437 	register struct sddevinfo *sdi;
438 	register int i;
439 	int index;
440 
441 	index = UNKNOWN_DISK;
442 	i = 0;
443 	for (sdi = sddevinfo; sdi->id_len > 0; sdi++) {
444 		if (sdi->type == type) {
445 			index = i;
446 			break;
447 		}
448 		i++;
449 	}
450 	return (index);
451 }
452 
453 static
454 sd_check(ii, sc)
455 	register struct iop/**/_device *ii;
456 	register struct scsi *sc;
457 {
458 	register struct sc_inq *sci;
459 	register struct sc_rcap *scr;
460 	register int intr;
461 	register int slave;
462 	register int unit;
463 	struct sdc_softc *sdc;
464 	struct sdd_softc *sdd;
465 	struct sc_extnd *sce;
466 	int retrycnt;
467 	int index;
468 	int media_in;
469 
470 	intr = ii->ii_intr;
471 	slave = ii->ii_slave;
472 	unit = ii->ii_unit;
473 	sdc = &sdc_softc[ii->ii_ctlr];
474 	sdd = &sdd_softc[unit];
475 	scr = (struct sc_rcap *)sc->sc_param;
476 	sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
477 
478 	/*
479 	 * check if the logical unit is ready.
480 	 *	(by TEST UNIT READY command)
481 	 */
482 	media_in = sd_tstdrv(ii, sc);
483 	if (media_in < 0)
484 		return (-3);
485 
486 	/*
487 	 * Get controller and drive information.
488 	 *	(by INQUIRY command)
489 	 */
490 	retrycnt = 0;
491 	sci = get_sc_inq(intr);
492 loop_inq:
493 	if (retrycnt++ > MAXPROBERETRY)
494 		return (-1);
495 
496 	scop_inquiry(intr, sc, slave, SCSI_INTDIS, sizeof(struct sc_inq), sci);
497 	sc->sc_tstatus &= TGSTMASK;
498 
499 	if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) {
500 
501 		bzero((caddr_t)sce, RSEN_CNT);
502 		scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT,
503 				(caddr_t)sce);
504 		sc->sc_tstatus &= TGSTMASK;
505 		if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD)
506 			return (-1);
507 		if (sce->sce_extend != 0x70)
508 			goto loop_inq;
509 
510 		switch (sce->sce_sdecode) {
511 
512 		case 0x04:	/* Drive Not Ready */
513 		case 0x28:	/* Medium Changed */
514 		case 0x29:	/* Power On or Reset or Bus Device Reset */
515 		case 0x2a:	/* Mode Select Parameter Changed */
516 			break;
517 
518 		default:
519 			return (-1);
520 		}
521 		DELAY(D100MSEC);		/* wait 100 ms. */
522 		goto loop_inq;
523 	}
524 
525 	index = identity_check(sci, -1, unit);
526 
527 	switch (sddevinfo[index].type) {
528 
529 	case SMO_S501:
530 	case SMO_S501_ISO:
531 	case SMO_S501_ISO2:
532 		sdc->sdc_firmware =
533 			SDCFW_MO | (sdc->sdc_firmware & ~SDCFW_DEVMASK);
534 		break;
535 
536 	defaults:
537 		break;
538 	}
539 
540 	if (sci->sci_qual & 0x80) {
541 		/*
542 		 * removable medium device
543 		 */
544 		sdc->sdc_firmware |= SDCFW_RMB;
545 		if ((media_in == 0) || ((sdc->sdc_firmware & SDCFW_MO) == 0))
546 			return (index);
547 	}
548 
549 	/****************/
550 	/* HD & MO only */
551 	/****************/
552 	/*
553 	 * Get drive capacity
554 	 *	(by READ CAPACITY command)
555 	 */
556 	retrycnt = 0;
557 loop_rcap:
558 	if (retrycnt++ > MAXPROBERETRY)
559 		return (-4);
560 
561 	scop_rcap(intr, sc, slave, SCSI_INTDIS, 8, (caddr_t)0);
562 	sc->sc_tstatus &= TGSTMASK;
563 	if (sc->sc_istatus != INST_EP)
564 		return (-5);
565 	if (sc->sc_tstatus == TGST_CC) {
566 		bzero((caddr_t)sce, RSEN_CNT);
567 		scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT,
568 				(caddr_t)sce);
569 		sc->sc_tstatus &= TGSTMASK;
570 		if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD)
571 			return (-6);
572 		if (sderrordisp((caddr_t)sce, ii) == FORMAT_MODE_CORRUPTED) {
573 			scr->scr_nblock = 0;
574 			scr->scr_blocklen = DEV_BSIZE;
575 			sdd->sdd_flags |= SDDF_NONFMT;
576 		} else {
577 			DELAY(D100MSEC);		/* wait 100 ms. */
578 			goto loop_rcap;
579 		}
580 	}
581 	else if (sc->sc_tstatus != TGST_GOOD) {
582 		DELAY(D100MSEC);		/* wait 100 ms. */
583 		goto loop_rcap;
584 	}
585 
586 	sdd->sdd_nsect = scr->scr_nblock + 1;
587 	sdd->sdd_sectsize = scr->scr_blocklen;
588 
589 	index = identity_check(sci, scr->scr_nblock +1, unit);
590 
591 	return (index);
592 }
593 
594 static
595 sd_tstdrv(ii, sc)
596 	register struct iop/**/_device *ii;
597 	register struct scsi *sc;
598 {
599 	register struct sc_extnd *sce;
600 	register int intr;
601 	register int slave;
602 	register int retrycnt;
603 	struct sdc_softc *sdc;
604 	struct sdd_softc *sdd;
605 
606 	sdc = &sdc_softc[ii->ii_ctlr];
607 	sdd = &sdd_softc[ii->ii_unit];
608 
609 	intr = ii->ii_intr;
610 	slave = ii->ii_slave;
611 	sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
612 	retrycnt = 0;
613 loop_tst:
614 	if (retrycnt++ > MAXPROBERETRY)
615 		return (-1);
616 
617 	scop_tst(intr, sc, slave, SCSI_INTDIS);
618 	sc->sc_tstatus &= TGSTMASK;
619 	if (sc->sc_istatus != INST_EP) {
620 		DELAY(D100MSEC);		/* wait 100 ms. */
621 		goto loop_tst;
622 	}
623 
624 	switch (sc->sc_tstatus) {
625 
626 	case TGST_CC:
627 		/* Get error code */
628 		bzero((caddr_t)sce, RSEN_CNT);
629 		scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT,
630 				(caddr_t)sce);
631 		sc->sc_tstatus &= TGSTMASK;
632 		if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) {
633 			DELAY(D100MSEC);	/* wait 100 ms. */
634 			goto loop_tst;
635 		}
636 
637 		if (sce->sce_extend != 0x70)
638 			goto loop_tst;
639 
640 		switch (sce->sce_skey) {
641 
642 		case 0x0:		/* No Sense */
643 		case 0x4:		/* Hardware error */
644 		case 0x6:		/* Unit attention */
645 			goto loop_tst;
646 
647 		case 0x2:		/* Not ready */
648 			switch (sce->sce_sdecode) {
649 
650 			case 0x04:	/* Not ready */
651 				/*
652 				 * Drive not ready... so start..
653 				 */
654 				scop_stst(intr, sc, slave, SCSI_INTDIS, SDSS_START);
655 				DELAY(D100MSEC * 10);	/* wait 1 sec. */
656 				goto loop_tst;
657 
658 			case 0x0a:	/* No Disk *//*MO*/
659 			default:
660 				DELAY(D100MSEC);
661 				goto loop_tst;
662 			}
663 			break;
664 
665 		case 0x03:
666 			if (sce->sce_sdecode == FORMAT_MODE_CORRUPTED)
667 				return (1);	/* ignore error */
668 			/* fall through */
669 
670 		default:
671 			return (-2);
672 		}
673 		break;
674 
675 	case TGST_BUSY:
676 		goto loop_tst;
677 
678 	case TGST_GOOD:
679 		break;
680 
681 	default:
682 		return (-3);
683 	}
684 
685 	return (1);
686 }
687 
688 #ifdef NEWSOS4
689 static
690 sd_setup_cmds(ii, sc)
691 	register struct iop/**/_device *ii;
692 	register struct scsi *sc;
693 {
694 	register struct sddevinfo *sdi;
695 	register struct sc_extnd *sce;
696 	struct sc_ureq **p;
697 	struct sc_ureq *scu;
698 	int error;
699 	extern struct sc_ureq scu_rsense;
700 
701 	if ((p = sddevinfo[ii->ii_type].setup_cmds) == NULL)
702 		return (0);
703 
704 	/*
705 	 * Do setup commands
706 	 */
707 	while (scu = *p) {
708 		bcopy((caddr_t)scu, sdtmp, sizeof(struct sc_ureq));
709 		scu = (struct sc_ureq *)sdtmp;
710 		scu->scu_cdb[1] |= (ii->ii_slave & 0x07) << 5;
711 		error = sd_scu_exec((ii->ii_unit << 3), scu, sc);
712 		if (error != 0)
713 			return (-1);
714 		if ((scu->scu_istatus != INST_EP)
715 		    || (scu->scu_tstatus != TGST_GOOD)) {
716 			bcopy((caddr_t)&scu_rsense, sdtmp, sizeof(struct sc_ureq));
717 			scu = (struct sc_ureq *)sdtmp;
718 			scu->scu_cdb[1] |= (ii->ii_slave & 0x07) << 5;
719 			sce = (scu->scu_addr == NULL) ?
720 				(struct sc_extnd *)scu->scu_param :
721 				(struct sc_extnd *)scu->scu_addr;
722 			if (sd_scu_exec((ii->ii_unit << 3), scu, sc) == 0) {
723 				/* UNIT ATTENTION */
724 				/* retry same command */
725 				if (sce->sce_skey == 0x06)
726 					continue;
727 			}
728 		}
729 		p++;
730 	}
731 	return (1);
732 }
733 #endif /* NEWSOS4 */
734 
735 static
736 sd_other_pages(ii, sc)
737 	register struct iop/**/_device *ii;
738 	register struct scsi *sc;
739 {
740 	register struct sddevinfo *sdi;
741 	char **p;
742 	char *page;
743 	int length;
744 	int retrycnt;
745 	int len;
746 
747 	sdi = &sddevinfo[ii->ii_type];
748 	if ((p = sdi->other_pages) == NULL)
749 		return (0);
750 
751 	/*
752 	 * set other parameters
753 	 */
754 	while (page = *p++) {
755 		retrycnt = 0;
756 loop_other_pages:
757 		bzero((caddr_t)sdtmp, 4);
758 		length = *(page + 1) + 2;
759 		bcopy(page, &sdtmp[4], length);
760 		if (retrycnt++ > MAXPROBERETRY)
761 			return (-1);
762 
763 		scop_mselect(ii->ii_intr, sc, ii->ii_slave, SCSI_INTDIS,
764 				(SDM_PF<<24) + length +4, (caddr_t)sdtmp);
765 		sc->sc_tstatus &= TGSTMASK;
766 		if ((sc->sc_istatus != INST_EP)
767 				|| (sc->sc_tstatus != TGST_GOOD)) {
768 			struct sc_extnd *sce;
769 
770 			sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
771 			scop_rsense(ii->ii_intr, sc, ii->ii_slave, SCSI_INTDIS,
772 						RSEN_CNT, (caddr_t)sce);
773 			switch (sce->sce_skey) {
774 
775 			case 0x00:
776 			case 0x02:
777 			case 0x04:
778 			case 0x06:
779 				DELAY(D100MSEC);   /* 100 ms. */
780 				goto loop_other_pages;
781 
782 			default:
783 				return (-1);
784 			}
785 		}
786 	}
787 
788 	if (sdi->firm_flags & FIRM_CACHE_ON)
789 		sdc_softc[ii->ii_ctlr].sdc_firmware |= SDCFW_CACHE;
790 	else
791 		sdc_softc[ii->ii_ctlr].sdc_firmware &= ~SDCFW_CACHE;
792 
793 	return (1);
794 }
795 
796 static
797 sd_err_rcv(ii, sc)
798 	register struct iop/**/_device *ii;
799 	register struct scsi *sc;
800 {
801 	register struct sdc_softc *sdc;
802 	register int intr;
803 	register int slave;
804 	register int len;
805 	struct sc_extnd *sce;
806 	struct sdd_softc *sdd;
807 	struct sddevinfo *sdi;
808 	int retrycnt;
809 	char *erp_page;
810 
811 	intr = ii->ii_intr;
812 	slave = ii->ii_slave;
813 	sdc = &sdc_softc[ii->ii_ctlr];
814 	sdd = &sdd_softc[ii->ii_unit];
815 	sdi = &sddevinfo[ii->ii_type];
816 	sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
817 
818 	/*
819 	 * set Default DISK sector size
820 	 */
821 	if (sdd->sdd_sectsize == 0)
822 		sdd->sdd_sectsize = DEV_BSIZE;
823 
824 
825 	if (sdi->ERP_page == NULL) {
826 		/*
827 		 * use default error recovery parameters
828 		 */
829 		sdc->sdc_firmware |= SDCFW_DEFMODE;
830 		return (0);
831 	}
832 
833 	if (sdi->firm_flags & FIRM_AWRE)
834 		sdc->sdc_firmware |= SDCFW_AWRE;
835 	if (sdi->firm_flags & FIRM_ARRE)
836 		sdc->sdc_firmware |= SDCFW_ARRE;
837 	/*
838 	 * set ERROR RECOVERY PARAMETERS
839 	 */
840 loop_err_rcv:
841 	bzero((caddr_t)sdtmp, 4);
842 	erp_page = sdi->ERP_page;
843 	len = *(erp_page + 1) + 2;
844 	bcopy(erp_page, &sdtmp[4], len);
845 
846 	scop_mselect(intr, sc, slave, SCSI_INTDIS,
847 			(SDM_PF<<24) + len +4, (caddr_t)sdtmp);
848 	sc->sc_tstatus &= TGSTMASK;
849 	if (sc->sc_istatus != INST_EP || sc->sc_tstatus != TGST_GOOD) {
850 		if (sc->sc_tstatus == TGST_CC) {
851 			bzero((caddr_t)sce, RSEN_CNT);
852 			scop_rsense(intr, sc, slave, SCSI_INTDIS, RSEN_CNT,
853 					(caddr_t)sce);
854 			if (sce->sce_sdecode == 0x2a) {
855 				/* mode select parameter changed */
856 				goto ercv_done;
857 			} else if (sce->sce_skey == 0x6) {
858 				/* unit attention */
859 				goto loop_err_rcv;
860 			}
861 		}
862 		/*
863 		 * use default ERROR RECOVERY mode
864 		 */
865 		sdc->sdc_firmware |= SDCFW_DEFMODE;
866 		sdc->sdc_firmware &= ~(SDCFW_AWRE|SDCFW_ARRE);
867 	}
868 
869 ercv_done:
870 
871 	return (1);
872 }
873 
874 static
875 sd_synctr_on(ii, sc)
876 	register struct iop/**/_device *ii;
877 	register struct scsi *sc;
878 {
879 	register struct sddevinfo *sdi;
880 	register struct sync_param *syncp;
881 
882 	sdi = &sddevinfo[ii->ii_type];
883 
884 	if (sdi->firm_flags & FIRM_SYNCTR) {
885 		scinit(sc, ii->ii_slave, DEV_BSIZE);
886 		sc->sc_opcode = SCOP_TST;
887 		sc->sc_message = MSG_EXTND;	/* extended message */
888 		sc->sc_param[0] = MSG_EXTND;
889 		sc->sc_param[1] = 0x03;
890 		sc->sc_param[2] = 0x01;		/* synchronous transfer */
891 		sc->sc_param[3] = sdi->tr_period;	/* transfer period */
892 		sc->sc_param[4] = sdi->tr_offset;	/* REQ offset */
893 
894 		if (sdc_softc[ii->ii_ctlr].sdc_firmware & SDCFW_CACHE)
895 			sc->sc_tstatus |= TS_CONTR_ON;	/* contiguous TR ON */
896 		else
897 			sc->sc_tstatus |= TS_CONTR_OFF;	/* contiguous TR OFF */
898 
899 #ifdef news1800
900 		if (scsi_berr_bug() != 0) {
901 			sc->sc_tstatus &= ~TS_CONTR_ON;
902 			sc->sc_tstatus |= TS_CONTR_OFF;
903 		}
904 #endif
905 
906 		if (sc->sc_tstatus & TS_CONTR_OFF)
907 			sdc_softc[ii->ii_ctlr].sdc_firmware &= ~SDCFW_CONTR;
908 		else
909 			sdc_softc[ii->ii_ctlr].sdc_firmware |= SDCFW_CONTR;
910 
911 		sc_go(ii->ii_intr, sc, SCSI_INTDIS);
912 
913 		syncp = &sd_sync_param[ii->ii_unit];
914 		syncp->tr_period = sc->sc_param[3];
915 		syncp->tr_offset = sc->sc_param[4];
916 		if (sc->sc_param[4])
917 			sdd_softc[ii->ii_unit].sdd_flags |= SDDF_SYNCTR;
918 	}
919 }
920 
921 
922 sdattach(ii)
923 	register struct iop/**/_device *ii;
924 {
925 	register int unit;
926 	register int i;
927 	struct sdc_softc *sdc;
928 	struct sdd_softc *sdd;
929 	int dummy;
930 
931 	sdc = &sdc_softc[ii->ii_ctlr];
932 	sdc->sdc_timeo = 60;			/* timeout 60 sec */
933 
934 	unit = ii->ii_unit;
935 	sdd = &sdd_softc[unit];
936 	sdd->sdd_stoptime = OD_STOPTIME;	/* REMOVABLE MEDIA */
937 	sdd->sdd_start = -2;
938 
939 	sdmaptype(ii);
940 
941 	if (sdwstart == 0) {
942 		sdwstart++;
943 		timeout(sdwatch, (caddr_t)0, hz);
944 		timeout(sdstop, (caddr_t)0, hz);
945 	}
946 
947 #ifdef NEWSOS4
948 	/*
949 	 * Do setup commands
950 	 */
951 	if (sd_setup_cmds(ii, get_scsi(ii->ii_intr)) < 0)
952 		printf("sd%d: setup failure\n", ii->ii_unit);
953 #endif
954 
955 	/*
956 	 * initialize open flag
957 	 */
958 	for (i = 0; i < PNUM; i++) {
959 		sd_b_openf[unit][i] = 0;
960 		sd_c_openf[unit][i] = 0;
961 	}
962 
963 	if (re_init_done > 0)
964 		return;
965 
966 	if (sdc->sdc_firmware & SDCFW_HD) {
967 		/*
968 		 * If device is Hard Disk,
969 		 *	then get partition information.
970 		 */
971 		sdrpartinfo(ii);
972 		dummy = DEV_BSIZE * sdstdrv[unit].rps * sdstdrv[unit].nsect;
973 	} else
974 		dummy = DEV_BSIZE * 40 * 31;
975 
976 	if (ii->ii_dk >= 0 && dummy)
977 		dk_wpms[ii->ii_dk] = dummy / (2 * 1000000);
978 }
979 
980 sdmaptype(ii)
981 	register struct iop/**/_device *ii;
982 {
983 	printf("sd%d: %s\n", ii->ii_unit, sddevinfo[ii->ii_type].call_name);
984 }
985 
986 int sd_b_major = -1;
987 
988 sd_b_open(dev, flag)
989 	dev_t dev;
990 	int flag;
991 {
992 	sd_b_major = major(dev);
993 	return (_sdopen(dev, flag, S_IFBLK));
994 }
995 
996 int sd_c_major = -1;
997 
998 sd_c_open(dev, flag)
999 	dev_t dev;
1000 	int flag;
1001 {
1002 	sd_c_major = major(dev);
1003 	return (_sdopen(dev, flag, S_IFCHR));
1004 }
1005 
1006 _sdopen(dev, flag, fmt)
1007 	register dev_t dev;
1008 	int flag;
1009 	int fmt;
1010 {
1011 	register struct iop/**/_device *ii;
1012 	register struct sdd_softc *sdd;
1013 	register struct sdc_softc *sdc;
1014 	register struct sddevinfo *sdi;
1015 	register int unit;
1016 	register int i;
1017 	u_char *sdopfp;
1018 	u_char	old_sdopf;
1019 	int media_changed;
1020 	int s;
1021 	int stat;
1022 	struct scsi uscsi;
1023 
1024 	unit = dev2unit(dev);
1025 	if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
1026 		return (ENXIO);
1027 
1028 	sdd = &sdd_softc[unit];
1029 	sdc = &sdc_softc[ii->ii_ctlr];
1030 	sdi = &sddevinfo[ii->ii_type];
1031 
1032 	if (sdd->sdd_flags & SDDF_XUSE)
1033 		return (EBUSY);
1034 
1035 	/*
1036 	 * LOCK while sdstop() running.
1037 	 */
1038 	s = splclock();
1039 	while (sdc->sdc_state & SDCS_SCUNLOCK) {
1040 		sdc->sdc_state |= SDCS_OPEN_WAIT;
1041 		sleep((caddr_t)sdc, PRIBIO);
1042 	}
1043 	splx(s);
1044 
1045 	/*
1046 	 * LOCK sdtmp buffer
1047 	 */
1048 	s = splclock();
1049 	while (sdtmp_stat & B_BUSY) {
1050 		sdtmp_stat |= B_WANTED;
1051 		sleep((caddr_t)sdtmp, PRIBIO);
1052 	}
1053 	sdtmp_stat |= B_BUSY;
1054 	splx(s);
1055 	sdd->sdd_flags |= SDDF_GETTMP;
1056 
1057 	if ((fmt & S_IFMT) == S_IFBLK)
1058 		sdopfp = &sd_b_openf[unit][dev2part(dev)];
1059 	else
1060 		sdopfp = &sd_c_openf[unit][dev2part(dev)];
1061 	old_sdopf = *sdopfp;
1062 	if (old_sdopf <= 1)
1063 		*sdopfp += 1;		/* 1: 1st open (ONLY_ONE) */
1064 					/* 2: already opened */
1065 	stat = 0;
1066 	media_changed = 0;
1067 
1068 	/*
1069 	 * From here on until pre_open_done is only for removable devices
1070 	 */
1071 	if ((sdc->sdc_firmware & SDCFW_RMB) == 0)
1072 		goto pre_open_done;
1073 
1074 	if ((minor(dev) & 0x80) || (dev == rootdev))
1075 		sdd->sdd_stoptime = 0x7fffffff;		/*XXX*/
1076 
1077 	/*
1078 	 * Start Unit
1079 	 */
1080 	s = splclock();	/* inhibit clock interrupt */
1081 	i = sdd->sdd_start;
1082 	sdd->sdd_start = sdd->sdd_stoptime;
1083 	splx(s);
1084 	if (i <= 0) {
1085 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1086 		uscsi.sc_opcode = SCOP_STST;
1087 		uscsi.sc_count = SDSS_START;
1088 
1089 		if (sdcmd(dev, &uscsi)) {
1090 			sdd->sdd_start = i;
1091 			if ((flag & FWRITE) == 0)
1092 				goto sdopen_setup;
1093 			stat = EIO;
1094 			goto pre_open_done;
1095 		}
1096 	}
1097 
1098 	/*
1099 	 * prevent medium removal
1100 	 */
1101 	scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1102 	uscsi.sc_opcode = SCOP_MEDRMV;
1103 	uscsi.sc_count = SDRMV_PREV;
1104 	if (sdcmd(dev, &uscsi)) {
1105 		stat = EIO;
1106 		goto pre_open_done;
1107 	}
1108 	sdd->sdd_flags |= SDDF_INHRMV;
1109 
1110 sdopen_setup:
1111 	if ((sdd->sdd_flags & SDDF_SAMEDSK) == SDDF_DSKCHGD) {
1112 		sdd->sdd_flags |= SDDF_SAMEDSK;
1113 		media_changed = 1;
1114 
1115 		/*
1116 		 * From here on until mo_check_done is only for MO device
1117 		 */
1118 		if ((sdc->sdc_firmware & SDCFW_MO) == 0)
1119 			goto mo_check_done;
1120 
1121 		/*
1122 		 * Mode Sense
1123 		 */
1124 		bzero(sdtmp, 36);
1125 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1126 		uscsi.sc_cpoint = sdtmp;
1127 		uscsi.sc_ctrnscnt = 36;
1128 		uscsi.sc_opcode = SCOP_MSENSE;
1129 		uscsi.sc_lad = (SDM_PF << 16)|((SDM_PC_CUR|SDM_PCODE_ALL) << 8);
1130 		uscsi.sc_count = 36;
1131 
1132 		if (sdcmd(dev, &uscsi) == 0) {
1133 			/*
1134 			 * check Write Protect mode
1135 			 */
1136 			if (sdtmp[2] & 0x80)
1137 				sdd->sdd_flags |= SDDF_WPROTECT;
1138 			else
1139 				sdd->sdd_flags &= ~SDDF_WPROTECT;
1140 			/*
1141 			 * check Format Mode
1142 			 */
1143 			if (sdtmp[26] == 2) {
1144 				ii->ii_type = search_index(SMO_S501);
1145 				if (mo_disp_format)
1146 					printf("sd%d: format mode 2 (original format)\n", unit);
1147 			} else if (sdtmp[26] == 3) {
1148 				int spare;
1149 
1150 				spare = *(short *)&sdtmp[32];
1151 				if (spare == 2048)
1152 					ii->ii_type =
1153 						search_index(SMO_S501_ISO2);
1154 				else
1155 					ii->ii_type =
1156 						search_index(SMO_S501_ISO);
1157 				if (mo_disp_format)
1158 					printf("sd%d: format mode 3 (ISO format) spare=%d\n", unit, spare);
1159 			} else {
1160 				sdd->sdd_flags |= SDDF_NONFMT;
1161 				if (mo_disp_format)
1162 					printf("sd%d: Non format\n", unit);
1163 			}
1164 			sdi = &sddevinfo[ii->ii_type];
1165 		}
1166 
1167 		/*
1168 		 * Mode Select
1169 		 *	Error Recovery Parameters set
1170 		 */
1171 		i = *(sdi->ERP_page +1) + 2;	/* page length */
1172 		bzero(sdtmp, i + 4);
1173 		bcopy(sdi->ERP_page, (caddr_t)&sdtmp[4], i);
1174 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1175 		uscsi.sc_cpoint = sdtmp;
1176 		uscsi.sc_ctrnscnt = i + 4;
1177 		uscsi.sc_opcode = SCOP_MSELECT;
1178 		uscsi.sc_lad = (SDM_PF << 16);
1179 		uscsi.sc_count = i + 4;
1180 
1181 		(void) sdcmd(dev, &uscsi);
1182 
1183 		/*
1184 		 * Read Grown Defect list
1185 		 */
1186 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1187 		uscsi.sc_cpoint = sdtmp;
1188 		uscsi.sc_ctrnscnt = 4;
1189 		uscsi.sc_opcode = SCOP_RDL;
1190 		uscsi.sc_cdb.un_type1.t1_ladhi = (SDDL_GLIST|SDDL_PHYSFMT) << 8;
1191 		uscsi.sc_cdb.un_type1.t1_p3 = 4;
1192 
1193 		(void) sdcmd(dev, &uscsi);
1194 		i = *(short *)&sdtmp[2] / 8;
1195 		if (i > (1024*9/10))
1196 			printf("sd%d: WARNING: DEFECT SPARE LOCATION < 10%\n",
1197 				unit);
1198 mo_check_done:
1199 		/*
1200 		 * Read Capacity
1201 		 */
1202 		bzero((caddr_t)sdtmp, 8);
1203 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1204 		uscsi.sc_cpoint = sdtmp;
1205 		uscsi.sc_ctrnscnt = 8;
1206 		uscsi.sc_opcode = SCOP_RCAP;
1207 
1208 		(void) sdcmd(dev, &uscsi);
1209 		sdd->sdd_nsect = *(int *)&sdtmp[0] + 1;
1210 		sdd->sdd_sectsize = *(int *)&sdtmp[4];
1211 
1212 		if ((sdd->sdd_sectsize != DEV_BSIZE)
1213 				&& (sdd->sdd_sectsize != SDBSIZE1K))
1214 			sdd->sdd_sectsize = DEV_BSIZE;
1215 	}
1216 
1217 	if ((sdd->sdd_flags & SDDF_WPROTECT) && (flag & FWRITE))
1218 		stat = EROFS;
1219 
1220 pre_open_done:
1221 
1222 	if (stat == 0) {
1223 		if ((isalone(unit) == ONLY_ONE) || media_changed) {
1224 			/*
1225 			 * read partition information from sector zero.
1226 			 */
1227 			sdrpartinfo(ii);
1228 			if (ii->ii_dk >= 0) {
1229 				dk_wpms[ii->ii_dk] =
1230 					sdd->sdd_sectsize * sdstdrv[unit].rps
1231 					* sdstdrv[unit].nsect / (2 * 1000000);
1232 			}
1233 		}
1234 	} else {
1235 		/*
1236 		 * open error
1237 		 */
1238 		*sdopfp = old_sdopf;
1239 		if ((sdd->sdd_flags & SDDF_INHRMV) && (isalone(unit) == 0)) {
1240 			sdd->sdd_flags &= ~SDDF_INHRMV;
1241 			scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1242 			uscsi.sc_opcode = SCOP_MEDRMV;
1243 			uscsi.sc_count = SDRMV_ALLOW;
1244 			(void) sdcmd(dev, &uscsi);
1245 		}
1246 	}
1247 
1248 	/*
1249 	 * UNLOCK open
1250 	 */
1251 	s = splclock();
1252 	sdd->sdd_flags &= ~SDDF_GETTMP;
1253 	if (sdtmp_stat & B_WANTED)
1254 		wakeup((caddr_t)sdtmp);
1255 	sdtmp_stat &= ~(B_BUSY|B_WANTED);
1256 	splx(s);
1257 	return (stat);
1258 }
1259 
1260 int sd_access_check_on;		/* Common flags for sd_access_check() */
1261 
1262 sd_access_check(bp)
1263 	register struct buf *bp;
1264 {
1265 	register struct iop/**/_device *ii;
1266 	register struct sdd_softc *sdd;
1267 	int unit;
1268 	int check_part;
1269 	int limit;
1270 	int over;
1271 	register struct size *sizes;
1272 	register int lba;	/* logical block address */
1273 	register int sz;
1274 	register int i;
1275 
1276 	check_part = 0;
1277 	unit = dev2unit(bp->b_dev);
1278 	ii = sddinfo[unit];
1279 	sdd = &sdd_softc[unit];
1280 	sizes = sdstdrv[unit].sizes;
1281 
1282 	lba = sizes[dev2part(bp->b_dev)].sd_blkoff + dkblock(bp);
1283 	sz = howmany(bp->b_bcount, sdd->sdd_sectsize);
1284 
1285 	/*
1286 	 * When block device is used,
1287 	 *	inhibit raw device write operation.
1288 	 */
1289 	if ((major(bp->b_dev) == sd_c_major)			/* RAW I/O */
1290 	    && ((bp->b_flags & B_READ) == 0)			/* WRITE */
1291 	    && ((ii->ii_flags & SD_F_ENW) == 0)			/* INHIBIT */
1292 	    && ((sd_access_check_on & SD_F_ENW) == 0)) {
1293 
1294 		for (i = 0; i < PNUM; i++) {
1295 			if (sd_b_openf[unit][i] == 0)
1296 				continue;
1297 			/*
1298 			 *   |----|========|---|======|-------|
1299 			 * 1 |---+++--------------------------| CUT OFF
1300 			 * 2 |---++++++++++++-----------------| CUT OFF
1301 			 * 3 |---++++++++++++++++-------------| CUT OFF
1302 			 * 4 |---++++++++++++++++++++++++-----| CUT OFF
1303 			 * 5 |-------+++----------------------| ERROR
1304 			 * 6 |------------+++-----------------| ERROR
1305 			 * 7 |------------+++++++-------------| ERROR
1306 			 * 8 |------------+++++++++++++++-----| ERROR
1307 			 */
1308 			if ((lba < (sizes[i].sd_blkoff + sizes[i].sd_nblocks))
1309 			    && ((lba + sz) > sizes[i].sd_blkoff))
1310 				check_part |= (1 << i);
1311 		}
1312 	}
1313 
1314 	if (check_part) {
1315 		limit = 0x7fffffff;	/* XXX */
1316 		for (i = 0; i < PNUM; i++) {
1317 			if ((check_part & (1 << i)) == 0)
1318 				continue;
1319 
1320 			if (lba >= sizes[i].sd_blkoff) {
1321 				bp->b_flags |= B_ERROR;
1322 				bp->b_error = EIO;
1323 				bp->b_resid = bp->b_bcount;
1324 
1325 				printf("sd%d%c: RAW DEVICE WRITE PROTECTED: ",
1326 					unit, pname[dev2part(bp->b_dev)]);
1327 				printf("sn = 0x%x(%d), off = 0x%x(%d)\n",
1328 					dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize,
1329 					dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize,
1330 					sizes[dev2part(bp->b_dev)].sd_blkoff,
1331 					sizes[dev2part(bp->b_dev)].sd_blkoff);
1332 
1333 				return (-1);
1334 			}
1335 
1336 			if (sizes[i].sd_blkoff < limit)
1337 				limit = sizes[i].sd_blkoff;
1338 		}
1339 	} else {
1340 		limit = sizes[dev2part(bp->b_dev)].sd_blkoff
1341 			+ sizes[dev2part(bp->b_dev)].sd_nblocks;
1342 	}
1343 
1344 	if ((over = (lba + sz) - limit) > 0) {
1345 		/*
1346 		 * Logical Block Address is outside the valid area.
1347 		 */
1348 		if (((ii->ii_flags & SD_F_EOLBA) != 0)
1349 			|| ((sd_access_check_on & SD_F_EOLBA) != 0)) {
1350 			/*
1351 			 * error if outside LBA
1352 			 */
1353 			return(-1);
1354 		}
1355 		bp->b_resid = bp->b_bcount - (sz - over) * sdd->sdd_sectsize;
1356 		if (bp->b_resid >= bp->b_bcount) {
1357 			bp->b_resid = bp->b_bcount;
1358 			return(-1);
1359 		}
1360 	}
1361 
1362 	return (0);
1363 }
1364 
1365 sd_b_close(dev, flag)
1366 	dev_t dev;
1367 	int flag;
1368 {
1369 	return (_sdclose(dev, flag, S_IFBLK));
1370 }
1371 
1372 sd_c_close(dev, flag)
1373 	dev_t dev;
1374 	int flag;
1375 {
1376 	return (_sdclose(dev, flag, S_IFCHR));
1377 }
1378 
1379 _sdclose(dev, flag, fmt)
1380 	register dev_t dev;
1381 	int flag;
1382 	int fmt;
1383 {
1384 	register struct iop/**/_device *ii;
1385 	register struct sdd_softc *sdd;
1386 	register int unit;
1387 	struct sdc_softc *sdc;
1388 	struct scsi uscsi;
1389 	struct sc_extnd *sce;
1390 
1391 	unit = dev2unit(dev);
1392 	if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
1393 		return (ENXIO);
1394 
1395 	sdd = &sdd_softc[unit];
1396 	sdc = &sdc_softc[ii->ii_ctlr];
1397 	sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
1398 
1399 	/*
1400 	 * still remain jobs
1401 	 *	sleep about 10ms -> 1sec
1402 	 */
1403 	while (ii->ii_mi->im_tab.b_actf != NULL)
1404 		sleep((caddr_t)&lbolt, PRIBIO);
1405 
1406 	if ((fmt & S_IFMT) == S_IFBLK)
1407 		sd_b_openf[unit][dev2part(dev)] = 0;
1408 	else
1409 		sd_c_openf[unit][dev2part(dev)] = 0;
1410 	sdd->sdd_flags &= ~SDDF_XUSE;
1411 
1412 	if ((sdc->sdc_firmware & SDCFW_RMB) && (isalone(unit) == 0)) {
1413 		sdd->sdd_flags &= ~SDDF_INHRMV;
1414 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1415 		uscsi.sc_opcode = SCOP_MEDRMV;
1416 		uscsi.sc_count = SDRMV_ALLOW;
1417 		(void) sdcmd(dev, &uscsi);
1418 	}
1419 	return (0);
1420 }
1421 
1422 sdcmd(dev, usc)
1423 	dev_t dev;
1424 	struct scsi *usc;
1425 {
1426 	register struct buf *bp;
1427 	register struct scsi *ksc;
1428 	register u_char *point;
1429 	register int unit;
1430 	int error;
1431 	int s;
1432 	int cnt;
1433 
1434 	if (usc == 0)
1435 		return (ENXIO);
1436 
1437 	error = 0;
1438 	unit = dev2unit(dev);
1439 	bp = &csdbuf[unit];
1440 
1441 	/*
1442 	 * LOCK csdbuf
1443 	 */
1444 	s = splclock();
1445 	while (bp->b_flags & B_BUSY) {
1446 		bp->b_flags |= B_WANTED;
1447 		sleep((caddr_t)bp, PRIBIO);
1448 	}
1449 	bzero((caddr_t)bp, sizeof(struct buf));
1450 	bp->b_flags = B_BUSY|B_READ;
1451 	splx(s);
1452 
1453 	ksc = &kernscsi[unit];
1454 	bcopy((caddr_t)usc, (caddr_t)ksc, sizeof(struct scsi));
1455 	/*
1456 	 * setup command buffer
1457 	 */
1458 	bp->b_dev = dev;
1459 	bp->b_proc = curproc;
1460 	cnt = ksc->sc_ctrnscnt;
1461 	bp->b_bcount = cnt;
1462 
1463 	point = ksc->sc_cpoint;
1464 	bp->b_un.b_addr = (caddr_t)point;
1465 	if (cnt > 0) {
1466 		if (point == NULL) {
1467 			ksc->sc_cpoint = point = get_scsi(unit)->sc_param;
1468 			if (cnt > 20) {
1469 				error = EFAULT;
1470 				goto done;
1471 			}
1472 		}
1473 		if (point < (u_char *)KERNBASE) {
1474 			if (useracc(point, cnt, B_WRITE) == NULL) {
1475 				error = EFAULT;
1476 				goto done;
1477 			}
1478 			curproc->p_flag |= SPHYSIO;
1479 			vslock(point, cnt);
1480 			bp->b_flags |= B_PHYS;
1481 		}
1482 #ifndef mips
1483 		else {
1484 			if (kernacc(point, cnt, B_WRITE) == NULL) {
1485 				error = EFAULT;
1486 				goto done;
1487 			}
1488 		}
1489 #endif
1490 		ksc->sc_tstatus = TS_MAPPED_PIO;	/* XXX */
1491 	}
1492 
1493 	/*
1494 	 * call strategy entry, and wait command done.
1495 	 */
1496 	sdstrategy(bp);
1497 	iowait(bp);
1498 
1499 	if ((cnt > 0) && (point < (u_char *)KERNBASE)) {
1500 		vsunlock(point, cnt, B_READ);
1501 		curproc->p_flag &= ~SPHYSIO;
1502 	}
1503 	if ((bp->b_flags & B_ERROR) == 0)
1504 		error = 0;
1505 	else {
1506 		if (bp->b_error)
1507 			error = bp->b_error;
1508 		else
1509 			error = EIO;
1510 	}
1511 	bcopy((caddr_t)ksc, (caddr_t)usc, sizeof(struct scsi));
1512 
1513 done:
1514 	/*
1515 	 * UNLOCK csdbuf
1516 	 */
1517 	s = splclock();
1518 	if (bp->b_flags & B_WANTED)
1519 		wakeup((caddr_t)bp);
1520 	bp->b_flags = 0;
1521 	splx(s);
1522 	return (error);
1523 }
1524 
1525 /*
1526  * read partition information from sector zero.
1527  */
1528 sdrpartinfo(ii)
1529 	register struct iop/**/_device *ii;
1530 {
1531 	register struct disklabel *dlp;
1532 	register struct sdst *hsp;
1533 	register struct sdst *st;
1534 	register int unit;
1535 	register int i;
1536 	struct firstsector *fsp;
1537 	struct sdc_softc *sdc;
1538 	struct sdd_softc *sdd;
1539 	struct sddevinfo *sdi;
1540 #ifdef DISKINFO
1541 	struct diskinfo *dip;
1542 #endif
1543 	struct scsi uscsi;
1544 	int s;
1545 
1546 	sdi = &sddevinfo[ii->ii_type];
1547 	unit = ii->ii_unit;
1548 
1549 	sdd = &sdd_softc[unit];
1550 	sdc = &sdc_softc[ii->ii_ctlr];
1551 
1552 	if ((sdd->sdd_flags & (SDDF_NONFMT|SDDF_FMTDONE)) == 0) {
1553 		register struct sc_rcap *scr = (struct sc_rcap *)sdtmp;
1554 
1555 		sdd->sdd_flags |= SDDF_FMTDONE;
1556 
1557 		bzero((caddr_t)sdtmp, 8);
1558 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1559 		uscsi.sc_cpoint = (u_char *)scr;
1560 		uscsi.sc_ctrnscnt = 8;
1561 		uscsi.sc_opcode = SCOP_RCAP;
1562 		(void) sdcmd(unit << 3, &uscsi);
1563 
1564 		sdd->sdd_nsect = scr->scr_nblock + 1;
1565 		sdd->sdd_sectsize = scr->scr_blocklen;
1566 		if (sdd->sdd_sectsize == 0)
1567 			sdd->sdd_sectsize = SDBSIZE1K;
1568 	}
1569 
1570 	bzero(sdtmp, DEV_BSIZE);
1571 
1572 	if ((sdd->sdd_flags & SDDF_NONFMT) == 0) {
1573 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
1574 		uscsi.sc_cpoint = sdtmp;
1575 		uscsi.sc_ctrnscnt = DEV_BSIZE;
1576 		uscsi.sc_opcode = SCOP_READ;
1577 		uscsi.sc_lad = 0;
1578 		uscsi.sc_count = 1;
1579 
1580 		(void) sdcmd(unit << 3, &uscsi);
1581 		sdd->sdd_flags &= ~SDDF_SKIPCHECK;
1582 	}
1583 
1584 	fsp = (struct firstsector *)sdtmp;
1585 	dlp = (struct disklabel *)(sdtmp + LABELOFFSET);
1586 #ifdef DISKINFO
1587 	dip = &fsp->diskinfo;
1588 #endif
1589 
1590 	s = splclock();
1591 	hsp = &sdstdrv[unit];
1592 	bzero((caddr_t)hsp, sizeof (struct sdst));
1593 	bzero(&sdlabel[unit], sizeof (struct disklabel));
1594 
1595 	if ((dlp->d_magic == DISKMAGIC)
1596 	    && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) {
1597 		sdlabel[unit] = *dlp;
1598 		disklabel2sdst(unit, dlp, hsp);
1599 #ifdef DISKINFO
1600 	} else if ((dip->di_magic == DISKINFO_MAGIC)
1601 		    && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) {
1602 		diskinfo2sdst(unit, dip, hsp);
1603 		diskinfo2disklabel(unit, dip, &sdlabel[unit]);
1604 #endif
1605 	} else {
1606 		if ((ii->ii_type == UNKNOWN_DISK)
1607 				|| (sdi->sdstp->sizes == calc_disk_sizes)) {
1608 			/*
1609 			 * If device is UNKNOWN PARTITION SIZE,
1610 			 *	calculate default partition from capacity.
1611 			 */
1612 			st = sdi->sdstp;
1613 			hsp->nsect = st->nsect;		/* # sectors/track */
1614 			hsp->ntrak = st->ntrak;		/* # tracks/cylinder */
1615 			hsp->nspc = st->nspc;		/* # sectors/cylinder */
1616 			hsp->ncyl = st->ncyl;		/* # cylinders */
1617 			hsp->rps = st->rps;		/* # revolutions/sec */
1618 			hsp->sizes = sdsizedrv[unit];	/* partition table */
1619 
1620 			sd_calcpart(ii, hsp->sizes,
1621 					sdd->sdd_nsect, sdd->sdd_sectsize);
1622 			sdst2disklabel(unit, hsp, &sdlabel[unit]);
1623 		} else {
1624 			/*
1625 			 * If device is support disk,
1626 			 *	copy default partition from size table.
1627 			 */
1628 			st = sdi->sdstp;
1629 
1630 			hsp->nsect = st->nsect;	/* # sectors/track */
1631 			hsp->ntrak = st->ntrak;	/* # tracks/cylinder */
1632 			hsp->nspc = st->nspc;	/* # sectors/cylinder */
1633 			hsp->ncyl = st->ncyl;	/* # cylinders */
1634 			hsp->rps = st->rps;	/* # revolutions / second */
1635 			hsp->sizes = sdsizedrv[unit];	/* partition table */
1636 
1637 			for (i = 0; i < PNUM; i++) {
1638 			    hsp->sizes[i].sd_nblocks = st->sizes[i].sd_nblocks;
1639 			    hsp->sizes[i].sd_blkoff = st->sizes[i].sd_blkoff;
1640 			}
1641 			sdst2disklabel(unit, hsp, &sdlabel[unit]);
1642 		}
1643 	}
1644 
1645 	/* BEGIN XXX*/
1646 	if (hsp->rps == 0) {
1647 		/*
1648 		 * If device is support disk,
1649 		 *	copy default partition from size table.
1650 		 */
1651 		st = sdi->sdstp;
1652 
1653 		hsp->nsect = st->nsect;		/* # sectors/track */
1654 		hsp->ntrak = st->ntrak;		/* # tracks/cylinder */
1655 		hsp->nspc = st->nspc;		/* # sectors/cylinder */
1656 		hsp->ncyl = st->ncyl;		/* # cylinders */
1657 		hsp->rps = st->rps;		/* # revolutions / second */
1658 		sdst2disklabel(unit, hsp, &sdlabel[unit]);
1659 	}
1660 	/* END XXX*/
1661 	(void)splx(s);
1662 }
1663 
1664 static char Warn_Part[] = "sd%d: PARTITION TABLE CHANGED\n";
1665 static char Pr_Part_Fmt[] = "sd%d%c: nblk=%d, off=%d\n";
1666 
1667 #define stsz(N) st->sizes[(N)].sd_nblocks
1668 #define stof(N) st->sizes[(N)].sd_blkoff
1669 #define dlsz(N) dlp->d_partitions[(N)].p_size
1670 #define dlof(N) dlp->d_partitions[(N)].p_offset
1671 #define disz(N) dip->di_part[(N)].dp_nblocks
1672 #define diof(N) dip->di_part[(N)].dp_blkoff
1673 
1674 #ifndef BBSIZE
1675 #define BBSIZE 8192
1676 #endif
1677 
1678 static
1679 check_sdst(unit, st)
1680 	int unit;
1681 	struct sdst *st;
1682 {
1683 	if (st->nsect == 0) {
1684 		st->nsect = 1;
1685 		printf("sd%d: nsect SHOULD BE != 0, 1 assumed\n", unit);
1686 	}
1687 
1688 	if (st->rps == 0) {
1689 		st->rps = 60;
1690 		printf("sd%d: rps SHOULD BE != 0, 60 assumed\n", unit);
1691 	}
1692 }
1693 
1694 static
1695 disklabel2sdst(unit, dlp, st)
1696 	int unit;
1697 	register struct disklabel *dlp;
1698 	register struct sdst *st;
1699 {
1700 	register int i;
1701 	int msg_header_printed;
1702 
1703 	msg_header_printed = 0;
1704 
1705 	st->nsect = dlp->d_nsectors;	/* # sectors/track */
1706 	st->ntrak = dlp->d_ntracks;	/* # tracks/cylinder */
1707 	st->nspc = dlp->d_secpercyl;	/* # sectors/cylinder */
1708 	st->ncyl = dlp->d_ncylinders;	/* # cylinders */
1709 	st->rps = dlp->d_rpm / 60;	/* # revolutions / second */
1710 	st->sizes = sdsizedrv[unit];	/* partition table */
1711 
1712 	check_sdst(unit, st);
1713 
1714 	for (i = 0; i < PNUM; i++) {
1715 		if (msg_header_printed == 0) {
1716 			if (((stsz(i) != 0) || (stof(i) != 0))
1717 			    && ((stsz(i) != dlsz(i)) || (stof(i) != dlof(i)))) {
1718 				msg_header_printed = 1;
1719 			}
1720 		}
1721 	}
1722 
1723 	for (i = 0; i < PNUM; i++) {
1724 		stsz(i) = dlsz(i);
1725 		stof(i) = dlof(i);
1726 	}
1727 
1728 	if (msg_header_printed) {
1729 		printf(Warn_Part, unit);
1730 		for (i = 0; i < PNUM; i++)
1731 			printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i));
1732 	}
1733 }
1734 
1735 #ifdef DISKINFO
1736 static
1737 diskinfo2sdst(unit, dip, st)
1738 	int unit;
1739 	register struct diskinfo *dip;
1740 	register struct sdst *st;
1741 {
1742 	register int i;
1743 	int msg_header_printed;
1744 
1745 	msg_header_printed = 0;
1746 
1747 	st->nsect = dip->di_dkst.dks_nsect;	/* # sectors/track */
1748 	st->ntrak = dip->di_dkst.dks_ntrak;	/* # tracks/cylinder */
1749 	st->nspc = dip->di_dkst.dks_nsect * dip->di_dkst.dks_ntrak;
1750 						/* # sectors/cylinder */
1751 	st->ncyl = dip->di_dkst.dks_ncyl;	/* # cylinders */
1752 	st->rps = dip->di_dkst.dks_rps;		/* # revolutions / second */
1753 	st->sizes = sdsizedrv[unit];		/* partition table */
1754 
1755 	check_sdst(unit, st);
1756 
1757 	for (i = 0; i < PNUM; i++) {
1758 		if (msg_header_printed == 0) {
1759 			if (((stsz(i) != 0) || (stof(i) != 0))
1760 			    && ((stsz(i) != disz(i)) || (stof(i) != diof(i)))) {
1761 				msg_header_printed = 1;
1762 			}
1763 		}
1764 	}
1765 
1766 	for (i = 0; i < PNUM; i++) {
1767 		stsz(i) = disz(i);
1768 		stof(i) = diof(i);
1769 	}
1770 
1771 	if (msg_header_printed) {
1772 		printf(Warn_Part, unit);
1773 		for (i = 0; i < PNUM; i++)
1774 			printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i));
1775 	}
1776 }
1777 
1778 static
1779 diskinfo2disklabel(unit, dip, dlp)
1780 	int unit;
1781 	register struct diskinfo *dip;
1782 	register struct disklabel *dlp;
1783 {
1784 	register int i;
1785 
1786 	dlp->d_type = DTYPE_SCSI;			/* drive type */
1787 	dlp->d_secsize = sdd_softc[unit].sdd_sectsize;	/* # of bytes per sector */
1788 	dlp->d_nsectors = dip->di_dkst.dks_nsect;	/* # sectors/track */
1789 	dlp->d_ntracks = dip->di_dkst.dks_ntrak;	/* # tracks/cylinder */
1790 	dlp->d_ncylinders = dip->di_dkst.dks_ncyl;	/* # cylinders */
1791 	dlp->d_secpercyl = dip->di_dkst.dks_nsect * dip->di_dkst.dks_ntrak;
1792 							/* # sectors/cylinder */
1793 	dlp->d_rpm = dip->di_dkst.dks_rps * 60;		/* # revolutions / second */
1794 	dlp->d_bbsize = BBSIZE;	/*XXX*/	/* size of boot area at sn0, bytes */
1795 	dlp->d_sbsize = SBSIZE;	/*XXX*/	/* max size of fs superblock, bytes */
1796 
1797 	for (i = 0; i < PNUM; i++) {
1798 		dlsz(i) = disz(i);
1799 		dlof(i) = diof(i);
1800 	}
1801 }
1802 #endif /* DISKINFO */
1803 
1804 /* #ifdef DISKINFO KU:XXX */
1805 static
1806 disklabel2diskinfo(unit, dlp, dip)
1807 	int unit;
1808 	register struct disklabel *dlp;
1809 	register struct diskinfo *dip;
1810 {
1811 	register int i;
1812 
1813 	dip->di_magic = DISKINFO_MAGIC;
1814 	dip->di_dkst.dks_nsect = dlp->d_nsectors;	/* # sectors/track */
1815 	dip->di_dkst.dks_ntrak = dlp->d_ntracks;	/* # tracks/cylinder */
1816 	dip->di_dkst.dks_ncyl = dlp->d_ncylinders;	/* # cylinders */
1817 	dip->di_dkst.dks_rps = dlp->d_rpm / 60;		/* # revolutions/second */
1818 
1819 	for (i = 0; i < PNUM; i++) {
1820 		disz(i) = dlsz(i);
1821 		diof(i) = dlof(i);
1822 	}
1823 }
1824 /* #endif /* DISKINFO */
1825 
1826 static
1827 sdst2disklabel(unit, st, dlp)
1828 	int unit;	/*XXX*/
1829 	register struct sdst *st;
1830 	register struct disklabel *dlp;
1831 {
1832 	register int i;
1833 
1834 	dlp->d_type = DTYPE_SCSI;			/* drive type */
1835 	dlp->d_secsize = sdd_softc[unit].sdd_sectsize;	/* # of bytes per sector */
1836 	dlp->d_nsectors = st->nsect;	/* # sectors/track */
1837 	dlp->d_ntracks = st->ntrak;	/* # tracks/cylinder */
1838 	dlp->d_ncylinders = st->ncyl;	/* # cylinders */
1839 	dlp->d_secpercyl = st->nspc;	/* # sectors/cylinder */
1840 	dlp->d_rpm = st->rps * 60;	/* # revolutions / minute */
1841 	dlp->d_bbsize = BBSIZE;	/*XXX*/	/* size of boot area at sn0, bytes */
1842 	dlp->d_sbsize = SBSIZE;	/*XXX*/	/* max size of fs superblock, bytes */
1843 
1844 	for (i = 0; i < PNUM; i++) {
1845 		dlsz(i) = stsz(i);
1846 		dlof(i) = stof(i);
1847 	}
1848 }
1849 
1850 #undef stsz
1851 #undef stof
1852 #undef dlsz
1853 #undef dlof
1854 #undef disz
1855 #undef diof
1856 
1857 sd_calcpart(ii, disk_sizes, nsect, sectsize)
1858 	register struct iop/**/_device *ii;
1859 	register struct size disk_sizes[];
1860 	int nsect;
1861 	int sectsize;
1862 {
1863 	register struct defpart *dp;
1864 	register int size_mb;
1865 	register int i;
1866 	int psize;
1867 
1868 	size_mb = nsect * sectsize / (1024 * 1024);
1869 
1870 	for (dp = defpart_std; dp->range_max; dp++)
1871 		if ((dp->range_min <= size_mb) && (size_mb < dp->range_max))
1872 			break;
1873 
1874 	/* PASS1 */
1875 	for (i = 0; i < PNUM; i++) {
1876 		psize = dp->partsize[i];
1877 
1878 		switch (psize) {
1879 
1880 		case PART_UNUSED:
1881 			disk_sizes[i].sd_nblocks = 0;
1882 			break;
1883 
1884 		case PART_SPEC:
1885 			disk_sizes[i].sd_nblocks = nsect * sectsize / DEV_BSIZE;
1886 			break;
1887 
1888 		case PART_CALCF:
1889 		case PART_CALCG:
1890 			break;
1891 
1892 		default:
1893 			disk_sizes[i].sd_nblocks = psize;
1894 			break;
1895 		}
1896 	}
1897 
1898 	/* PASS2 */
1899 	for (i = 0; i < PNUM; i++) {
1900 		psize = dp->partsize[i];
1901 
1902 		switch (psize) {
1903 
1904 		case PART_UNUSED:
1905 		case PART_SPEC:
1906 			break;
1907 
1908 		case PART_CALCF:
1909 			disk_sizes[i].sd_nblocks =
1910 				disk_sizes[PART_C].sd_nblocks -
1911 				(disk_sizes[PART_A].sd_nblocks +
1912 				 disk_sizes[PART_B].sd_nblocks +
1913 				 disk_sizes[PART_D].sd_nblocks +
1914 				 disk_sizes[PART_E].sd_nblocks +
1915 				 disk_sizes[PART_H].sd_nblocks);
1916 			break;
1917 
1918 		case PART_CALCG:
1919 			disk_sizes[i].sd_nblocks =
1920 				disk_sizes[PART_C].sd_nblocks -
1921 				(disk_sizes[PART_A].sd_nblocks +
1922 				 disk_sizes[PART_B].sd_nblocks +
1923 				 disk_sizes[PART_H].sd_nblocks);
1924 			break;
1925 
1926 		default:
1927 			break;
1928 		}
1929 	}
1930 
1931 	/* OFFSET */
1932 	disk_sizes[PART_A].sd_blkoff = 0;
1933 	disk_sizes[PART_B].sd_blkoff = disk_sizes[PART_A].sd_nblocks;
1934 	disk_sizes[PART_C].sd_blkoff = 0;
1935 	disk_sizes[PART_D].sd_blkoff = disk_sizes[PART_A].sd_nblocks
1936 					+ disk_sizes[PART_B].sd_nblocks
1937 					+ disk_sizes[PART_H].sd_nblocks;
1938 	disk_sizes[PART_E].sd_blkoff = disk_sizes[PART_D].sd_blkoff
1939 					+ disk_sizes[PART_D].sd_nblocks;
1940 	disk_sizes[PART_F].sd_blkoff = disk_sizes[PART_E].sd_blkoff
1941 					+ disk_sizes[PART_E].sd_nblocks;
1942 	disk_sizes[PART_G].sd_blkoff = disk_sizes[PART_D].sd_blkoff;
1943 
1944 	if (disk_sizes[PART_H].sd_nblocks == 0)
1945 		disk_sizes[PART_H].sd_blkoff = 0;
1946 	else {
1947 		disk_sizes[PART_H].sd_blkoff =
1948 			disk_sizes[PART_A].sd_nblocks +
1949 			disk_sizes[PART_B].sd_nblocks;
1950 	}
1951 
1952 	for (i = 0; i < PNUM; i++)
1953 		if (disk_sizes[i].sd_nblocks == 0)
1954 			disk_sizes[i].sd_blkoff = 0;
1955 }
1956 
1957 int sd_str_pr = 0;
1958 
1959 sdstrategy(bp)
1960 	register struct buf *bp;
1961 {
1962 	register struct iop/**/_device *ii;
1963 	register struct sdst *st;
1964 	register struct buf *dp;
1965 	register int unit;
1966 	register int ssize;
1967 	struct sdd_softc *sdd;
1968 	struct sdc_softc *sdc;
1969 	long bn;
1970 	int xunit;
1971 	int s;
1972 
1973 	xunit = dev2part(bp->b_dev);
1974 	unit = dev2unit(bp->b_dev);
1975 	if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
1976 		goto bad;
1977 
1978 	if (bp != &csdbuf[unit]) {
1979 		/*
1980 		 * READ / WRITE command
1981 		 */
1982 		sdd = &sdd_softc[unit];
1983 		if (sdd->sdd_flags & SDDF_NONFMT)
1984 			goto bad;
1985 		sdc = &sdc_softc[ii->ii_ctlr];
1986 		ssize = sdd->sdd_sectsize;
1987 		if ((ssize != DEV_BSIZE)
1988 			&& ((((dkblock(bp) * DEV_BSIZE) % ssize) != 0)
1989 				|| (((bp->b_flags & B_READ) == 0) &&
1990 				    ((bp->b_bcount % ssize) != 0)))) {
1991 			goto bad;
1992 		}
1993 
1994 		st = &sdstdrv[unit];
1995 		bn = dkblock(bp);
1996 		bp->b_resid = 0;
1997 		if ((bn < 0) || (bn >= st->sizes[xunit].sd_nblocks))
1998 			goto bad2;
1999 		if (sd_access_check(bp) < 0)
2000 			goto bad2;
2001 
2002 #ifdef notdef /* KU: XXX */
2003 		bp->b_cylin = (bn + st->sizes[xunit].sd_blkoff) / st->nspc;
2004 	} else {
2005 		bp->b_cylin = 0;
2006 #endif
2007 	}
2008 
2009 	s = splsc();
2010 	dp = &sdutab[ii->ii_unit];
2011 	disksort(dp, bp);
2012 	if (dp->b_active == 0) {
2013 		sdustart(ii);
2014 		bp = &ii->ii_mi->im_tab;
2015 		if (bp->b_actf && bp->b_active == 0)
2016 			sdstart(ii->ii_mi);
2017 	}
2018 	splx(s);
2019 	return;
2020 
2021 bad:
2022 	bp->b_flags |= B_ERROR;
2023 	goto done;
2024 bad2:
2025 	bp->b_resid = bp->b_bcount;
2026 done:
2027 	iodone(bp);
2028 }
2029 
2030 /*
2031  * Unit start routine.
2032  */
2033 sdustart(ii)
2034 	register struct iop/**/_device *ii;
2035 {
2036 	register struct iop/**/_ctlr *im;
2037 	register struct buf *dp;
2038 
2039 	if (ii == NULL)
2040 		return;
2041 	im = ii->ii_mi;
2042 	dk_busy &= ~(1 << ii->ii_dk);
2043 	dp = &sdutab[ii->ii_unit];
2044 	if (dp->b_actf == NULL)
2045 		return;
2046 	/*
2047 	 * If the controller is active, just remember
2048 	 * that this device would like to be positioned ...
2049 	 * if we tried to position now we would confuse the SD.
2050 	 */
2051 	if (im->im_tab.b_active) {
2052 		sdc_softc[im->im_ctlr].sdc_softas |= (1 << ii->ii_slave);
2053 		return;
2054 	}
2055 	/*
2056 	 * If we have already positioned this drive,
2057 	 * then just put it on the ready queue.
2058 	 */
2059 	if (dp->b_active == 0)
2060 		dp->b_active = 1;
2061 	/*
2062 	 * Device is ready to go
2063 	 * put it on the ready queue for the controller
2064 	 * (unless its already there.)
2065 	 */
2066 	if (dp->b_active != 2) {
2067 		dp->b_forw = NULL;
2068 		if (im->im_tab.b_actf == NULL)
2069 			im->im_tab.b_actf = dp;
2070 		else
2071 			im->im_tab.b_actl->b_forw = dp;
2072 		im->im_tab.b_actl = dp;
2073 		dp->b_active = 2;
2074 	}
2075 }
2076 
2077 /*
2078  * Start up a transfer on a drive.
2079  */
2080 sdstart(im)
2081 	register struct iop/**/_ctlr *im;
2082 {
2083 	register struct buf *bp;
2084 	register struct buf *dp;
2085 	register struct sdc_softc *sdc;
2086 
2087 loop:
2088 	/*
2089 	 * Pull a request off the controller queue.
2090 	 */
2091 	if ((dp = im->im_tab.b_actf) == NULL)
2092 		return;
2093 	if ((bp = dp->b_actf) == NULL) {
2094 		im->im_tab.b_actf = dp->b_forw;
2095 		goto loop;
2096 	}
2097 	/*
2098 	 * Mark controller busy, and
2099 	 * determine destination of this request.
2100 	 */
2101 	im->im_tab.b_active++;
2102 
2103 	sdexec(bp);
2104 }
2105 
2106 void
2107 sdexec(bp)
2108 	register struct buf *bp;
2109 {
2110 	register struct iop/**/_device *ii;
2111 	register struct buf_stat *bs;
2112 	register struct scsi *sc;
2113 	register int ssize;
2114 	register int unit;
2115 	register int intr;
2116 	register int bn;
2117 	struct sdc_softc *sdc;
2118 	struct sdd_softc *sdd;
2119 	struct sdst *st;
2120 	int sz;
2121 	int over;
2122 	struct sc_map *map;
2123 
2124 	unit = dev2unit(bp->b_dev);
2125 	ii= sddinfo[unit];
2126 	intr = ii->ii_intr;
2127 	sdd = &sdd_softc[unit];
2128 	sdc = &sdc_softc[ii->ii_ctlr];
2129 
2130 	sc = get_scsi(intr);
2131 
2132 	if (bp == &csdbuf[unit]) {	/* do sdcmd() */
2133 		bcopy((caddr_t)&kernscsi[unit],
2134 			(caddr_t)sc, sizeof(struct scsi));
2135 		if (bp->b_un.b_addr == NULL) {
2136 			map = 0;
2137 		} else {
2138 			map = get_sc_map(intr);
2139 			sc->sc_map = (struct sc_map *)ipc_phys(map);
2140 		}
2141 	} else {			/* R/W */
2142 		ssize = sdd->sdd_sectsize;
2143 
2144 		st = &sdstdrv[unit];
2145 		bn = dkblock(bp);
2146 		if (sdd->sdd_lastblk / st->nspc != bn / st->nspc)
2147 			dk_seek[ii->ii_dk]++;
2148 
2149 		st = &sdstdrv[unit];
2150 		bn = dkblock(bp);
2151 
2152 		/*
2153 		 * Setup for the transfer, and get in the IOP queue.
2154 		 */
2155 		scinit(sc, ii->ii_slave, ssize);
2156 		sc->sc_ctrnscnt = bp->b_bcount - bp->b_resid;
2157 		map = get_sc_map(intr);
2158 		sc->sc_map = (struct sc_map *)ipc_phys(map);
2159 
2160 		/* cdb */
2161 		sc->sc_cdb.un_type1.t1_opcode =
2162 				(bp->b_flags & B_READ) ?	SCOP_EREAD :
2163 				(ii->ii_flags & SD_F_WRTVRFY) ?	SCOP_WRTVRFY :
2164 								SCOP_EWRITE;
2165 #ifdef mips
2166 		{
2167 		int v;
2168 
2169 		v = (bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff)
2170 					* DEV_BSIZE / sdd->sdd_sectsize;
2171 		sc->sc_ladhi = v >> 16;
2172 		sc->sc_ladlo = v;
2173 
2174 		v = (sc->sc_ctrnscnt + ssize - 1) / ssize;
2175 		sc->sc_cdb.un_type1.t1_p2 = v >> 8;
2176 		sc->sc_cdb.un_type1.t1_p3 = v;
2177 		}
2178 #else
2179 		*(u_int *)(&sc->sc_cdb.un_type1.t1_ladhi) =
2180 				(bn + st->sizes[dev2part(bp->b_dev)].sd_blkoff)
2181 					* DEV_BSIZE / sdd->sdd_sectsize;
2182 		*(u_short *)(&sc->sc_cdb.un_type1.t1_p2) =
2183 				    (sc->sc_ctrnscnt + ssize -1) / ssize;
2184 #endif
2185 		if ((sdd->sdd_flags & SDDF_ERASEOFF)
2186 				&& ((bp->b_flags & B_READ) == 0)) {
2187 			sc->sc_ctrl = 0x40;
2188 		}
2189 	}
2190 
2191 	sdc->sdc_firmware |= SDCFW_BUSY;
2192 	iop/**/go(ii, map);
2193 }
2194 
2195 /*
2196  * Now all ready to go.
2197  */
2198 sddgo(im)
2199 	register struct iop/**/_ctlr *im;
2200 {
2201 	register int intr;
2202 
2203 	im->im_tab.b_active = 2;
2204 	intr = im->im_intr;
2205 
2206 	sc_go(intr, get_scsi(intr), SCSI_INTEN);
2207 }
2208 
2209 /*
2210  * copyin(), copyout() can't use in the interrupt routine.
2211  *	because user process is changed.
2212  */
2213 /*
2214  * Handle a disk interrupt.
2215  *	d: controller number
2216  */
2217 sdintr(d)
2218 	int d;
2219 {
2220 	register struct iop/**/_ctlr *im;
2221 	register struct sdc_softc *sdc;
2222 	register struct sdd_softc *sdd;
2223 	register struct scsi *sc;
2224 	register int intr;
2225 	register int unit;
2226 	register int slave;
2227 	register int as;
2228 	struct iop/**/_device *ii;
2229 	struct sddevinfo *sdi;
2230 	struct sc_extnd *sce;
2231 	struct sdst *st;
2232 	struct buf *bp;
2233 	struct buf *dp;
2234 	char *erp_page;
2235 	int code;
2236 	int len;
2237 	int tstatus;
2238 	int delay_start();
2239 	int delay_medrmv();
2240 	int wait_re_init_done();
2241 
2242 	im = sdminfo[d];
2243 	sdc = &sdc_softc[im->im_ctlr];
2244 	intr = im->im_intr;
2245 	as = sdc->sdc_softas;
2246 
2247 	sdc->sdc_wticks = 0;
2248 	sc = get_scsi(intr);
2249 	/*
2250 	 * If SDCS_IOCTL bit is set, then don't check error.
2251 	 */
2252 	if (sdc->sdc_state & SDCS_IOCTL) {
2253 		sdc->sdc_state &= ~SDCS_IOCTL;
2254 		sdd = &sdd_softc[(sdip[d][sc->sc_identify & IDT_DRMASK])->ii_unit];
2255 
2256 		if (sdc->sdc_state & SDCS_SCUNLOCK) {
2257 			int s;
2258 
2259 			sdc->sdc_state &= ~SDCS_SCUNLOCK;
2260 			s = splclock();
2261 			if (sdc->sdc_state & SDCS_OPEN_WAIT) {
2262 				sdc->sdc_state &= ~SDCS_OPEN_WAIT;
2263 				wakeup((caddr_t)sdc);
2264 			}
2265 			splx(s);
2266 			/*
2267 			 * UNLOCK SCSI access
2268 			 */
2269 			sdc->sdc_firmware &= ~SDCFW_BUSY;
2270 		}
2271 		return;
2272 	}
2273 
2274 	im->im_tab.b_active = 1;
2275 	/*
2276 	 * Get device and block structures, and a pointer
2277 	 * to the iop_device for the drive.
2278 	 */
2279 	dp = im->im_tab.b_actf;
2280 	bp = dp->b_actf;
2281 	unit = dev2unit(bp->b_dev);
2282 
2283 	ii = sddinfo[unit];
2284 	slave = ii->ii_slave;
2285 	st = &sdstdrv[unit];
2286 	dk_busy &= ~(1 << ii->ii_dk);
2287 	sdd = &sdd_softc[unit];
2288 	sdi = &sddevinfo[ii->ii_type];
2289 	sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];
2290 
2291 	/*
2292 	 * Check error on the drive.
2293 	 */
2294 	tstatus = sc->sc_tstatus & TGSTMASK;
2295 	if (sc->sc_istatus != INST_EP) {
2296 		/*
2297 		 * initiator status is bad.
2298 		 *	check & retry !!
2299 		 */
2300 		if ((sc->sc_istatus&(INST_EP|INST_PRE)) == (INST_EP|INST_PRE)) {
2301 			/* detect parity error or abnormal terminate */
2302 			if ((sc->sc_istatus & INST_LB) == 0)
2303 				printf("sd%d: SCSI bus parity error\n", unit);
2304 			sdc->sdc_countcc--;
2305 			goto sdintr_exec;
2306 		}
2307 		if ((sc->sc_istatus & INST_EP) == 0) {
2308 			if (sc->sc_istatus & (INST_WAIT | INST_IP | INST_WR)) {
2309 				if (++sdc->sdc_retrycnt < NRETRY) {
2310 					im->im_tab.b_active = 2;
2311 					/*
2312 					 * Konomama return sitemo,
2313 					 * lost interrupt ni narudake deha
2314 					 * naidarou ka ?
2315 					 * Isso error ni sitahou ga
2316 					 * ii nodeha naidarou ka ?
2317 					 */
2318 					return;
2319 				}
2320 			}
2321 			printf("SCSI%d: abnormal termination\n", intr);
2322 			printf("ISTAT = 0x%x, TSTAT = 0x%x\n",
2323 					sc->sc_istatus, sc->sc_tstatus);
2324 			if (++sdc->sdc_nhrderr >= MAXHRDERR) {
2325 				printf("SCSI%d: too many hard errors\n", intr);
2326 				sdc->sdc_nhrderr = 0;
2327 				goto sdintr_error;
2328 			}
2329 			screset(intr);
2330 			goto sdintr_exec;
2331 		}
2332 		if ((sc->sc_istatus & (INST_TO|INST_HE)) != 0) {
2333 			if (sc->sc_istatus & INST_HE) {
2334 				/*
2335 				 * SCSI bus reset is occured.
2336 				 *	to be continue --> hdreset()
2337 				 */
2338 				re_init_done = 0;
2339 				timeout(wait_re_init_done, bp, 10*hz);
2340 				return;
2341 			}
2342 			if (++sdc->sdc_nhrderr >= MAXHRDERR) {
2343 				printf("SCSI%d: too many hard errors (ISTAT=0x%x)\n",
2344 					intr, sc->sc_istatus);
2345 				sdc->sdc_nhrderr = 0;
2346 				goto sdintr_error;
2347 			}
2348 			if (++sdc->sdc_retrycnt >= NRETRY) {
2349 				printf("SCSI%d: too many initiator errors (ISTAT=0x%x)\n",
2350 					intr, sc->sc_istatus);
2351 				goto sdintr_error;
2352 			}
2353 			DELAY(D100MSEC * 10);
2354 			goto sdintr_exec;
2355 		}
2356 	}
2357 
2358 	if (sdd->sdd_flags & SDDF_SKIPCHECK)
2359 		goto sdintr_done;
2360 
2361 check_target_status:
2362 	/*
2363 	 * check target status
2364 	 */
2365 	switch (sdc->sdc_state) {
2366 
2367 	/********************************/
2368 	/*				*/
2369 	/*	NORMAL OPERATION	*/
2370 	/*				*/
2371 	/********************************/
2372 	case SDCS_NORMAL:
2373 		switch (tstatus) {
2374 
2375 		case TGST_GOOD:
2376 			break;
2377 
2378 		case TGST_CC:
2379 			sdc->sdc_state |= SDCS_RSENSE;
2380 sdintr_rsense:
2381 			im->im_tab.b_active = 2;
2382 			bzero((caddr_t)sce, RSEN_CNT);
2383 			scop_rsense(intr, sc, slave,
2384 					SCSI_INTEN, RSEN_CNT, (caddr_t)sce);
2385 			return;
2386 
2387 		case TGST_BUSY:
2388 			if (++sdc->sdc_retrycnt > MAXRETRYCNT) {
2389 				goto sdintr_error;
2390 			}
2391 			timeout(sdexec, (caddr_t)bp, hz);
2392 			return;
2393 
2394 		default:
2395 			printf("sd%d: bad target status 0x%x\n",
2396 						unit, sc->sc_tstatus);
2397 			goto sdintr_error;
2398 		}
2399 		break;
2400 
2401 	/****************************************/
2402 	/*					*/
2403 	/*	REQUEST SENSE analysis		*/
2404 	/*					*/
2405 	/****************************************/
2406 	case SDCS_RSENSE:
2407 	case SDCS_PREVRMB|SDCS_RSENSE:
2408 	case SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE:
2409 	case SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE:
2410 	case SDCS_ECCOFF|SDCS_RSENSE:
2411 	case SDCS_ECCOFF|SDCS_RASBLK|SDCS_RSENSE:
2412 	case SDCS_ECCOFF|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE:
2413 	case SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE:
2414 	case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE:
2415 		if (tstatus != TGST_GOOD) {
2416 			printf("sd%d: bad target status 0x%x\n",
2417 						unit, sc->sc_tstatus);
2418 			goto sdintr_error;
2419 		}
2420 		/*
2421 		 * error message print out
2422 		 */
2423 		code = sderrordisp(sce, ii);
2424 
2425 
2426 		if ((sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE)) ||
2427 		    (sdc->sdc_state == (SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE))) {
2428 			printf("sd%d: cannot reassign block %d\n",
2429 						unit, sdd->sdd_badsect);
2430 			goto sdintr_error;
2431 		}
2432 		if (sdc->sdc_state == (SDCS_PREVRMB|SDCS_RSENSE)) {
2433 			if (sce->sce_skey == 0x2) {
2434 				/*
2435 				 * Not ready
2436 				 */
2437 				sdc->sdc_state = SDCS_PREVRMB;
2438 				timeout(delay_medrmv, (caddr_t)ii, hz);
2439 				return;
2440 			}
2441 		}
2442 
2443 		/*			*/
2444 		/* RSENSE error handler	*/
2445 		/*			*/
2446 		switch (code) {
2447 
2448 		/********************************/
2449 		/*	continue		*/
2450 		/********************************/
2451 		/* NO SENSE */
2452 		case 0x00:	/* No Additional Sense Information */
2453 		/* RECOVERED ERROR */
2454 		case 0x38:	/* Recovered with Auto-Reallocation */
2455 			sdc->sdc_state &= ~SDCS_RSENSE;
2456 			goto check_target_status;
2457 
2458 		/********************************/
2459 		/*	continue or error	*/
2460 		/********************************/
2461 		/* ILLEGAL REQUEST */
2462 
2463 		case 0x21:	/* illegal Logical Block Address */
2464 			if (&st->sizes[dev2part(bp->b_dev)] == NULL)
2465 				goto sdintr_error;
2466 			if (bp->b_bcount > 0) {
2467 				bp->b_resid = bp->b_bcount
2468 				    - (sdd->sdd_badsect * sdd->sdd_sectsize
2469 				    - (st->sizes[dev2part(bp->b_dev)].sd_blkoff
2470 				    + dkblock(bp)) * DEV_BSIZE);
2471 			}
2472 			if (bp->b_resid >= bp->b_bcount || bp->b_resid <= 0) {
2473 				/*
2474 				 * all I/O failure
2475 				 */
2476 				bp->b_resid = bp->b_bcount;
2477 				goto sdintr_error;
2478 			}
2479 			/* Ignore error */
2480 			break;
2481 
2482 		/* MEDIUM ERROR */
2483 		case 0x31:	/* Medium Format Corrupted */
2484 			sdd->sdd_flags |= SDDF_NONFMT;
2485 			/* Ignore error */
2486 			break;
2487 
2488 		/********************************/
2489 		/*	more retry		*/
2490 		/********************************/
2491 		/* MEDIUM or RECOVERED ERROR */
2492 		case 0x10:	/* ID CRC Error */
2493 		case 0x12:	/* No Address Mark found in ID field */
2494 		case 0x13:	/* No Address Mark found in Data field */
2495 		case 0x14:	/* No recode found */
2496 		/* H/W or MEDIUM or RECOVERED ERROR */
2497 		case 0x15:	/* Seek Positioning Error */
2498 			if (sd_ignore_error) {
2499 				sdc->sdc_state = SDCS_NORMAL;
2500 				goto check_target_status;
2501 			}
2502 			/* fall through */
2503 
2504 		/* H/W ERROR */
2505 		case 0x01:	/* No Index/Address Mark Found signal */
2506 		case 0x02:	/* No Seek Complete */
2507 		case 0x06:	/* No Track Zero found */
2508 		/* H/W ERROR or RECOVERED ERROR */
2509 		case 0x03:	/* Write Fault */
2510 		case 0x08:	/* Logical Unit Communication Failure */
2511 		case 0x09:	/* Track Following Error */
2512 		case 0x0b:	/* Load/Unload Failure */
2513 		case 0x0c:	/* Spindle Failure */
2514 		case 0x0d:	/* Focus Failure */
2515 		case 0x0e:	/* Tracking Failure */
2516 		case 0x0f:	/* Drive Initialization Failure */
2517 			sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO;
2518 
2519 			scinit(sc, slave, sdd->sdd_sectsize);
2520 			/* sc_cdb */
2521 			sc->sc_opcode = SCOP_REZERO;
2522 
2523 			sddgo(im);
2524 			return;
2525 
2526 		/********************************/
2527 		/*	re-allocate & retry	*/
2528 		/********************************/
2529 		/* MEDIUM or RECOVERED ERROR */
2530 		case 0x11:	/* Unrecovered Read Error */
2531 			if (sdc->sdc_state & SDCS_RASREAD) {
2532 sdintr_lostdata:
2533 				sdc->sdc_state =
2534 					SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA;
2535 				im->im_tab.b_active = 2;
2536 				scop_rasblk(intr, sc, slave,
2537 					SCSI_INTEN, sdd->sdd_badsect);
2538 				sdd->sdd_flags &= ~SDDF_VBADSECT;
2539 				return;
2540 			}
2541 			/* fall through */
2542 
2543 		/* RECOVERED ERROR */
2544 		case 0x17:	/* Recovered read data with retries */
2545 		case 0x18:	/* Recovered read data with ECC */
2546 			/*
2547 			 * set ECC ON & more retry
2548 			 */
2549 			if (sdc->sdc_firmware & SDCFW_DEFMODE)
2550 				goto sdintr_ecc;
2551 
2552 			if (sdc->sdc_state & SDCS_RASREAD)
2553 				goto sdintr_rasblk;
2554 
2555 			sdc->sdc_state = SDCS_ECC;
2556 			goto sdintr_msel_set;
2557 
2558 		/********************************/
2559 		/*	unit start & retry	*/
2560 		/********************************/
2561 		/* NOT READY */
2562 		case 0x04:	/* Drive Not Ready */
2563 			if (sdc->sdc_state & SDCS_ECC)
2564 				sdc->sdc_state = SDCS_ECCOFF|SDCS_RETRY;
2565 			else
2566 				sdc->sdc_state = SDCS_RETRY;
2567 			goto sdintr_stst;
2568 
2569 		/********************************/
2570 		/*	retry			*/
2571 		/********************************/
2572 		/* UNIT ATTENTION */
2573 		case 0x28:	/* Medium Changed */
2574 			sdd->sdd_flags &= ~(SDDF_NONFMT
2575 					    |SDDF_SAMEDSK
2576 					    |SDDF_REQ_EJECT
2577 					    |SDDF_XUSE
2578 					    |SDDF_INHRMV
2579 					    |SDDF_ERASEOFF);
2580 			/* fall through */
2581 
2582 		case 0x29: /* Power On or Reset or Bus Device Reset */
2583 			if (sdc->sdc_firmware & SDCFW_RMB) {
2584 				/***************************/
2585 				/* medium removable device */
2586 				/***************************/
2587 				sdc->sdc_state = SDCS_PREVRMB;
2588 				im->im_tab.b_active = 2;
2589 				scop_medrmv(intr, sc, slave,
2590 					    SCSI_INTEN, SDRMV_PREV);
2591 				return;
2592 			}
2593 
2594 		case 0x2a:	/* Mode Select Parameter Changed */
2595 		case 0x47:	/* SCSI interface bus parity error */
2596 			if (sdc->sdc_state & SDCS_ECC) {
2597 				sdc->sdc_state = SDCS_RETRY;
2598 				goto sdintr_msel_reset;
2599 			}
2600 			sdc->sdc_state = SDCS_NORMAL;
2601 			goto sdintr_exec;
2602 
2603 		/********************************/
2604 		/*	set error flag		*/
2605 		/********************************/
2606 		case 0x40:	/* RAM failure */
2607 		case 0x41:	/* Data Path diagnostic failure */
2608 		case 0x42:	/* Power On diagnostic failure */
2609 
2610 		case 0xb2:	/* Caddy load/eject failed */
2611 		case 0xb4:	/* Focus servo failure */
2612 		case 0xb5:	/* Spindle servo failure */
2613 		case 0xb6:	/* Caddy load mechanism failed */
2614 			goto sdintr_error;
2615 
2616 /*MO*/		case 0x80:	/* Limit Laser Life */
2617 /*MO*/		case 0x81:	/* Focus Coil Over-current Failure */
2618 /*MO*/		case 0x82:	/* Tracking Coil Over-current Failure */
2619 /*MO*/		case 0x83:	/* Temperature Alarm */
2620 /*CD*/	/*	case 0x80: */	/* Prevent bit is set */
2621 /*CD*/	/*	case 0x81: */	/* Logical unit is reserved */
2622 /*CD*/	/*	case 0x82: */	/* End of usr area encountered */
2623 /*CD*/	/*	case 0x83: */	/* Overlapped commands attempted */
2624 			goto sdintr_error;
2625 
2626 		default:
2627 			/*
2628 			 *	error detect, but what shall we do ?
2629 			 */
2630 	/*	case 0x05: */	/* Drive Not Selected */
2631 	/*	case 0x07: */	/* Multiple Drives Selected */
2632 	/*	case 0x0a: */	/* No disk */
2633 	/*	case 0x1a: */	/* Parameter overrun */
2634 	/*	case 0x1b: */	/* Synchronous transfer error */
2635 	/*	case 0x1d: */	/* Compare error */
2636 	/*	case 0x22: */	/* Illegal function for device type */
2637 	/*	case 0x23: */	/* Illegal function for Medium type */
2638 	/*	case 0x25: */	/* Illegal LUN */
2639 	/*	case 0x27: */	/* Write Protected */
2640 	/*	case 0x2b: */	/* Firmware has been downloaded */
2641 	/*	case 0x39: */	/* Automatic Reallocation Failure */
2642 	/*	case 0x43: */	/* Message Reject Error */
2643 	/*	case 0x45: */	/* Selection/Reselection failure */
2644 	/*	case 0x48: */	/* Initiator detected error */
2645 	/*	case 0x49: */	/* Inappropriate/illegal message */
2646 	/*	case 0x60: */	/* COPY: STATUS error */
2647 	/*	case 0x85: */	/* Audio address not valid */
2648 	/*	case 0xb0: */	/* Caddy not inserted in drive */
2649 	/*	case 0xb1: */	/* Unable to recover TOC */
2650 	/*	case 0xb3: */	/* CIRC unrecovered data error(L-EC off) */
2651 	/*	case 0xc3: */	/* COPY: Illegale CDB length */
2652 	/*	case 0xc5: */	/* COPY: Catastrophic error */
2653 	/*	case 0xc6: */	/* COPY: Illegal phase change */
2654 	/*	case 0xfc: */	/* COPY: MODE SENSE failed */
2655 
2656 			/*
2657 			 *	medium error
2658 			 */
2659 	/*	case 0x19: */	/* Defect list error */
2660 	/*	case 0x1c: */	/* Primary Defect List not found */
2661 	/*	case 0x30: */	/* Incompatible Cartridge */
2662 	/*	case 0x32: */	/* No Spare Defect Location Available */
2663 	/*	case 0x3a: */	/* Defect List Update Failure */
2664 	/*	case 0x3d: */	/* Defect List Not Available */
2665 			goto sdintr_error;
2666 		}
2667 		/*
2668 		 * No error detected or ignored.
2669 		 */
2670 		break;
2671 
2672 	/************************************************/
2673 	/*						*/
2674 	/*	PREVENT MEDIUM REMOVABLE COMMAND	*/
2675 	/*						*/
2676 	/************************************************/
2677 	case SDCS_PREVRMB:
2678 		if (tstatus == TGST_CC) {
2679 			sdc->sdc_state = SDCS_PREVRMB|SDCS_RSENSE;
2680 			goto sdintr_rsense;
2681 		}
2682 		sdd->sdd_flags |= SDDF_INHRMV;
2683 		if (sdc->sdc_state & SDCS_ECC) {
2684 			sdc->sdc_state = SDCS_RETRY;
2685 			goto sdintr_msel_reset;
2686 		}
2687 		sdc->sdc_state = SDCS_NORMAL;
2688 		goto sdintr_exec;
2689 		break;
2690 
2691 	/****************************************/
2692 	/*					*/
2693 	/*	REZERO done & RETRY COMMAND	*/
2694 	/*					*/
2695 	/****************************************/
2696 	case SDCS_ECC|SDCS_ECC_HOLD|SDCS_REZERO:
2697 		if (sdc->sdc_firmware & SDCFW_DEFMODE) {
2698 			sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY;
2699 			goto sdintr_stst;
2700 		}
2701 
2702 		sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD;
2703 		goto sdintr_msel_set;
2704 
2705 	/********************************/
2706 	/*				*/
2707 	/*	RETRY COMMAND		*/
2708 	/*				*/
2709 	/********************************/
2710 	case SDCS_RETRY:
2711 		sdc->sdc_state = SDCS_NORMAL;
2712 		goto sdintr_exec;
2713 
2714 	/************************************************/
2715 	/*						*/
2716 	/*	ERROR CORRECTION ON MODE SELECT result	*/
2717 	/*						*/
2718 	/************************************************/
2719 	case SDCS_ECC:
2720 		if (tstatus != TGST_GOOD) {
2721 			printf("sd%d: bad target status 0x%x\n",
2722 						unit, sc->sc_tstatus);
2723 			goto sdintr_error;
2724 		}
2725 sdintr_ecc:
2726 		if (bp->b_flags & B_READ) {
2727 			sdc->sdc_state = SDCS_ECC|SDCS_RASREAD;
2728 			im->im_tab.b_active = 2;
2729 			scop_rdwr(intr, sc, slave, SCSI_INTEN,
2730 					B_READ, sdwork,
2731 					sdd->sdd_badsect, sdd->sdd_sectsize);
2732 			return;
2733 		}
2734 		goto sdintr_rasblk;
2735 
2736 	/************************************************/
2737 	/*						*/
2738 	/*	READ DATA from BAD BLOCK result		*/
2739 	/*						*/
2740 	/************************************************/
2741 	case SDCS_ECC|SDCS_RASREAD:
2742 		if (tstatus == TGST_CC) {
2743 			sdc->sdc_state = SDCS_ECC|SDCS_RASREAD|SDCS_RSENSE;
2744 			goto sdintr_rsense;
2745 		} else if (tstatus != TGST_GOOD) {
2746 			printf("sd%d: bad target status 0x%x\n",
2747 						unit, sc->sc_tstatus);
2748 			printf("sd%d: cannot read block\n", unit);
2749 			goto sdintr_error;
2750 		}
2751 sdintr_rasblk:
2752 		if (sdd->sdd_flags & SDDF_WPROTECT)
2753 			goto sdintr_error;
2754 		sdc->sdc_state = SDCS_ECC|SDCS_RASBLK;
2755 		im->im_tab.b_active = 2;
2756 		scop_rasblk(intr, sc, slave, SCSI_INTEN, sdd->sdd_badsect);
2757 		sdd->sdd_flags &= ~SDDF_VBADSECT;
2758 		return;
2759 
2760 	/****************************************/
2761 	/*					*/
2762 	/*	REASSIGN BLOCK result		*/
2763 	/*					*/
2764 	/****************************************/
2765 	case SDCS_ECC|SDCS_RASBLK:
2766 		if (tstatus == TGST_CC) {
2767 			sdc->sdc_state = SDCS_ECC|SDCS_RASBLK|SDCS_RSENSE;
2768 			goto sdintr_rsense;
2769 		} else if (tstatus != TGST_GOOD) {
2770 			printf("sd%d: bad target status 0x%x\n",
2771 						unit, sc->sc_tstatus);
2772 			goto sdintr_error;
2773 		}
2774 		printf("sd%d: block %d is reassigned\n",
2775 			unit, sdd->sdd_badsect);
2776 		if (bp->b_flags & B_READ) {
2777 sdintr_raswrite:
2778 			sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE;
2779 			im->im_tab.b_active = 2;
2780 			scop_rdwr(intr, sc, slave, SCSI_INTEN,
2781 					B_WRITE, sdwork,
2782 					sdd->sdd_badsect, sdd->sdd_sectsize);
2783 			return;
2784 		}
2785 		sdc->sdc_state = SDCS_RETRY;
2786 		goto sdintr_msel_reset;
2787 
2788 	/************************************************/
2789 	/*						*/
2790 	/*	WRITE DATA to REASSIGNED BLOCK result	*/
2791 	/*						*/
2792 	/************************************************/
2793 	case SDCS_ECC|SDCS_RASWRITE:
2794 		if (tstatus == TGST_CC) {
2795 			sdc->sdc_state = SDCS_ECC|SDCS_RASWRITE|SDCS_RSENSE;
2796 			goto sdintr_rsense;
2797 		} else if (tstatus != TGST_GOOD) {
2798 			printf("sd%d: bad target status 0x%x\n",
2799 						unit, sc->sc_tstatus);
2800 			goto sdintr_error;
2801 		}
2802 		sdc->sdc_state = SDCS_RETRY;
2803 		goto sdintr_msel_reset;
2804 
2805 	/****************************************/
2806 	/*					*/
2807 	/*	reset ECC & RETRY TIMES		*/
2808 	/*					*/
2809 	/****************************************/
2810 	case SDCS_ECCOFF|SDCS_RETRY:
2811 		sdc->sdc_state = SDCS_RETRY;
2812 		goto sdintr_msel_reset;
2813 
2814 	/********************************************************/
2815 	/*							*/
2816 	/*	READ DATA from BAD BLOCK result in faliure	*/
2817 	/*							*/
2818 	/********************************************************/
2819 	case SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA:
2820 		if (tstatus == TGST_CC) {
2821 			sdc->sdc_state =
2822 				SDCS_ECC|SDCS_RASBLK|SDCS_LOSTDATA|SDCS_RSENSE;
2823 			goto sdintr_rsense;
2824 		} else if (tstatus != TGST_GOOD) {
2825 			printf("sd%d: rasblk: bad target status 0x%x\n",
2826 				unit, sc->sc_tstatus);
2827 			goto sdintr_error;
2828 		}
2829 		bzero(sdwork, sdd->sdd_sectsize);
2830 		scop_rdwr(intr, sc, slave, SCSI_INTDIS,
2831 			B_WRITE, sdwork, sdd->sdd_badsect, sdd->sdd_sectsize);
2832 		printf("sd%d: block %d is reassigned (lost data)\n",
2833 			unit, sdd->sdd_badsect);
2834 		goto sdintr_error;
2835 
2836 	/****************************************/
2837 	/*					*/
2838 	/*	issue START UNIT command	*/
2839 	/*					*/
2840 	/****************************************/
2841 	case SDCS_ECC|SDCS_ECC_HOLD:
2842 		/*
2843 		 * Drive not ready... so start..
2844 		 */
2845 		sdc->sdc_state = SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY;
2846 sdintr_stst:
2847 		timeout(delay_start, (caddr_t)ii, hz);
2848 		return;
2849 
2850 	/****************************************/
2851 	/*					*/
2852 	/*	RETRY with ECC & more RETRYS	*/
2853 	/*					*/
2854 	/****************************************/
2855 	case SDCS_ECC|SDCS_ECC_HOLD|SDCS_RETRY:
2856 		sdc->sdc_state = SDCS_ECCOFF;
2857 sdintr_exec:
2858 		if (sdc->sdc_countcc++ > MAXRETRYCNT)
2859 			goto sdintr_error;
2860 		sdexec(bp);
2861 		return;
2862 
2863 	/****************************************/
2864 	/*					*/
2865 	/*	reset ECC & RETRY TIMES		*/
2866 	/*					*/
2867 	/****************************************/
2868 	case SDCS_ECCOFF:
2869 		if (tstatus == TGST_CC) {
2870 			sdc->sdc_state = SDCS_ECCOFF|SDCS_RSENSE;
2871 			goto sdintr_rsense;
2872 		} else if (tstatus != TGST_GOOD) {
2873 			printf("sd%d: bad target status 0x%x\n",
2874 				unit, sc->sc_tstatus);
2875 			goto sdintr_error;
2876 		}
2877 		sdc->sdc_state = SDCS_NORMAL;
2878 		goto sdintr_msel_reset;
2879 
2880 sdintr_msel_set:
2881 		/*
2882 		 * set more ERROR RECOVERY PARAMETERS
2883 		 */
2884 		if ((erp_page = sdi->max_ERP_page) == NULL)
2885 			goto check_target_status;
2886 		bzero((caddr_t)sc->sc_param, 4);
2887 		len = *(erp_page + 1) + 2;
2888 		bcopy(erp_page, &sc->sc_param[4], len);
2889 
2890 		im->im_tab.b_active = 2;
2891 		scop_mselect(intr, sc, slave, SCSI_INTEN,
2892 				(SDM_PF<<24) + len +4, (caddr_t)0);
2893 		return;
2894 
2895 sdintr_msel_reset:
2896 		if (sdc->sdc_firmware & SDCFW_DEFMODE)
2897 			goto sdintr_exec;
2898 
2899 		/*
2900 		 * set normal ERROR RECOVERY PARAMETERS
2901 		 */
2902 		erp_page = sdi->ERP_page;
2903 		bzero((caddr_t)sc->sc_param, 4);
2904 		len = *(erp_page + 1) + 2;
2905 		bcopy(erp_page, &sc->sc_param[4], len);
2906 
2907 		im->im_tab.b_active = 2;
2908 		scop_mselect(intr, sc, slave, SCSI_INTEN,
2909 				(SDM_PF<<24) + len +4, (caddr_t)0);
2910 		return;
2911 
2912 sdintr_error:
2913 		bp->b_flags |= B_ERROR;
2914 		if (sdc->sdc_state & SDCS_ECC) {
2915 			sdc->sdc_state = SDCS_NORMAL;
2916 			goto sdintr_msel_reset;
2917 		}
2918 		break;
2919 
2920 	/*
2921 	 * UNKNOWN STATUS
2922 	 */
2923 	default:
2924 		printf("sd%d: unknown status (0x%x)\n", unit, sdc->sdc_state);
2925 		goto sdintr_error;
2926 	}
2927 
2928 sdintr_done:
2929 
2930 	if (bp->b_flags & B_ERROR) {
2931         printf("%s%d%c: hard error sn%d ", "sd",
2932             minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
2933 		printf("\n");
2934 	}
2935 	sdd->sdd_lastblk = dkblock(bp) + btodb(bp->b_bcount - bp->b_resid);
2936 	sdc->sdc_countcc = 0;
2937 	sdc->sdc_retrycnt = 0;
2938 	sdd->sdd_flags &= ~SDDF_VBADSECT;
2939 
2940 	if (im->im_tab.b_active) {
2941 		im->im_tab.b_active = 0;
2942 		im->im_tab.b_errcnt = 0;
2943 		im->im_tab.b_actf = dp->b_forw;
2944 		dp->b_active = 0;
2945 		dp->b_errcnt = 0;
2946 		dp->b_actf = bp->av_forw;
2947 		if (bp == &csdbuf[unit]) {
2948 			register struct scsi *ksc = &kernscsi[unit];
2949 			/* copy result */
2950 			bcopy((caddr_t)sc, (caddr_t)ksc, sizeof(struct scsi));
2951 		}
2952 
2953 		iodone(bp);
2954 
2955 		/*
2956 		 * If this unit has more work to do,
2957 		 * then start it up right away.
2958 		 */
2959 		if (dp->b_actf)
2960 			sdustart(ii);
2961 	}
2962 	as &= ~(1 << slave);
2963 
2964 	sdc->sdc_state = SDCS_NORMAL;
2965 
2966 	/*
2967 	 * UNLOCK SCSI access
2968 	 */
2969 	sdc->sdc_firmware &= ~SDCFW_BUSY;
2970 
2971 start:
2972 	/*
2973 	 * Process other units which need attention.
2974 	 * For each unit which needs attention, call
2975 	 * the unit start routine to place the slave
2976 	 * on the controller device queue.
2977 	 */
2978 	sdc->sdc_softas = 0;
2979 	while (unit = ffs(as)) {
2980 		unit--;
2981 		as &= ~(1 << unit);
2982 		sdustart(sdip[im->im_ctlr][unit]);
2983 	}
2984 	/*
2985 	 * If the controller is not transferring,
2986 	 * but there are devices ready to transfer,
2987 	 * start the controller.
2988 	 */
2989 	if (im->im_tab.b_actf && im->im_tab.b_active == 0)
2990 		(void) sdstart(im);
2991 }
2992 
2993 wait_re_init_done(bp)
2994 	register struct buf *bp;
2995 {
2996 	if (re_init_done >= 2)
2997 		sdexec(bp);
2998 	else
2999 		timeout(wait_re_init_done, bp, 10*hz);
3000 }
3001 
3002 delay_start(ii)
3003 	struct iop/**/_device *ii;
3004 {
3005 	ii->ii_mi->im_tab.b_active = 2;
3006 	scop_stst(ii->ii_intr, get_scsi(ii->ii_intr), ii->ii_slave,
3007 			SCSI_INTEN, SDSS_START);
3008 }
3009 
3010 delay_medrmv(ii)
3011 	struct iop/**/_device *ii;
3012 {
3013 	ii->ii_mi->im_tab.b_active = 2;
3014 	scop_medrmv(ii->ii_intr, get_scsi(ii->ii_intr), ii->ii_slave,
3015 			SCSI_INTEN, SDRMV_PREV);
3016 }
3017 
3018 sderrordisp(rsen_data, ii)
3019 	u_char *rsen_data;
3020 	struct iop/**/_device *ii;
3021 {
3022 	register struct sc_extnd *sce;
3023 	register struct sdc_softc *sdc;
3024 	register struct sdd_softc *sdd;
3025 	register int unit;
3026 	register int code;
3027 	struct sc_nextnd *scn;
3028 	struct msg_list *ml;
3029 
3030 	unit = ii->ii_unit;
3031 	sdc = &sdc_softc[ii->ii_ctlr];
3032 	sdd = &sdd_softc[unit];
3033 
3034 	sce = (struct sc_extnd *)rsen_data;
3035 
3036 	if (sce->sce_extend == 0x70) {
3037 		/*
3038 		 * Extended Sense data
3039 		 */
3040 		code = sce->sce_sdecode;
3041 
3042 		if (code & 0x80)
3043 			ml = ecodelist_mo;
3044 		else
3045 			ml = ecodelist;
3046 
3047 		if (sce->sce_advalid) {
3048 			if ((sdd->sdd_flags & SDDF_VBADSECT) == 0) {
3049 #ifdef mips
3050 				sdd->sdd_badsect = (sce->sce_infob1 << 24) +
3051 						   (sce->sce_infob2 << 16) +
3052 						   (sce->sce_infob3 <<  8) +
3053 						   (sce->sce_infob4);
3054 #else
3055 				sdd->sdd_badsect = *((int *)&sce->sce_infob1);
3056 #endif
3057 				sdd->sdd_flags |= SDDF_VBADSECT;
3058 			}
3059 		}
3060 
3061 		if (!rsense_msg_disp && !isdispmsg(code, ml, sdc->sdc_countcc))
3062 			return (code);
3063 
3064 		if (sce->sce_advalid) {
3065 			int sn;
3066 #ifdef mips
3067 			sn = (sce->sce_infob1 << 24) +
3068 			     (sce->sce_infob2 << 16) +
3069 			     (sce->sce_infob3 <<  8) +
3070 			     (sce->sce_infob4);
3071 #else
3072 			sn = *((int *)&sce->sce_infob1);
3073 #endif
3074 			if (sce->sce_addlen >= 5) {
3075 				printf("sd%d(sn %d): skey=0x%x, code=0x%x\n",
3076 					unit, sn, sce->sce_skey, code);
3077 			} else {
3078 				printf("sd%d(sn %d): skey=0x%x\n",
3079 					unit, sn, sce->sce_skey);
3080 			}
3081 		} else {
3082 			if (sce->sce_addlen >= 5)
3083 				printf("sd%d: skey=0x%x, code=0x%x\n",
3084 					unit, sce->sce_skey, code);
3085 			else
3086 				printf("sd%d: skey=0x%x\n",
3087 					unit, sce->sce_skey);
3088 		}
3089 		if (sce->sce_addlen >= 6)
3090 			printf("sd%d: ASCQ=0x%x\n", unit, sce->sce_ascq);
3091 		{
3092 			u_char *p;
3093 			int len;
3094 
3095 			len = 8 + sce->sce_addlen;
3096 			if (len > RSEN_CNT)
3097 				len = RSEN_CNT;
3098 			p = (u_char *)sce;
3099 			printf("sd%d: ", unit);
3100 			while (len--)
3101 				printf("%x ", *p++);
3102 			printf("\n");
3103 		}
3104 	} else {
3105 		/*
3106 		 * Non-extended Sense data
3107 		 */
3108 		scn = (struct sc_nextnd *)rsen_data;
3109 
3110 		code = scn->scn_ecode;
3111 		ml = ecodelist;
3112 		if (sce->sce_advalid) {
3113 			if ((sdd->sdd_flags & SDDF_VBADSECT) == 0) {
3114 				sdd->sdd_badsect = scn->scn_secno;
3115 				sdd->sdd_flags |= SDDF_VBADSECT;
3116 			}
3117 		}
3118 		if (rsense_msg_disp || isdispmsg(code, ml, sdc->sdc_countcc)) {
3119 			if (sce->sce_advalid)
3120 				printf("sd%d(sn %d): code=0x%x\n",
3121 					unit, scn->scn_secno, code);
3122 			else
3123 				printf("sd%d: code=0x%x\n", unit, code);
3124 		}
3125 	}
3126 	return (code);
3127 }
3128 
3129 void
3130 sdminphys(bp)
3131 	struct buf *bp;
3132 {
3133 	if (bp->b_bcount > MAXSDPHYS)
3134 		bp->b_bcount = MAXSDPHYS;
3135 }
3136 
3137 
3138 #define	sdphysio	physio
3139 
3140 sdread(dev, uio, flag)
3141 	register dev_t dev;
3142 	struct uio *uio;
3143 	int flag;
3144 {
3145 	register struct iop/**/_device *ii;
3146 	register int unit;
3147 
3148 	unit = dev2unit(dev);
3149 	if (unit >= nsd || (ii = sddinfo[unit]) == 0)
3150 		return (ENXIO);
3151 
3152 	return (sdphysio(sdstrategy, &rsdbuf[unit], dev, B_READ, sdminphys, uio));
3153 }
3154 
3155 sdwrite(dev, uio, flag)
3156 	register dev_t dev;
3157 	struct uio *uio;
3158 	int flag;
3159 {
3160 	register struct iop/**/_device *ii;
3161 	register int unit;
3162 
3163 	unit = dev2unit(dev);
3164 	if (unit >= nsd || (ii = sddinfo[unit]) == 0)
3165 		return (ENXIO);
3166 
3167 	return (sdphysio(sdstrategy, &rsdbuf[unit], dev, B_WRITE, sdminphys, uio));
3168 }
3169 
3170 #define MAXBL 256
3171 
3172 /*ARGSUSED*/
3173 sdioctl(dev, cmd, data, flag)
3174 	dev_t dev;
3175 	int cmd;
3176 	caddr_t data;
3177 	int flag;
3178 {
3179 	register struct iop/**/_device *ii;
3180 	register struct sc_ureq *scu;
3181 	register struct sdst *st;
3182 	register struct scsi *sc;
3183 	register int unit;
3184 	register int ctlr;
3185 	register int slave;
3186 	struct sdc_softc *sdc;
3187 	struct sdd_softc *sdd;
3188 	struct Partinfo *pi;
3189 	struct dkst *di;
3190 	struct buf *bp;
3191 	struct sddevinfo *sdi;
3192 	struct sdst *stp;
3193 	struct scsi uscsi;
3194 	int error;
3195 	int i;
3196 	int s;
3197 	int tstatus;
3198 	char *p;
3199 	int blkno, count;
3200 
3201 	unit = dev2unit(dev);
3202 	if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
3203 		return (ENXIO);
3204 
3205 	slave = ii->ii_slave;
3206 	ctlr = ii->ii_ctlr;
3207 	sdc = &sdc_softc[ctlr];
3208 	sdd = &sdd_softc[unit];
3209 	sc = &uscsi;
3210 
3211 	error = 0;
3212 	switch (cmd) {
3213 
3214 	case DIOCWLABEL:
3215 		if (*(int *)data & SD_F_ENW)
3216 			ii->ii_flags |= SD_F_ENW;
3217 		else
3218 			ii->ii_flags &= ~SD_F_ENW;
3219 		break;
3220 
3221 	case DIOCGDINFO:
3222 		*(struct disklabel *)data = sdlabel[unit];
3223 		break;
3224 
3225 	case DIOCSDINFO:
3226 		sdlabel[unit] = *(struct disklabel *)data;
3227 		disklabel2sdst(unit, &sdlabel[unit], &sdstdrv[unit]);
3228 		break;
3229 
3230 	case DIOCWDINFO:
3231 	case DKIOCRGEOM:
3232 		switch (cmd) {
3233 		case DKIOCRGEOM:
3234 			st = &sdstdrv[unit];
3235 			sdi = &sddevinfo[ii->ii_type];
3236 			stp = sdi->sdstp;
3237 
3238 			st->ncyl = stp->ncyl;	/* # cylinders / drive */
3239 			st->ntrak = stp->ntrak;	/* # tracks / cylinder */
3240 			st->nsect = stp->nsect;	/* # sectors / track */
3241 			st->rps = stp->rps;	/* # revolutions / second */
3242 
3243 			sdst2disklabel(unit, st, &sdlabel[unit]);
3244 
3245 			if (*(int *)data == RGEOM_SDINFO)
3246 				goto done;
3247 
3248 			break;
3249 
3250 		case DIOCWDINFO:
3251 			sdlabel[unit] = *(struct disklabel *)data;
3252 
3253 			break;
3254 		}
3255 
3256 		/*
3257 		 * Common code for DIOCWDINFO and DKIOCRGEOM
3258 		 */
3259 
3260 		/**** READ sector 0 ****/
3261 		/*
3262 		 * LOCK sdtmp buffer
3263 		 */
3264 		s = splclock();
3265 		while (sdtmp_stat & B_BUSY) {
3266 			sdtmp_stat |= B_WANTED;
3267 			sleep((caddr_t)sdtmp, PRIBIO);
3268 		}
3269 		sdtmp_stat |= B_BUSY;
3270 		splx(s);
3271 
3272 		bzero(sdtmp, DEV_BSIZE);
3273 
3274 		if ((sdd->sdd_flags & SDDF_NONFMT) == 0) {
3275 			scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3276 			uscsi.sc_cpoint = sdtmp;
3277 			uscsi.sc_ctrnscnt = DEV_BSIZE;
3278 			uscsi.sc_opcode = SCOP_READ;
3279 			uscsi.sc_lad = 0;
3280 			uscsi.sc_count = 1;
3281 			error = sdcmd(dev, &uscsi);
3282 		} else {
3283 			error = EIO;
3284 		}
3285 
3286 		if (error) {
3287 			/*
3288 			 * UNLOCK sdtmp buffer
3289 			 */
3290 			s = splclock();
3291 			if (sdtmp_stat & B_WANTED)
3292 				wakeup((caddr_t)sdtmp);
3293 			sdtmp_stat &= ~(B_BUSY|B_WANTED);
3294 			splx(s);
3295 
3296 			break;
3297 		}
3298 
3299 		*(struct disklabel *)(sdtmp + LABELOFFSET) = sdlabel[unit];
3300 		disklabel2diskinfo(unit, &sdlabel[unit],
3301 				    &((struct firstsector *)sdtmp)->diskinfo);
3302 
3303 		/**** WRITE sector 0 ****/
3304 
3305 		if (error == 0) {
3306 			if ((sdd->sdd_flags & SDDF_NONFMT) == 0) {
3307 				scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3308 				uscsi.sc_cpoint = sdtmp;
3309 				uscsi.sc_ctrnscnt = DEV_BSIZE;
3310 				uscsi.sc_opcode = SCOP_WRITE;
3311 
3312 				uscsi.sc_lad = 0;
3313 				uscsi.sc_count = 1;
3314 
3315 				error = sdcmd(dev, &uscsi);
3316 			} else
3317 				error = EIO;
3318 		}
3319 
3320 		/*
3321 		 * UNLOCK sdtmp buffer
3322 		 */
3323 		s = splclock();
3324 		if (sdtmp_stat & B_WANTED)
3325 			wakeup((caddr_t)sdtmp);
3326 		sdtmp_stat &= ~(B_BUSY|B_WANTED);
3327 		splx(s);
3328 
3329 		disklabel2sdst(unit, &sdlabel[unit], &sdstdrv[unit]);
3330 
3331 		break;
3332 
3333 	case DKIOCGGEOM:
3334 		st = &sdstdrv[unit];
3335 		di = (struct dkst *)data;
3336 
3337 		di->dks_ncyl = st->ncyl;	/* # cylinders / drive */
3338 		di->dks_ntrak = st->ntrak;	/* # tracks / cylinder */
3339 		di->dks_nsect = st->nsect;	/* # sectors / track */
3340 		di->dks_rps = st->rps;		/* # revolutions / second */
3341 
3342 		break;
3343 
3344 	case DKIOCSGEOM:
3345 		st = &sdstdrv[unit];
3346 		di = (struct dkst *)data;
3347 
3348 		st->ncyl = di->dks_ncyl;	/* # cylinders / drive */
3349 		st->ntrak = di->dks_ntrak;	/* # tracks / cylinder */
3350 		st->nsect = di->dks_nsect;	/* # sectors / track */
3351 		st->rps = di->dks_rps;		/* # revolutions / second */
3352 
3353 		sdst2disklabel(unit, st, &sdlabel[unit]);
3354 		break;
3355 
3356 	case DKIOCGPART:
3357 	case DKIOCSPART:
3358 		/*
3359 		 * partition information
3360 		 */
3361 		st = &sdstdrv[unit];
3362 		pi = (struct Partinfo *)data;
3363 
3364 		if (cmd == DKIOCGPART) {
3365 			pi->dp_nblocks = st->sizes[dev2part(dev)].sd_nblocks;
3366 			pi->dp_blkoff = st->sizes[dev2part(dev)].sd_blkoff;
3367 		} else {
3368 			st->sizes[dev2part(dev)].sd_nblocks = pi->dp_nblocks;
3369 			st->sizes[dev2part(dev)].sd_blkoff = pi->dp_blkoff;
3370 
3371 			sdst2disklabel(unit, st, &sdlabel[unit]);
3372 		}
3373 		break;
3374 
3375 	case DKIOCGUNIT:
3376 		*(int *)data = slave;
3377 		break;
3378 
3379 	case DKIOCGCHAN:
3380 		*(int *)data = ii->ii_intr;
3381 		break;
3382 
3383 	case DKIOCSEEK:
3384 		scinit(sc, slave, sdd->sdd_sectsize);
3385 		sc->sc_opcode = SCOP_SEEK;
3386 		sc->sc_lad = *(int *)data;
3387 
3388 		(void) sdcmd(dev, sc);
3389 		tstatus = sc->sc_tstatus & TGSTMASK;
3390 		if ((sc->sc_istatus != INST_EP) || (tstatus != TGST_GOOD))
3391 			error = ESPIPE;
3392 		break;
3393 
3394 	case DKIOCRSEC0:
3395 	case DKIOCRBOOT1:
3396 	case DKIOCRBOOT:
3397 		if (sdd->sdd_flags & SDDF_NONFMT) {
3398 			error = EIO;
3399 			break;
3400 		}
3401 		switch (cmd) {
3402 
3403 		case DKIOCRSEC0:
3404 			blkno = 0;
3405 			count = 1;
3406 			break;
3407 
3408 		case DKIOCRBOOT1:
3409 			blkno = 1;
3410 			count = 15;
3411 			break;
3412 
3413 		default:
3414 			blkno = 0;
3415 			count = 16;
3416 		}
3417 		p = (char *)*(int *)data;
3418 		for (i = 0; !error && i < count; i++) {
3419 			s = splclock();
3420 			while (sdtmp_stat & B_BUSY) {
3421 				sdtmp_stat |= B_WANTED;
3422 				sleep((caddr_t)sdtmp, PRIBIO);
3423 			}
3424 			sdtmp_stat |= B_BUSY;
3425 			splx(s);
3426 			scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3427 			uscsi.sc_cpoint = sdtmp;
3428 			uscsi.sc_ctrnscnt = DEV_BSIZE;
3429 			uscsi.sc_opcode = SCOP_READ;
3430 			uscsi.sc_lad = blkno;
3431 			uscsi.sc_count = 1;
3432 			if (error = sdcmd(dev, &uscsi))
3433 				goto dkior_done;
3434 			if (error = copyout(sdtmp, p, DEV_BSIZE))
3435 				goto dkior_done;
3436 			blkno++;
3437 			p += DEV_BSIZE;
3438 
3439 dkior_done:
3440 			s = splclock();
3441 			if (sdtmp_stat & B_WANTED)
3442 				wakeup((caddr_t)sdtmp);
3443 			sdtmp_stat &= ~(B_BUSY|B_WANTED);
3444 			splx(s);
3445 		}
3446 		break;
3447 
3448 	case DKIOCWSEC0:
3449 	case DKIOCWBOOT1:
3450 	case DKIOCWBOOT:
3451 		if (sdd->sdd_flags & SDDF_NONFMT) {
3452 			error = EIO;
3453 			break;
3454 		}
3455 		switch (cmd) {
3456 
3457 		case DKIOCWSEC0:
3458 			blkno = 0;
3459 			count = 1;
3460 			break;
3461 
3462 		case DKIOCWBOOT1:
3463 			blkno = 1;
3464 			count = 15;
3465 			break;
3466 
3467 		default:
3468 			blkno = 0;
3469 			count = 16;
3470 		}
3471 		p = (char *)*(int *)data;
3472 		for (i = 0; !error && i < count; i++) {
3473 			s = splclock();
3474 			while (sdtmp_stat & B_BUSY) {
3475 				sdtmp_stat |= B_WANTED;
3476 				sleep(sdtmp, PRIBIO);
3477 			}
3478 			sdtmp_stat |= B_BUSY;
3479 			splx(s);
3480 			if (error = copyin(p, sdtmp, DEV_BSIZE))
3481 				goto dkiow_done;
3482 			scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3483 			uscsi.sc_cpoint = sdtmp;
3484 			uscsi.sc_ctrnscnt = DEV_BSIZE;
3485 			uscsi.sc_opcode = SCOP_WRITE;
3486 			uscsi.sc_lad = blkno;
3487 			uscsi.sc_count = 1;
3488 			if (error = sdcmd(dev, &uscsi))
3489 				goto dkiow_done;
3490 			blkno++;
3491 			p += DEV_BSIZE;
3492 
3493 dkiow_done:
3494 			s = splclock();
3495 			if (sdtmp_stat & B_WANTED)
3496 				wakeup(sdtmp);
3497 			sdtmp_stat &= ~(B_BUSY|B_WANTED);
3498 			splx(s);
3499 		}
3500 		break;
3501 
3502 	case SDIOC_PRVRMV:
3503 	case SDIOC_ALWRMV:
3504 		/*
3505 		 * prevent/allow medium removal
3506 		 */
3507 		scinit(sc, ii->ii_slave, sdd->sdd_sectsize);
3508 		sc->sc_opcode = SCOP_MEDRMV;
3509 		sc->sc_count = (cmd==SDIOC_PRVRMV)? SDRMV_PREV : SDRMV_ALLOW;
3510 		if (cmd == SDIOC_PRVRMV)
3511 			sdd->sdd_flags |= SDDF_INHRMV;
3512 		else
3513 			sdd->sdd_flags &= ~SDDF_INHRMV;
3514 
3515 		error = sdcmd(dev, sc);
3516 		break;
3517 
3518 	case SDIOC_SXUSE:
3519 		if (isalone(unit) != ONLY_ONE)
3520 			return (EBUSY);
3521 		sdd->sdd_flags |= SDDF_XUSE;
3522 		break;
3523 
3524 	case SDIOC_RXUSE:
3525 		sdd->sdd_flags &= ~SDDF_XUSE;
3526 		break;
3527 
3528 	case SDIOC_ERSON:
3529 		sdd->sdd_flags &= ~SDDF_ERASEOFF;
3530 		break;
3531 
3532 	case SDIOC_ERSOFF:
3533 		if ((sdd->sdd_flags & SDDF_XUSE) != 0)
3534 			return (EBUSY);
3535 		sdd->sdd_flags |= SDDF_ERASEOFF;
3536 		sdd->sdd_flags &= ~SDDF_NONFMT;
3537 		break;
3538 
3539 	case SDIOC_FORMAT:
3540 		/*
3541 		 * format unit
3542 		 */
3543 		if ((flag & FWRITE) == 0)
3544 			return (EINVAL);
3545 		if (isalone(unit) != ONLY_ONE)
3546 			return (EBUSY);
3547 		sdd->sdd_flags |= SDDF_XUSE;
3548 		sdd->sdd_flags &= ~(SDDF_NONFMT|SDDF_FMTDONE|SDDF_SAMEDSK);
3549 		scinit(sc, ii->ii_slave, sdd->sdd_sectsize);
3550 		sc->sc_ctrnscnt = 4;
3551 		sc->sc_opcode = SCOP_FMT;
3552 
3553 		sc->sc_lad = ((sddevinfo[ii->ii_type].fmt_opts & FMT_DLFMT)
3554 				| SDF_FMTDAT) << 16;
3555 
3556 		switch (sddevinfo[ii->ii_type].type) {
3557 
3558 		case SMO_S501:
3559 		case SMO_S501_ISO:
3560 		case SMO_S501_ISO2:
3561 			sc->sc_lad |= ((SDF_MKCDA|SDF_MKPLST) << 8);
3562 			break;
3563 
3564 		default:
3565 			break;
3566 		}
3567 
3568 		{
3569 			struct fmt_data *fdata = (struct fmt_data *)data;
3570 
3571 			error = copyin((caddr_t)fdata->dlh, sc->sc_param, 4);
3572 			if (error != 0) {
3573 				sdd->sdd_flags &= ~SDDF_XUSE;
3574 				break;
3575 			}
3576 			if (fdata->noglist)
3577 				sc->sc_lad |= (SDF_CMPLST<<16);
3578 		}
3579 
3580 		if (sdd->sdd_flags & SDDF_ERASEOFF)
3581 			sc->sc_ctrl = 0x40;
3582 
3583 		error = sdcmd(dev, sc);
3584 		sdd->sdd_flags &= ~SDDF_XUSE;
3585 		break;
3586 
3587 	case SDIOC_FORMAT2:
3588 		/*
3589 		 * format unit
3590 		 */
3591 		if ((flag & FWRITE) == 0)
3592 			return (EINVAL);
3593 		if (isalone(unit) != ONLY_ONE)
3594 			return (EBUSY);
3595 		sdd->sdd_flags |= SDDF_XUSE;
3596 		sdd->sdd_flags &= ~(SDDF_NONFMT|SDDF_FMTDONE|SDDF_SAMEDSK);
3597 
3598 		scu = (struct sc_ureq *)data;
3599 		error = sd_scu_exec(dev, scu, sc);
3600 		sdd->sdd_flags &= ~SDDF_XUSE;
3601 		break;
3602 
3603 	case SDIOC_GSTOPT:
3604 	case SDIOC_SSTOPT:
3605 		/*
3606 		 * get/set stop-unit timer
3607 		 */
3608 		if (cmd == SDIOC_GSTOPT)
3609 			*(int *)data = sdd->sdd_stoptime;
3610 		else {
3611 			if (*(int *)data == 0)
3612 				return (EINVAL);
3613 			sdd->sdd_stoptime = *(int *)data;
3614 		}
3615 		break;
3616 
3617 	case SDIOC_SEJECT:
3618 		/*
3619 		 * set auto eject flag
3620 		 */
3621 		sdd->sdd_flags |= SDDF_REQ_EJECT;
3622 		break;
3623 
3624 	case SDIOC_GFLAGS:
3625 		/*
3626 		 * get ii->ii_flags
3627 		 */
3628 		*(int *)data = ii->ii_flags;
3629 		break;
3630 
3631 	case SDIOC_SFLAGS:
3632 		/*
3633 		 * set ii->ii_flags
3634 		 */
3635 		ii->ii_flags = *(int *)data;
3636 		break;
3637 
3638 	case SDIOC_RASBLK:
3639 		/*
3640 		 * reassign block
3641 		 */
3642 		{
3643 			struct sc_rab *sca = (struct sc_rab *)sc->sc_param;
3644 
3645 			scinit(sc, ii->ii_slave, sdd->sdd_sectsize);
3646 			sc->sc_opcode = SCOP_RASBLK;
3647 			sc->sc_ctrnscnt = 8;
3648 
3649 			sca->sca_dllen = 4;
3650 			sca->sca_dlad[0] = *(int *)data;
3651 
3652 			error = sdcmd(dev, sc);
3653 		}
3654 		break;
3655 
3656 	case SDIOC_GNICKNAME:
3657 		{
3658 			int len;
3659 
3660 			len = strlen(sddevinfo[ii->ii_type].call_name);
3661 
3662 			if (len > IOCPARM_MASK)
3663 				len = IOCPARM_MASK;
3664 
3665 			error = copyout(
3666 				(caddr_t) sddevinfo[ii->ii_type].call_name,
3667 				(caddr_t) *(int *)data,
3668 				len);
3669 		}
3670 		break;
3671 
3672 	case SDIOC_GTYPINDEX:
3673 		*(int *)data = (int)ii->ii_type;
3674 		break;
3675 
3676 #ifdef SDIOC_SSYNCPARAM
3677 	case SDIOC_SSYNCPARAM:
3678 		{
3679 		struct sync_param *syncp;
3680 
3681 		syncp = (struct sync_param *)data;
3682 		scinit(sc, ii->ii_slave, sdd->sdd_sectsize);
3683 		sc->sc_opcode = SCOP_TST;
3684 		sc->sc_message = MSG_EXTND;	/* extended message */
3685 		sc->sc_param[0] = MSG_EXTND;
3686 		sc->sc_param[1] = 0x03;
3687 		sc->sc_param[2] = 0x01;		/* synchronous transfer */
3688 		sc->sc_param[3] = syncp->tr_period;	/* transfer period */
3689 		sc->sc_param[4] = syncp->tr_offset;	/* REQ offset */
3690 
3691 		(void) sdcmd(dev, sc);
3692 
3693 		syncp = &sd_sync_param[unit];
3694 		syncp->tr_period = sc->sc_param[3];
3695 		syncp->tr_offset = sc->sc_param[4];
3696 
3697 		if (syncp->tr_offset)
3698 			sdd->sdd_flags |= SDDF_SYNCTR;
3699 		else
3700 			sdd->sdd_flags &= ~SDDF_SYNCTR;
3701 		}
3702 		break;
3703 
3704 	case SDIOC_GSYNCPARAM:
3705 		{
3706 		struct sync_param *syncp = (struct sync_param *)data;
3707 
3708 		syncp->tr_period = sd_sync_param[unit].tr_period;
3709 		syncp->tr_offset = sd_sync_param[unit].tr_offset;
3710 		}
3711 		break;
3712 #endif /* SDIOC_SSYNCPARAM */
3713 
3714 	case MTIOCTOP:
3715 		{
3716 			register struct mtop *mtop = (struct mtop *)data;
3717 			register int lba;
3718 			int rest;
3719 			int blength;
3720 
3721 			switch (mtop->mt_op) {
3722 
3723 			case MTOFFL:
3724 				/*
3725 				 * set auto eject flag
3726 				 */
3727 				sdd->sdd_flags |= SDDF_REQ_EJECT;
3728 				break;
3729 
3730 #ifdef MTERASE
3731 			case MTERASE:
3732 				if (isalone(unit) != ONLY_ONE)
3733 					return (EBUSY);
3734 				sdd->sdd_flags |= SDDF_XUSE;
3735 				st = &sdstdrv[unit];
3736 				/*
3737 				 * MO disk erase
3738 				 *	block 0 to end (C partition)
3739 				 */
3740 				lba = 0;
3741 				rest = sdd->sdd_nsect;	/* C part size */
3742 				while (rest > 0) {
3743 					blength = (rest > MAXBL)? MAXBL : rest;
3744 					scinit(sc, ii->ii_slave,
3745 							sdd->sdd_sectsize);
3746 					sc->sc_opcode = SCOP_MOERASE;
3747 					sc->sc_lad = lba;
3748 					sc->sc_count = (blength % MAXBL);
3749 
3750 					(void) sdcmd(dev, sc);
3751 					lba += blength;
3752 					rest -= blength;
3753 				}
3754 				sdd->sdd_flags &= ~SDDF_XUSE;
3755 				break;
3756 #endif /* MTERASE */
3757 
3758 			default:
3759 				return (EINVAL);
3760 			}
3761 		}
3762 		break;
3763 
3764 	case SCSIIOCCMD:
3765 		scu = (struct sc_ureq *)data;
3766 		if ((scu->scu_count > 0) && scu->scu_addr) {
3767 			if (useracc(scu->scu_addr, scu->scu_count, B_WRITE)
3768 			    == NULL) {
3769 				error = EFAULT;
3770 				break;
3771 			}
3772 		}
3773 		error = sd_scu_exec(dev, scu, sc);
3774 		break;
3775 
3776 
3777 	case SDIOC_INQUIRY:
3778 		/*
3779 		 * LOCK sdtmp buffer
3780 		 */
3781 		s = splclock();
3782 		while (sdtmp_stat & B_BUSY) {
3783 			sdtmp_stat |= B_WANTED;
3784 			sleep((caddr_t)sdtmp, PRIBIO);
3785 		}
3786 		sdtmp_stat |= B_BUSY;
3787 		splx(s);
3788 
3789 		bzero((caddr_t)sdtmp, sizeof(struct sc_inq));
3790 		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize);
3791 		uscsi.sc_cpoint = sdtmp;
3792 		uscsi.sc_ctrnscnt = sizeof(struct sc_inq);
3793 		uscsi.sc_opcode = SCOP_INQUIRY;
3794 		uscsi.sc_count = sizeof(struct sc_inq);
3795 
3796 		if ((error = sdcmd(dev, &uscsi)) == 0)
3797 			bcopy((caddr_t)sdtmp, data, sizeof(struct sc_inq));
3798 		/*
3799 		 * UNLOCK open
3800 		 */
3801 		s = splclock();
3802 		if (sdtmp_stat & B_WANTED)
3803 			wakeup((caddr_t)sdtmp);
3804 		sdtmp_stat &= ~(B_BUSY|B_WANTED);
3805 		splx(s);
3806 		break;
3807 
3808 
3809 	case SCSIIOCGTIMEO:
3810 		*(int *)data = sdc->sdc_timeo;
3811 		break;
3812 
3813 	case SCSIIOCSTIMEO:
3814 		if (*(int *)data == 0)
3815 			return (EINVAL);
3816 		sdc->sdc_timeo = *(int *)data;
3817 		sdc->sdc_wticks = 0;
3818 		break;
3819 
3820 	default:
3821 		error = EINVAL;
3822 		break;
3823 	}
3824 
3825 done:
3826 	return (error);
3827 }
3828 
3829 static
3830 sd_scu_exec(dev, scu, sc)
3831 	dev_t dev;
3832 	register struct sc_ureq *scu;
3833 	register struct scsi *sc;
3834 {
3835 	struct sdd_softc *sdd;
3836 	int error;
3837 
3838 	sdd = &sdd_softc[dev2unit(dev)];
3839 
3840 	if (((scu->scu_identify & MSG_IDENT) == 0)
3841 		|| (scu->scu_identify & ~(MSG_IDENT|IDT_DISCON|IDT_DRMASK))
3842 		|| (scu->scu_addr && (scu->scu_bytesec == 0))) {
3843 		return (EINVAL);
3844 	}
3845 
3846 	bzero((caddr_t)sc, sizeof(struct scsi));
3847 	sc->sc_tstatus = scu->scu_tstatus;
3848 	sc->sc_identify = scu->scu_identify;
3849 	sc->sc_message = scu->scu_message;
3850 	sc->sc_bytesec = scu->scu_bytesec;
3851 	sc->sc_cpoint = scu->scu_addr;
3852 	sc->sc_ctrnscnt = scu->scu_count;
3853 	bcopy((caddr_t)scu->scu_cdb, &sc->sc_cdb, sizeof(sc->sc_cdb));
3854 
3855 	bcopy((caddr_t)scu->scu_param, (caddr_t)sc->sc_param,
3856 						sizeof(sc->sc_param));
3857 
3858 	sdd->sdd_flags |= SDDF_SKIPCHECK;
3859 	error = sdcmd(dev, sc);
3860 	sdd->sdd_flags &= ~SDDF_SKIPCHECK;
3861 
3862 	scu->scu_istatus = sc->sc_istatus;
3863 	scu->scu_tstatus = sc->sc_tstatus;
3864 	scu->scu_message = sc->sc_message;
3865 	bcopy((caddr_t)sc->sc_param, (caddr_t)scu->scu_param,
3866 		sizeof(sc->sc_param));
3867 	return (error);
3868 }
3869 
3870 /*ARGSUSED*/
3871 sddump(dev)
3872 	dev_t dev;
3873 {
3874 	return (ENXIO);
3875 }
3876 
3877 sdsize(dev)
3878 	register dev_t dev;
3879 {
3880 	register struct iop/**/_device *ii;
3881 	register struct sdd_softc *sdd;
3882 	register struct sdst *st;
3883 	register int unit;
3884 	int i;
3885 
3886 	unit = dev2unit(dev);
3887 	if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)
3888 		return (-1);
3889 
3890 	sdd = &sdd_softc[unit];
3891 	switch (sdc_softc[ii->ii_ctlr].sdc_firmware & SDCFW_DEVMASK) {
3892 
3893 	case SDCFW_HD:		/* Hard Disk */
3894 		st = &sdstdrv[unit];
3895 		break;
3896 
3897 	case SDCFW_MO:		/* MO only */
3898 		if ((sdd->sdd_flags & SDDF_SAMEDSK) == SDDF_DSKCHGD) {
3899 			/*
3900 			 * read partition information,
3901 			 *	and set up sdstdrv[unit]
3902 			 */
3903 			if (sd_b_open(dev, FREAD|FWRITE) != 0) {
3904 				/*
3905 				 * block device open error
3906 				 */
3907 				return (-1);
3908 			} else {
3909 				/*
3910 				 * use disk partition information
3911 				 */
3912 				st = &sdstdrv[unit];
3913 				if (isalone(unit) == ONLY_ONE)
3914 					sd_b_close(dev, 0);
3915 			}
3916 		} else if (sdd->sdd_flags & SDDF_NONFMT) {
3917 			/*
3918 			 * medium is not initialized.
3919 			 */
3920 			return (-1);
3921 		} else {
3922 			st = &sdstdrv[unit];
3923 		}
3924 		break;
3925 
3926 	default:
3927     /*  case SDCFW_CD: */
3928 		return (-1);
3929 
3930 	}
3931 
3932 	if (st->sizes == NULL)
3933 		return (-1);					/* XXX */
3934 	else
3935 		return (st->sizes[dev2part(dev)].sd_nblocks);	/* XXX */
3936 }
3937 
3938 /*
3939  * Reset driver.
3940  * Cancel software state of all pending transfers,
3941  * and restart all units and the controller.
3942  */
3943 sdreset()
3944 {
3945 	register struct iop/**/_ctlr *im;
3946 	register struct iop/**/_device *ii;
3947 	register struct sdc_softc *sdc;
3948 	register struct sdd_softc *sdd;
3949 	register int i;
3950 	register int unit;
3951 
3952 	re_init_done = 1;
3953 	for (i = 0; i < nsdc; i++) {
3954 		im = sdminfo[i];
3955 		if (im == 0)
3956 			continue;
3957 		if (im->im_alive == 0)
3958 			continue;
3959 		printf(" sdc%d: ", i);
3960 		sdc = &sdc_softc[i];
3961 		sdc->sdc_wticks = 0;
3962 
3963 		/* scop_init() is already called by screset() */
3964 
3965 		sdtmp_stat &= ~B_BUSY;
3966 
3967 		for (unit = 0; unit < nsd; unit++) {
3968 			ii = sddinfo[unit];
3969 			if (ii == 0)
3970 				continue;
3971 			if (ii->ii_alive == 0)
3972 				continue;
3973 			if (ii->ii_mi != im)
3974 				continue;
3975 
3976 			csdbuf[unit].b_flags &= ~B_BUSY;
3977 
3978 			sdd = &sdd_softc[unit];
3979 			sdd->sdd_flags = 0;
3980 
3981 			/*
3982 			 * UNLOCK SCSI access
3983 			 */
3984 			sdc->sdc_firmware &= ~SDCFW_BUSY;
3985 
3986 			if (sdslave(ii, ii->ii_addr, im->im_intr) == 0) {
3987 				printf("sd%d: not ready\n", ii->ii_slave);
3988 				continue;
3989 			}
3990 			sdattach(ii);
3991 		}
3992 	}
3993 	re_init_done = 2;
3994 }
3995 
3996 int sd_long_timeout = 24 * 60 * 60;	/* 24 hours */
3997 
3998 #define max(a, b) (((a)>(b))?(a):(b))
3999 
4000 /*
4001  * Wake up every second and if interrupt is pending
4002  * but nothing has happened increment a counter.
4003  * If nothing happens for sdc_timeo seconds, reset the IOP
4004  * and begin anew.
4005  */
4006 sdwatch()
4007 {
4008 	register struct iop/**/_ctlr *im;
4009 	register struct sdc_softc *sdc;
4010 	register int i;
4011 	register int unit;
4012 	int timeo;
4013 
4014 	extern int Scsi_Disconnect;
4015 
4016 	timeout(sdwatch, (caddr_t)0, hz);
4017 	for (i = 0; i < nsdc; i++) {
4018 		im = sdminfo[i];
4019 		if (im == 0)
4020 			continue;
4021 		if (im->im_alive == 0)
4022 			continue;
4023 		sdc = &sdc_softc[i];
4024 
4025 		if (im->im_tab.b_active)
4026 			goto active;
4027 
4028 		for (unit = 0; unit < nsd; unit++)
4029 			if (sdutab[unit].b_active && sddinfo[unit]->ii_mi == im)
4030 				goto active;
4031 
4032 		sdc->sdc_wticks = 0;
4033 		continue;
4034 active:
4035 		if (Scsi_Disconnect)
4036 			timeo = sdc->sdc_timeo;
4037 		else
4038 			timeo = max(sdc->sdc_timeo, sd_long_timeout);
4039 
4040 		if (sdc->sdc_wticks++ >= timeo) {
4041 			register struct scsi *sc;
4042 
4043 			sc = get_scsi(im->im_intr);
4044 			sdc->sdc_wticks = 0;
4045 			printf("sdc%d: lost interrupt\n", i);
4046 
4047 			screset(im->im_intr);
4048 		}
4049 	}
4050 }
4051 
4052 /*
4053  * sdstop() is timer interrupt routine.
4054  *	So, can't use sleep().
4055  */
4056 sdstop()
4057 {
4058 	register struct iop/**/_ctlr *im;
4059 	register struct iop/**/_device *ii;
4060 	register struct sdc_softc *sdc;
4061 	register struct sdd_softc *sdd;
4062 	register int unit;
4063 	register int intr;
4064 	register int i;
4065 	struct scsi *sc;
4066 	int eject_sw;
4067 
4068 	timeout(sdstop, (caddr_t)0, hz);
4069 
4070 	for (i = 0; i < nsdc; i++) {
4071 		im = sdminfo[i];
4072 		if (im == 0)
4073 			continue;
4074 		if (im->im_alive == 0)
4075 			continue;
4076 		for (unit = 0; unit < nsd; unit++) {
4077 			if ((ii = sddinfo[unit]) == 0)
4078 				continue;
4079 			if (ii->ii_mi != im)
4080 				continue;
4081 			sdc = &sdc_softc[ii->ii_ctlr];
4082 			if ((sdc->sdc_firmware & SDCFW_RMB) == 0)
4083 				continue;
4084 			intr = ii->ii_intr;
4085 			if (isalone(unit))
4086 				continue;
4087 			/**********************/
4088 			/*    MO & CD-ROM     */
4089 			/**********************/
4090 			/*
4091 			 * there is no process which open the unit.
4092 			 */
4093 			sdd = &sdd_softc[unit];
4094 			sc = get_scsi(intr);
4095 			if (sdd->sdd_start > 0)
4096 				sdd->sdd_start--;
4097 			else if (sdd->sdd_start == 0) {
4098 				/*
4099 				 * Now stop the unit.
4100 				 * check SCSI access
4101 				 */
4102 				if (sdc->sdc_firmware & SDCFW_BUSY)
4103 					continue;
4104 				sdc->sdc_firmware |= SDCFW_BUSY;
4105 				sdc->sdc_state |= SDCS_IOCTL|SDCS_SCUNLOCK;
4106 
4107 				eject_sw = (sdd->sdd_flags & SDDF_REQ_EJECT) ?
4108 						SDSS_EJECT : SDSS_STOP;
4109 				scop_stst(intr, sc, ii->ii_slave,
4110 						SCSI_INTEN, eject_sw);
4111 				sdd->sdd_start = -2;
4112 			}
4113 		}
4114 	}
4115 }
4116 
4117 isalone(unit)
4118 	register int unit;
4119 {
4120 	register int i, n;
4121 
4122 	n = 0;
4123 	for (i = 0; i < PNUM; i++)
4124 		n += (sd_b_openf[unit][i] + sd_c_openf[unit][i]);
4125 	return (n);
4126 }
4127 
4128 /************************************************
4129  * Convert Hex and RS code table definition	*
4130  ************************************************/
4131 
4132 #define	X8_L	0x001d
4133 #define	X8_H	0x1d00
4134 
4135 
4136 #define	hextors(data)	hxtable[(int)((data) & 0xff)]
4137 #define	XORMASK(code)	xortable[(unsigned int)(code)]
4138 
4139 int	hxtable[256] = {
4140 	0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6,
4141 	0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
4142 	0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81,
4143 	0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
4144 	0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21,
4145 	0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
4146 	0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9,
4147 	0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
4148 	0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd,
4149 	0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
4150 	0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd,
4151 	0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
4152 	0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e,
4153 	0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
4154 	0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b,
4155 	0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
4156 	0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d,
4157 	0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
4158 	0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c,
4159 	0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
4160 	0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd,
4161 	0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
4162 	0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e,
4163 	0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
4164 	0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76,
4165 	0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
4166 	0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa,
4167 	0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
4168 	0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51,
4169 	0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
4170 	0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8,
4171 	0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf,
4172 };
4173 
4174 int xortable[256] = {
4175 	0x00000000, 0x90910101, 0x91210201, 0x01b00300,
4176 	0x92410401, 0x02d00500, 0x03600600, 0x93f10701,
4177 	0x94810801, 0x04100900, 0x05a00a00, 0x95310b01,
4178 	0x06c00c00, 0x96510d01, 0x97e10e01, 0x07700f00,
4179 	0x99011001, 0x09901100, 0x08201200, 0x98b11301,
4180 	0x0b401400, 0x9bd11501, 0x9a611601, 0x0af01700,
4181 	0x0d801800, 0x9d111901, 0x9ca11a01, 0x0c301b00,
4182 	0x9fc11c01, 0x0f501d00, 0x0ee01e00, 0x9e711f01,
4183 	0x82012001, 0x12902100, 0x13202200, 0x83b12301,
4184 	0x10402400, 0x80d12501, 0x81612601, 0x11f02700,
4185 	0x16802800, 0x86112901, 0x87a12a01, 0x17302b00,
4186 	0x84c12c01, 0x14502d00, 0x15e02e00, 0x85712f01,
4187 	0x1b003000, 0x8b913101, 0x8a213201, 0x1ab03300,
4188 	0x89413401, 0x19d03500, 0x18603600, 0x88f13701,
4189 	0x8f813801, 0x1f103900, 0x1ea03a00, 0x8e313b01,
4190 	0x1dc03c00, 0x8d513d01, 0x8ce13e01, 0x1c703f00,
4191 	0xb4014001, 0x24904100, 0x25204200, 0xb5b14301,
4192 	0x26404400, 0xb6d14501, 0xb7614601, 0x27f04700,
4193 	0x20804800, 0xb0114901, 0xb1a14a01, 0x21304b00,
4194 	0xb2c14c01, 0x22504d00, 0x23e04e00, 0xb3714f01,
4195 	0x2d005000, 0xbd915101, 0xbc215201, 0x2cb05300,
4196 	0xbf415401, 0x2fd05500, 0x2e605600, 0xbef15701,
4197 	0xb9815801, 0x29105900, 0x28a05a00, 0xb8315b01,
4198 	0x2bc05c00, 0xbb515d01, 0xbae15e01, 0x2a705f00,
4199 	0x36006000, 0xa6916101, 0xa7216201, 0x37b06300,
4200 	0xa4416401, 0x34d06500, 0x35606600, 0xa5f16701,
4201 	0xa2816801, 0x32106900, 0x33a06a00, 0xa3316b01,
4202 	0x30c06c00, 0xa0516d01, 0xa1e16e01, 0x31706f00,
4203 	0xaf017001, 0x3f907100, 0x3e207200, 0xaeb17301,
4204 	0x3d407400, 0xadd17501, 0xac617601, 0x3cf07700,
4205 	0x3b807800, 0xab117901, 0xaaa17a01, 0x3a307b00,
4206 	0xa9c17c01, 0x39507d00, 0x38e07e00, 0xa8717f01,
4207 	0xd8018001, 0x48908100, 0x49208200, 0xd9b18301,
4208 	0x4a408400, 0xdad18501, 0xdb618601, 0x4bf08700,
4209 	0x4c808800, 0xdc118901, 0xdda18a01, 0x4d308b00,
4210 	0xdec18c01, 0x4e508d00, 0x4fe08e00, 0xdf718f01,
4211 	0x41009000, 0xd1919101, 0xd0219201, 0x40b09300,
4212 	0xd3419401, 0x43d09500, 0x42609600, 0xd2f19701,
4213 	0xd5819801, 0x45109900, 0x44a09a00, 0xd4319b01,
4214 	0x47c09c00, 0xd7519d01, 0xd6e19e01, 0x46709f00,
4215 	0x5a00a000, 0xca91a101, 0xcb21a201, 0x5bb0a300,
4216 	0xc841a401, 0x58d0a500, 0x5960a600, 0xc9f1a701,
4217 	0xce81a801, 0x5e10a900, 0x5fa0aa00, 0xcf31ab01,
4218 	0x5cc0ac00, 0xcc51ad01, 0xcde1ae01, 0x5d70af00,
4219 	0xc301b001, 0x5390b100, 0x5220b200, 0xc2b1b301,
4220 	0x5140b400, 0xc1d1b501, 0xc061b601, 0x50f0b700,
4221 	0x5780b800, 0xc711b901, 0xc6a1ba01, 0x5630bb00,
4222 	0xc5c1bc01, 0x5550bd00, 0x54e0be00, 0xc471bf01,
4223 	0x6c00c000, 0xfc91c101, 0xfd21c201, 0x6db0c300,
4224 	0xfe41c401, 0x6ed0c500, 0x6f60c600, 0xfff1c701,
4225 	0xf881c801, 0x6810c900, 0x69a0ca00, 0xf931cb01,
4226 	0x6ac0cc00, 0xfa51cd01, 0xfbe1ce01, 0x6b70cf00,
4227 	0xf501d001, 0x6590d100, 0x6420d200, 0xf4b1d301,
4228 	0x6740d400, 0xf7d1d501, 0xf661d601, 0x66f0d700,
4229 	0x6180d800, 0xf111d901, 0xf0a1da01, 0x6030db00,
4230 	0xf3c1dc01, 0x6350dd00, 0x62e0de00, 0xf271df01,
4231 	0xee01e001, 0x7e90e100, 0x7f20e200, 0xefb1e301,
4232 	0x7c40e400, 0xecd1e501, 0xed61e601, 0x7df0e700,
4233 	0x7a80e800, 0xea11e901, 0xeba1ea01, 0x7b30eb00,
4234 	0xe8c1ec01, 0x7850ed00, 0x79e0ee00, 0xe971ef01,
4235 	0x7700f000, 0xe791f101, 0xe621f201, 0x76b0f300,
4236 	0xe541f401, 0x75d0f500, 0x7460f600, 0xe4f1f701,
4237 	0xe381f801, 0x7310f900, 0x72a0fa00, 0xe231fb01,
4238 	0x71c0fc00, 0xe151fd01, 0xe0e1fe01, 0x7070ff00
4239 };
4240 
4241 /********************************************************
4242  * EDC (Error Detection Code) check			*
4243  *			(using CRC code)		*
4244  *	MODE 1 : Sync + Header + User data + edc	*
4245  *	MODE 2 : Sub header + User data + edc		*
4246  ********************************************************/
4247 
4248 #define	SYNC_EDC	0x908eff4e	/* sector sync EDC value	*/
4249 #define	HEADER		4		/* header length 4 bytes	*/
4250 #define	SUB_H		8		/* Subheader length 8 bytes	*/
4251 #define	USER_DATA	2048		/* User data length 2048 bytes	*/
4252 #define	EDC_LEN		4		/* EDC code length 4 bytes	*/
4253 
4254 cal_edc1(db, mode)
4255 	register unsigned char	*db;
4256 	int mode;
4257 {
4258 	register int j;
4259 	register unsigned int work;
4260 
4261 	j = USER_DATA + EDC_LEN;
4262 	if (mode == 2) {
4263 		j += SUB_H;
4264 		work = 0;
4265 	} else {
4266 		j += HEADER;
4267 		work = SYNC_EDC;
4268 	}
4269 	while (--j >= 0)
4270 		work = ((work >> 8) | (*db++ << 24)) ^ XORMASK(work & 0xff);
4271 
4272 	return (work);
4273 }
4274 
4275 
4276 /************************************************/
4277 /*	error detection & correction		*/
4278 /*	if form 1				*/
4279 /*	    header area should be zero		*/
4280 /************************************************/
4281 
4282 /*
4283  *	error detection & correction  P-direction
4284  */
4285 p_dir(dbuf)
4286 	register unsigned short	*dbuf;
4287 {
4288 	unsigned short	s0, s1, d;
4289 	register int	col, row;
4290 	register int	x;
4291 	unsigned char	s0l, s0h, s1l, s1h;
4292 
4293 	/*
4294 	 * calculate syndrome S0 S1
4295 	 */
4296 	for (col = 0; col < 43; col++) {
4297 		s0 = s1 = 0;
4298 
4299 		for (row = 0; row < 26; row++) {
4300 			d = dbuf[43 * row + col];
4301 			s0 ^= d;
4302 			s1 = rsshift(s1) ^ d;
4303 		}
4304 
4305 		s0h = s0 & 0x00ff;
4306 		s1h = s1 & 0x00ff;
4307 		s0l = (s0 >> 8) & 0x00ff;
4308 		s1l = (s1 >> 8) & 0x00ff;
4309 		/*
4310 		 * calculate error position & correction
4311 		 */
4312 		if (s0l != 0) {
4313 			if((x = hextors(s1l) - hextors(s0l)) < 0)
4314 				x += 255;
4315 			if ((x >= 0) && (x < 26)) {
4316 				x = 25 - x;
4317 				/*
4318 				 * correction
4319 				 */
4320 				dbuf[43 * x + col] ^= (s0 & 0xff00);
4321 			}
4322 		}
4323 
4324 		/*
4325 		 * calculate error position & correction
4326 		 */
4327 		if (s0h != 0) {
4328 			if((x = hextors(s1h) - hextors(s0h)) < 0)
4329 				x += 255;
4330 			if ((x >= 0) && (x < 26)) {
4331 				x = 25 - x;
4332 				/*
4333 				 * correction
4334 				 */
4335 				dbuf[43 * x + col] ^= (s0 & 0x00ff);
4336 			}
4337 		}
4338 	}
4339 }
4340 
4341 /*
4342  * error detection & correction  Q-direction
4343  */
4344 q_dir(dbuf)
4345 	register unsigned short	*dbuf;
4346 {
4347 	unsigned short s0, s1, d;
4348 	register int col, row;
4349 	register int x;
4350 	unsigned char s0l, s0h, s1l, s1h;
4351 
4352 	/*
4353 	 * calculate syndrome S0 S1
4354 	 */
4355 	for (row = 0; row < 26; row++) {
4356 		s0 = s1 = 0;
4357 
4358 		for (col = 0; col < 45; col++) {
4359 			if (col < 43)
4360 				d = dbuf[(44 * col + 43 * row) % 1118];
4361 			else if (col == 43)
4362 				d = dbuf[43 * 26 + row];
4363 			else
4364 				d = dbuf[44 * 26 + row];
4365 			s0 ^= d;
4366 			s1 = rsshift(s1) ^ d;
4367 		}
4368 
4369 		s0h = s0 & 0x00ff;
4370 		s1h = s1 & 0x00ff;
4371 		s0l = (s0 >> 8) & 0x00ff;
4372 		s1l = (s1 >> 8) & 0x00ff;
4373 		/*
4374 		 * calculate error position & correction
4375 		 */
4376 		if (s0l != 0) {
4377 			if((x = hextors(s1l) - hextors(s0l)) < 0)
4378 				x += 255;
4379 			if (x >= 0 && x < 45) {
4380 				x = 44 - x;
4381 				/*
4382 				 * correction
4383 				 */
4384 				if (x < 43)
4385 					dbuf[(44 * x + 43 * row) % 1118]
4386 						^= s0 & 0xff00;
4387 				else if (x == 43)
4388 					dbuf[43 * 26 + row] ^= s0 & 0xff00;
4389 				else
4390 					dbuf[44 * 26 + row] ^= s0 & 0xff00;
4391 			}
4392 		}
4393 
4394 		/*
4395 		 * calculate error position & correction
4396 		 */
4397 		if (s0h != 0) {
4398 			if((x = hextors(s1h) - hextors(s0h)) < 0)
4399 				x += 255;
4400 			if ((x >= 0) && (x < 45)) {
4401 				x = 44 - x;
4402 				/*
4403 				 * correction
4404 				 */
4405 				if (x < 43)
4406 					dbuf[(44 * x + 43 * row) % 1118]
4407 						^= s0 & 0x00ff;
4408 				else if ( x == 43)
4409 					dbuf[43 * 26 + row] ^= s0 & 0x00ff;
4410 				else
4411 					dbuf[44 * 26 + row] ^= s0 & 0x00ff;
4412 			}
4413 		}
4414 	}
4415 }
4416 
4417 /*
4418  *	shift high & low byte at the same time
4419  */
4420 rsshift(d)
4421 	unsigned short d;
4422 {
4423 	register int x;
4424 	register int dmy;	/* This way is faster */
4425 
4426 	dmy = (int)d;
4427 	x = (dmy << 1) & 0xfefe;	/* clear LSB of high & low byte */
4428 	if ((dmy & 0x0080) != 0)
4429 		x ^= X8_L;
4430 	if ((dmy & 0x8000) != 0)
4431 		x ^= X8_H;
4432 	return(x);
4433 }
4434 #endif /* NSD > 0 */
4435