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