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