xref: /illumos-gate/usr/src/uts/sun/io/fd.c (revision 19397407)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * Intel 82077 Floppy Disk Driver
29  */
30 
31 /*
32  * Notes
33  *
34  *	0. The driver supports two flavors of hardware design:
35  *		"SUNW,fdtwo"	- sun4m	- 82077 with sun4m style Auxio
36  *		"fdthree"  - sun4u - 82077 with DMA
37  *	   In addition it supports an apparent bug in some versions of
38  *	   the 82077 controller.
39  *
40  *	1. The driver is mostly set up for multiple controllers, multiple
41  *	drives. However- we *do* assume the use of the AUXIO register, and
42  *	if we ever have > 1 fdc, we'll have to see what that means. This
43  *	is all intrinsically machine specific, but there isn't much we
44  *	can do about it.
45  *
46  *	2. The driver also is structured to deal with one drive active at
47  *	a time. This is because the 82072 chip (no longer supported) was
48  *	known to be buggy with respect to overlapped seeks.
49  *
50  *	3. The high level interrupt code is in assembler, and runs in a
51  *	sparc trap window. It acts as a pseudo-dma engine as well as
52  *	handles a couple of other interrupts. When it gets its job done,
53  *	it schedules a second stage interrupt (soft interrupt) which
54  *	is then fielded here in fd_lointr.  When DMA is used, the fdintr_dma
55  *	interrupt handler is used.
56  *
57  *	4. Nearly all locking is done on a lower level MUTEX_DRIVER
58  *	mutex. The locking is quite conservative, and is generally
59  *	established very close to any of the entries into the driver.
60  *	There is nearly no locking done of the high level MUTEX_DRIVER
61  *	mutex (which generally is a SPIN mutex because the floppy usually
62  *	interrupts above LOCK_LEVEL). The assembler high level interrupt
63  *	handler grabs the high level mutex, but the code in the driver
64  *	here is especially structured to not need to do this.
65  *
66  *	5. Fdrawioctl commands that pass data are not optimized for
67  *	speed. If they need to be faster, the driver structure will
68  *	have to be redone such that fdrawioctl calls physio after
69  *	cons'ing up a uio structure and that fdstart will be able
70  *	to detect that a particular buffer is a 'special' buffer.
71  *
72  *	6. Removable media support is not complete.
73  *
74  */
75 
76 #include <sys/param.h>
77 #include <sys/buf.h>
78 #include <sys/ioctl.h>
79 #include <sys/uio.h>
80 #include <sys/open.h>
81 #include <sys/conf.h>
82 #include <sys/file.h>
83 #include <sys/cmn_err.h>
84 #include <sys/debug.h>
85 #include <sys/kmem.h>
86 #include <sys/stat.h>
87 #include <sys/autoconf.h>
88 
89 #include <sys/dklabel.h>
90 
91 #include <sys/vtoc.h>
92 #include <sys/dkio.h>
93 #include <sys/fdio.h>
94 
95 #include <sys/ddi.h>
96 #include <sys/sunddi.h>
97 #include <sys/kstat.h>
98 
99 /*
100  * included to check for ELC or SLC which report floppy controller that
101  */
102 #include <sys/cpu.h>
103 
104 #include "sys/fdvar.h"
105 #include "sys/fdreg.h"
106 #include "sys/dma_i8237A.h"
107 
108 /*
109  * Defines
110  */
111 #define	KIOSP	KSTAT_IO_PTR(un->un_iostat)
112 #define	KIOIP	KSTAT_INTR_PTR(fdc->c_intrstat)
113 #define	MEDIUM_DENSITY	0x40
114 #define	SEC_SIZE_CODE	(fdctlr.c_csb->csb_unit]->un_chars->medium ? 3 : 2)
115 #define	CMD_READ	(MT + SK + FDRAW_RDCMD + MFM)
116 #define	CMD_WRITE	(MT + FDRAW_WRCMD + MFM)
117 #define	C		CE_CONT
118 #define	FD_POLLABLE_PROP	"pollable"	/* prom property */
119 #define	FD_MANUAL_EJECT		"manual"	/* prom property */
120 #define	FD_UNIT			"unit"		/* prom property */
121 
122 /*
123  * Sony MP-F17W-50D Drive Parameters
124  *				High Capacity
125  *	Capacity unformatted	2Mb
126  *	Capacity formatted	1.47Mb
127  *	Encoding method	 MFM
128  *	Recording density	17434 bpi
129  *	Track density		135 tpi
130  *	Cylinders		80
131  *	Heads			2
132  *	Tracks			160
133  *	Rotational speed	300 rpm
134  *	Transfer rate		250/500 kbps
135  *	Latency (average)	100 ms
136  *	Access time
137  *		Average		95 ms
138  *		Track to track	3 ms
139  *	Head settling time	15 ms
140  *	Motor start time	500 ms
141  *	Head load time		? ms
142  */
143 
144 /*
145  * The max_fd_dma_len is used only when southbridge is present.
146  * It has been observed that when IFB tests are run the floppy dma could get
147  * starved and result in underrun errors. After experimenting it was found that
148  * doing dma in chunks of 2048 works OK.
149  * The reason for making this a global variable is that there could be
150  * situations under which the customer would like to get full performance
151  * from floppy. He may not be having IFB boards that cause underrun errors.
152  * Under those conditions we could set this value to a much higher value
153  * by editing /etc/system file.
154  */
155 int	max_fd_dma_len = 2048;
156 
157 static void quiesce_fd_interrupt(struct fdctlr *);
158 
159 /*
160  * Character/block entry points function prototypes
161  */
162 static int fd_open(dev_t *, int, int, cred_t *);
163 static int fd_close(dev_t, int, int, cred_t *);
164 static int fd_strategy(struct buf *);
165 static int fd_read(dev_t, struct uio *, cred_t *);
166 static int fd_write(dev_t, struct uio *, cred_t *);
167 static int fd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
168 static int
169 fd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *, caddr_t, int *);
170 
171 /*
172  * Device operations (dev_ops) entries function prototypes
173  */
174 static int fd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
175 		void **result);
176 static int fd_attach(dev_info_t *, ddi_attach_cmd_t);
177 static int fd_detach(dev_info_t *, ddi_detach_cmd_t);
178 static int fd_power(dev_info_t *dip, int component, int level);
179 
180 /*
181  * Internal functions
182  */
183 static int fd_attach_check_drive(struct fdctlr *fdc);
184 static int fd_attach_det_ctlr(dev_info_t *dip, struct fdctlr *fdc);
185 static int fd_attach_map_regs(dev_info_t *dip, struct fdctlr *fdc);
186 static int fd_attach_register_interrupts(dev_info_t *dip, struct fdctlr *fdc,
187     int *hard);
188 static int fd_build_label_vtoc(struct fdunit *, struct vtoc *);
189 static void fd_build_user_vtoc(struct fdunit *, struct vtoc *);
190 static int fdcheckdisk(struct fdctlr *fdc, int unit);
191 static int fd_check_media(dev_t dev, enum dkio_state state);
192 static void fd_cleanup(dev_info_t *dip, struct fdctlr *fdc, int hard,
193     int locks);
194 static void fdeject(struct fdctlr *, int unit);
195 static int fdexec(struct fdctlr *fdc, int flags);
196 static void fdexec_turn_on_motor(struct fdctlr *fdc, int flags, uint_t unit);
197 static int fdformat(struct fdctlr *fdc, int unit, int cyl, int hd);
198 static caddr_t fd_getauxiova();
199 static struct fdctlr *fd_getctlr(dev_t);
200 static void fdgetcsb(struct fdctlr *);
201 static int fdgetlabel(struct fdctlr *fdc, int unit);
202 enum dkio_state fd_get_media_state(struct fdctlr *, int);
203 static uint_t fdintr_dma();
204 static int fd_isauxiodip(dev_info_t *);
205 static uint_t  fd_lointr(caddr_t arg);
206 static void fd_media_watch(void *);
207 static void fdmotoff(void *);
208 static int fd_part_is_open(struct fdunit *un, int part);
209 static int fdrawioctl(struct fdctlr *, int, intptr_t, int);
210 static int fdrecalseek(struct fdctlr *fdc, int unit, int arg, int execflg);
211 static int fdrecover(struct fdctlr *);
212 static void fdretcsb(struct fdctlr *);
213 static int fdreset(struct fdctlr *);
214 static int fdrw(struct fdctlr *fdc, int, int, int, int, int, caddr_t, uint_t);
215 static void fdselect(struct fdctlr *fdc, int unit, int onoff);
216 static int fdsensedrv(struct fdctlr *fdc, int unit);
217 static int fdsense_chng(struct fdctlr *, int unit);
218 static void fdstart(struct fdctlr *);
219 static int fdstart_dma(register struct fdctlr *fdc, caddr_t addr, uint_t len);
220 static int fd_unit_is_open(struct fdunit *);
221 static void fdunpacklabel(struct packed_label *, struct dk_label *);
222 static int fd_unbind_handle(struct fdctlr *);
223 static void fdwatch(void *);
224 static void set_rotational_speed(struct fdctlr *, int);
225 static int fd_get_media_info(struct fdunit *un, caddr_t buf, int flag);
226 static int fd_pm_lower_power(struct fdctlr *fdc);
227 static int fd_pm_raise_power(struct fdctlr *fdc);
228 static void create_pm_components(dev_info_t *dip);
229 static void set_data_count_register(struct fdctlr *fdc, uint32_t count);
230 static uint32_t get_data_count_register(struct fdctlr *fdc);
231 static void reset_dma_controller(struct fdctlr *fdc);
232 static void set_data_address_register(struct fdctlr *fdc, uint32_t address);
233 static uint32_t get_dma_control_register(struct fdctlr *fdc);
234 static void set_dma_mode(struct fdctlr *fdc, int val);
235 static void set_dma_control_register(struct fdctlr *fdc, uint32_t val);
236 static void release_sb_dma(struct fdctlr *fdc);
237 
238 /*
239  * External functions
240  */
241 extern uint_t fd_intr(caddr_t);	/* defined in fd_asm.s */
242 extern void set_auxioreg();
243 extern void call_debug();
244 
245 
246 
247 /*
248  * The following macro checks whether the device in a SUSPENDED state.
249  * As per WDD guide lines the I/O requests to a suspended device should
250  * be blocked until the device is resumed.
251  * Here we cv_wait on c_suspend_cv, and there is a cv_broadcast() in
252  * DDI_RESUME to wake up this thread.
253  *
254  * NOTE: This code is not tested because the kernel threads are suspended
255  * before the device is suspended. So there can not be any I/O requests on
256  * a suspended device until the cpr implementation changes..
257  */
258 
259 #define	CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc) 	\
260 		{\
261 			while (fdc->c_un->un_state == FD_STATE_SUSPENDED) {\
262 				cv_wait(&fdc->c_suspend_cv, \
263 							&fdc->c_lolock);\
264 			}\
265 		}
266 
267 /*
268  * bss (uninitialized data)
269  */
270 struct	fdctlr	*fdctlrs;	/* linked list of controllers */
271 
272 /*
273  * initialized data
274  */
275 
276 static int fd_check_media_time = 5000000;	/* 5 second state check */
277 static int fd_pollable = 0;
278 static uchar_t rwretry = 10;
279 static uchar_t skretry = 5;
280 /* This variable allows the dynamic change of the burst size */
281 static int fd_burstsize = DCSR_BURST_0 | DCSR_BURST_1;
282 
283 static struct driver_minor_data {
284 	char	*name;
285 	int	minor;
286 	int	type;
287 } fd_minor [] = {
288 	{ "a", 0, S_IFBLK},
289 	{ "b", 1, S_IFBLK},
290 	{ "c", 2, S_IFBLK},
291 	{ "a,raw", 0, S_IFCHR},
292 	{ "b,raw", 1, S_IFCHR},
293 	{ "c,raw", 2, S_IFCHR},
294 	{0}
295 };
296 
297 /*
298  * If the interrupt handler is invoked and no controllers expect an
299  * interrupt, the kernel panics.  The following message is printed out.
300  */
301 char *panic_msg = "fd_intr: unexpected interrupt\n";
302 
303 /*
304  * Specify/Configure cmd parameters
305  */
306 static uchar_t fdspec[2] = { 0xc2, 0x33 };	/*  "specify" parameters */
307 static uchar_t fdconf[3] = { 0x64, 0x58, 0x00 }; /*  "configure" parameters */
308 
309 /* When DMA is used, set the ND bit to 0 */
310 #define	SPEC_DMA_MODE	0x32
311 
312 /*
313  * default characteristics
314  */
315 static struct fd_char fdtypes[] = {
316 	{	/* struct fd_char fdchar_1.7MB density */
317 		0,		/* medium */
318 		500,		/* transfer rate */
319 		80,		/* number of cylinders */
320 		2,		/* number of heads */
321 		512,		/* sector size */
322 		21,		/* sectors per track */
323 		-1,		/* (NA) # steps per data track */
324 	},
325 	{	/* struct fd_char fdchar_highdens */
326 		0, 		/* medium */
327 		500, 		/* transfer rate */
328 		80, 		/* number of cylinders */
329 		2, 		/* number of heads */
330 		512, 		/* sector size */
331 		18, 		/* sectors per track */
332 		-1, 		/* (NA) # steps per data track */
333 	},
334 	{	/* struct fd_char fdchar_meddens */
335 		1, 		/* medium */
336 		500, 		/* transfer rate */
337 		77, 		/* number of cylinders */
338 		2, 		/* number of heads */
339 		1024, 		/* sector size */
340 		8, 		/* sectors per track */
341 		-1, 		/* (NA) # steps per data track */
342 	},
343 	{	/* struct fd_char fdchar_lowdens  */
344 		0, 		/* medium */
345 		250, 		/* transfer rate */
346 		80, 		/* number of cylinders */
347 		2, 		/* number of heads */
348 		512, 		/* sector size */
349 		9, 		/* sectors per track */
350 		-1, 		/* (NA) # steps per data track */
351 	}
352 };
353 
354 
355 static int nfdtypes = sizeof (fdtypes) / sizeof (fdtypes[0]);
356 
357 
358 /*
359  * Default Label & partition maps
360  */
361 
362 static struct packed_label fdlbl_high_21 = {
363 	{ "3.5\" floppy cyl 80 alt 0 hd 2 sec 21" },
364 	300,				/* rotations per minute */
365 	80,				/* # physical cylinders */
366 	0,				/* alternates per cylinder */
367 	1,				/* interleave factor */
368 	80,				/* # of data cylinders */
369 	0,				/* # of alternate cylinders */
370 	2,				/* # of heads in this partition */
371 	21,				/* # of 512 byte sectors per track */
372 	{
373 		{ 0, 79 * 2 * 21 },	/* part 0 - all but last cyl */
374 		{ 79, 1 * 2 * 21 },	/* part 1 - just the last cyl */
375 		{ 0, 80 * 2 * 21 },	/* part 2 - "the whole thing" */
376 	},
377 	{	0,			/* version */
378 		"",			/* volume label */
379 		3,			/* no. of partitions */
380 		{ 0 },			/* partition hdrs, sec 2 */
381 		{ 0 },			/* mboot info.  unsupported */
382 		VTOC_SANE,		/* verify vtoc sanity */
383 		{ 0 },			/* reserved space */
384 		0,			/* timestamp */
385 	},
386 };
387 
388 static struct packed_label fdlbl_high_80 = {
389 	{ "3.5\" floppy cyl 80 alt 0 hd 2 sec 18" },
390 	300, 				/* rotations per minute */
391 	80, 				/* # physical cylinders */
392 	0, 				/* alternates per cylinder */
393 	1, 				/* interleave factor */
394 	80, 				/* # of data cylinders */
395 	0, 				/* # of alternate cylinders */
396 	2, 				/* # of heads in this partition */
397 	18, 				/* # of 512 byte sectors per track */
398 	{
399 		{ 0, 79 * 2 * 18 }, 	/* part 0 - all but last cyl */
400 		{ 79, 1 * 2 * 18 }, 	/* part 1 - just the last cyl */
401 		{ 0, 80 * 2 * 18 }, 	/* part 2 - "the whole thing" */
402 	},
403 	{	0,			/* version */
404 		"",			/* volume label */
405 		3,			/* no. of partitions */
406 		{ 0 },			/* partition hdrs, sec 2 */
407 		{ 0 },			/* mboot info.  unsupported */
408 		VTOC_SANE,		/* verify vtoc sanity */
409 		{ 0 },			/* reserved space */
410 		0,			/* timestamp */
411 	},
412 };
413 
414 /*
415  * A medium density diskette has 1024 byte sectors.  The dk_label structure
416  * assumes a sector is DEVBSIZE (512) bytes.
417  */
418 static struct packed_label fdlbl_medium_80 = {
419 	{ "3.5\" floppy cyl 77 alt 0 hd 2 sec 8" },
420 	360, 				/* rotations per minute */
421 	77, 				/* # physical cylinders */
422 	0, 				/* alternates per cylinder */
423 	1, 				/* interleave factor */
424 	77, 				/* # of data cylinders */
425 	0, 				/* # of alternate cylinders */
426 	2, 				/* # of heads in this partition */
427 	16, 				/* # of 512 byte sectors per track */
428 	{
429 		{ 0, 76 * 2 * 8 * 2 },  /* part 0 - all but last cyl */
430 		{ 76, 1 * 2 * 8 * 2 },  /* part 1 - just the last cyl */
431 		{ 0, 77 * 2 * 8 * 2 },  /* part 2 - "the whole thing" */
432 	},
433 	{	0,			/* version */
434 		"",			/* volume label */
435 		3,			/* no. of partitions */
436 		{ 0 },			/* partition hdrs, sec 2 */
437 		{ 0 },			/* mboot info.  unsupported */
438 		VTOC_SANE,		/* verify vtoc sanity */
439 		{ 0 },			/* reserved space */
440 		0,			/* timestamp */
441 	},
442 };
443 
444 static struct packed_label fdlbl_low_80 = {
445 	{ "3.5\" floppy cyl 80 alt 0 hd 2 sec 9" },
446 	300, 				/* rotations per minute */
447 	80, 				/* # physical cylinders */
448 	0, 				/* alternates per cylinder */
449 	1, 				/* interleave factor */
450 	80, 				/* # of data cylinders */
451 	0, 				/* # of alternate cylinders */
452 	2, 				/* # of heads in this partition */
453 	9, 				/* # of 512 byte sectors per track */
454 	{
455 		{ 0, 79 * 2 * 9 }, 	/* part 0 - all but last cyl */
456 		{ 79, 1 * 2 * 9 }, 	/* part 1 - just the last cyl */
457 		{ 0, 80 * 2 * 9 }, 	/* part 2 - "the whole thing" */
458 	},
459 	{	0,			/* version */
460 		"",			/* volume label */
461 		3,			/* no. of partitions */
462 		{ 0 },			/* partition hdrs, sec 2 */
463 		{ 0 },			/* mboot info.  unsupported */
464 		VTOC_SANE,		/* verify vtoc sanity */
465 		{ 0 },			/* reserved space */
466 		0,			/* timestamp */
467 	},
468 };
469 
470 static struct fdcmdinfo {
471 	char *cmdname;		/* command name */
472 	uchar_t ncmdbytes;	/* number of bytes of command */
473 	uchar_t nrsltbytes;	/* number of bytes in result */
474 	uchar_t cmdtype;		/* characteristics */
475 } fdcmds[] = {
476 	"", 0, 0, 0, 			/* - */
477 	"", 0, 0, 0, 			/* - */
478 	"read_track", 9, 7, 1, 		/* 2 */
479 	"specify", 3, 0, 3, 		/* 3 */
480 	"sense_drv_status", 2, 1, 3, 	/* 4 */
481 	"write", 9, 7, 1, 		/* 5 */
482 	"read", 9, 7, 1, 		/* 6 */
483 	"recalibrate", 2, 0, 2, 		/* 7 */
484 	"sense_int_status", 1, 2, 3, 	/* 8 */
485 	"write_del", 9, 7, 1, 		/* 9 */
486 	"read_id", 2, 7, 2, 		/* A */
487 	"motor_on/off", 1, 0, 4, 	/* B */
488 	"read_del", 9, 7, 1, 		/* C */
489 	"format_track", 10, 7, 1, 	/* D */
490 	"dump_reg", 1, 10, 4, 		/* E */
491 	"seek", 3, 0, 2, 		/* F */
492 	"", 0, 0, 0, 			/* - */
493 	"", 0, 0, 0, 			/* - */
494 	"", 0, 0, 0, 			/* - */
495 	"configure", 4, 0, 4, 		/* 13 */
496 	/* relative seek */
497 };
498 
499 static struct cb_ops fd_cb_ops = {
500 	fd_open, 		/* open */
501 	fd_close, 		/* close */
502 	fd_strategy, 		/* strategy */
503 	nodev, 			/* print */
504 	nodev, 			/* dump */
505 	fd_read, 		/* read */
506 	fd_write, 		/* write */
507 	fd_ioctl, 		/* ioctl */
508 	nodev, 			/* devmap */
509 	nodev, 			/* mmap */
510 	nodev, 			/* segmap */
511 	nochpoll, 		/* poll */
512 	fd_prop_op, 		/* cb_prop_op */
513 	0, 			/* streamtab  */
514 	D_NEW | D_MP		/* Driver compatibility flag */
515 };
516 
517 static struct dev_ops	fd_ops = {
518 	DEVO_REV, 		/* devo_rev, */
519 	0, 			/* refcnt  */
520 	fd_info, 		/* info */
521 	nulldev, 		/* identify */
522 	nulldev, 		/* probe */
523 	fd_attach, 		/* attach */
524 	fd_detach, 		/* detach */
525 	nodev, 			/* reset */
526 	&fd_cb_ops, 		/* driver operations */
527 	(struct bus_ops *)0,	/* bus operations */
528 	fd_power,		/* power */
529 	ddi_quiesce_not_supported,	/* devo_quiesce */
530 };
531 
532 
533 /*
534  * error handling
535  *
536  * for debugging, set rwretry and skretry = 1
537  *		set fderrlevel to 1
538  *		set fderrmask  to 224  or 100644
539  *
540  * after debug set rwretry to 10, skretry to 5, and fderrlevel to 3
541  * set fderrmask to FDEM_ALL
542  * remove the define FD_DEBUG
543  *
544  */
545 
546 static unsigned int fderrmask = (unsigned int)FDEM_ALL;
547 static int fderrlevel = 3;
548 
549 static int tosec = 16;  /* long timeouts for sundiag for now */
550 
551 /*
552  * loadable module support
553  */
554 
555 #include <sys/modctl.h>
556 
557 extern struct mod_ops mod_driverops;
558 static struct modldrv modldrv = {
559 	&mod_driverops,		/* Type of module. driver here */
560 	"Floppy Driver", 	/* Name of the module. */
561 	&fd_ops, 		/* Driver ops vector */
562 };
563 
564 static struct modlinkage modlinkage = {
565 	MODREV_1,
566 	&modldrv,
567 	NULL
568 };
569 
570 int
571 _init(void)
572 {
573 	return (mod_install(&modlinkage));
574 }
575 
576 int
577 _info(struct modinfo *modinfop)
578 {
579 	return (mod_info(&modlinkage, modinfop));
580 }
581 
582 int
583 _fini(void)
584 {
585 	int e;
586 
587 	if ((e = mod_remove(&modlinkage)) != 0)
588 		return (e);
589 
590 	/* ddi_soft_state_fini() */
591 	return (0);
592 }
593 
594 /* ARGSUSED */
595 static int
596 fd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
597 {
598 	struct 			fdctlr *fdc;
599 	struct 			driver_minor_data *dmdp;
600 	int			instance = ddi_get_instance(dip);
601 	int			hard_intr_set = 0;
602 
603 	FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: start\n"));
604 
605 	switch (cmd) {
606 		case DDI_ATTACH:
607 			break;
608 		case DDI_RESUME:
609 
610 			if (!(fdc = fd_getctlr(instance << FDINSTSHIFT))) {
611 				return (DDI_FAILURE);
612 			}
613 			quiesce_fd_interrupt(fdc);
614 			if (fdc->c_fdtype & FDCTYPE_SB)
615 				if (ddi_add_intr(dip, 0, &fdc->c_block, 0,
616 				    fdintr_dma, (caddr_t)0) != DDI_SUCCESS) {
617 				return (DDI_FAILURE);
618 			}
619 
620 			(void) pm_raise_power(dip, 0, PM_LEVEL_ON);
621 			mutex_enter(&fdc->c_lolock);
622 			/*
623 			 * Wake up any thread blocked due to I/O requests
624 			 * while the device was suspended.
625 			 */
626 			cv_broadcast(&fdc->c_suspend_cv);
627 			mutex_exit(&fdc->c_lolock);
628 			return (DDI_SUCCESS);
629 
630 		default:
631 			return (DDI_FAILURE);
632 	}
633 
634 
635 	/*
636 	 * Check for the pollable property
637 	 * A pollable floppy drive currently only exists on the
638 	 * Sparcstation Voyager.  This drive does not need to
639 	 * be turned on in order to sense whether or not a diskette
640 	 * is present.
641 	 */
642 	if (ddi_getprop(DDI_DEV_T_ANY, dip,
643 	    DDI_PROP_DONTPASS, FD_POLLABLE_PROP, 0))
644 		fd_pollable = 1;
645 
646 	fdc = kmem_zalloc(sizeof (*fdc), KM_SLEEP);
647 	fdc->c_dip = dip;
648 
649 
650 	fdc->c_next = fdctlrs;
651 	fdctlrs = fdc;
652 
653 	/* Determine which type of controller is present and initialize it */
654 	if (fd_attach_det_ctlr(dip, fdc) == DDI_FAILURE) {
655 		fd_cleanup(dip, fdc, hard_intr_set, 0);
656 		return (DDI_FAILURE);
657 	}
658 	/* Finish mapping the device registers & setting up structures */
659 	if (fd_attach_map_regs(dip, fdc) == DDI_FAILURE) {
660 		fd_cleanup(dip, fdc, hard_intr_set, 0);
661 		return (DDI_FAILURE);
662 	}
663 
664 	/*
665 	 * Initialize the DMA limit structures if it's being used.
666 	 */
667 	if (fdc->c_fdtype & FDCTYPE_DMA) {
668 		fdc->c_fd_dma_lim.dma_attr_version = DMA_ATTR_V0;
669 		fdc->c_fd_dma_lim.dma_attr_addr_lo = 0x00000000ull;
670 		fdc->c_fd_dma_lim.dma_attr_addr_hi = 0xfffffffeull;
671 		fdc->c_fd_dma_lim.dma_attr_count_max = 0xffffff;
672 		if (fdc->c_fdtype & FDCTYPE_SB) {
673 			fdc->c_fd_dma_lim.dma_attr_align = FD_SB_DMA_ALIGN;
674 		} else {
675 			fdc->c_fd_dma_lim.dma_attr_align = 1;
676 		}
677 		fdc->c_fd_dma_lim.dma_attr_burstsizes = 0x0;
678 		fdc->c_fd_dma_lim.dma_attr_minxfer = 1;
679 		fdc->c_fd_dma_lim.dma_attr_maxxfer = 0xffff;
680 		fdc->c_fd_dma_lim.dma_attr_seg = 0xffff;
681 		fdc->c_fd_dma_lim.dma_attr_sgllen = 1;
682 		fdc->c_fd_dma_lim.dma_attr_granular = 512;
683 
684 		if (ddi_dma_alloc_handle(dip, &fdc->c_fd_dma_lim,
685 		    DDI_DMA_DONTWAIT, 0, &fdc->c_dmahandle) != DDI_SUCCESS) {
686 			fd_cleanup(dip, fdc, hard_intr_set, 0);
687 			return (DDI_FAILURE);
688 		}
689 
690 		if (fdc->c_fdtype & FDCTYPE_SB) {
691 			ddi_device_acc_attr_t dev_attr;
692 			size_t	rlen;
693 
694 			dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
695 			dev_attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
696 			dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
697 
698 			if (ddi_dma_mem_alloc(fdc->c_dmahandle,
699 			    (size_t)(32*1024), &dev_attr, DDI_DMA_CONSISTENT,
700 			    DDI_DMA_SLEEP, NULL, (caddr_t *)&fdc->dma_buf,
701 			    &rlen, &fdc->c_dma_buf_handle) != DDI_SUCCESS) {
702 				fd_cleanup(dip, fdc, hard_intr_set, 0);
703 				return (DDI_FAILURE);
704 			}
705 
706 		}
707 	}
708 
709 
710 	/* Register the interrupts */
711 	if (fd_attach_register_interrupts(dip, fdc,
712 	    &hard_intr_set) == DDI_FAILURE) {
713 		fd_cleanup(dip, fdc, hard_intr_set, 0);
714 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
715 		    (C, "fd_attach: registering interrupts failed\n"));
716 		return (DDI_FAILURE);
717 	}
718 
719 
720 	/*
721 	 * set initial controller/drive/disk "characteristics/geometry"
722 	 *
723 	 * NOTE:  The driver only supports one floppy drive.  The hardware
724 	 * only supports one drive because there is only one auxio register
725 	 * for one drive.
726 	 */
727 	fdc->c_un = kmem_zalloc(sizeof (struct fdunit), KM_SLEEP);
728 	fdc->c_un->un_chars = kmem_alloc(sizeof (struct fd_char), KM_SLEEP);
729 	fdc->c_un->un_iostat = kstat_create("fd", 0, "fd0", "disk",
730 	    KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT);
731 	if (fdc->c_un->un_iostat) {
732 		fdc->c_un->un_iostat->ks_lock = &fdc->c_lolock;
733 		kstat_install(fdc->c_un->un_iostat);
734 	}
735 
736 	fdc->c_un->un_drive = kmem_zalloc(sizeof (struct fd_drive), KM_SLEEP);
737 
738 	/* check for the manual eject property */
739 	if (ddi_getprop(DDI_DEV_T_ANY, dip,
740 	    DDI_PROP_DONTPASS, FD_MANUAL_EJECT, 0)) {
741 		fdc->c_un->un_drive->fdd_ejectable = 0;
742 	} else {
743 		/* an absence of the property indicates auto eject */
744 		fdc->c_un->un_drive->fdd_ejectable = -1;
745 	}
746 
747 	FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: ejectable? %d\n",
748 	    fdc->c_un->un_drive->fdd_ejectable));
749 
750 	/*
751 	 * Check for the drive id.  If the drive id property doesn't exist
752 	 * then the drive id is set to 0
753 	 */
754 	fdc->c_un->un_unit_no = ddi_getprop(DDI_DEV_T_ANY, dip,
755 	    DDI_PROP_DONTPASS, FD_UNIT, 0);
756 
757 
758 	if (fdc->c_fdtype & FDCTYPE_SB) {
759 		fdc->sb_dma_channel = ddi_getprop(DDI_DEV_T_ANY, dip,
760 		    DDI_PROP_DONTPASS, "dma-channel", 0);
761 	}
762 
763 
764 	FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: unit %d\n",
765 	    fdc->c_un->un_unit_no));
766 
767 	/* Initially set the characteristics to high density */
768 	fdc->c_un->un_curfdtype = 1;
769 	*fdc->c_un->un_chars = fdtypes[fdc->c_un->un_curfdtype];
770 	fdunpacklabel(&fdlbl_high_80, &fdc->c_un->un_label);
771 
772 	/* Make sure drive is present */
773 	if (fd_attach_check_drive(fdc) == DDI_FAILURE) {
774 		fd_cleanup(dip, fdc, hard_intr_set, 1);
775 		return (DDI_FAILURE);
776 	}
777 
778 	for (dmdp = fd_minor; dmdp->name != NULL; dmdp++) {
779 		if (ddi_create_minor_node(dip, dmdp->name, dmdp->type,
780 		    (instance << FDINSTSHIFT) | dmdp->minor,
781 		    DDI_NT_FD, 0) == DDI_FAILURE) {
782 			fd_cleanup(dip, fdc, hard_intr_set, 1);
783 			return (DDI_FAILURE);
784 		}
785 	}
786 
787 	create_pm_components(dip);
788 
789 	/*
790 	 * Add a zero-length attribute to tell the world we support
791 	 * kernel ioctls (for layered drivers)
792 	 */
793 	(void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
794 	    DDI_KERNEL_IOCTL, NULL, 0);
795 
796 	ddi_report_dev(dip);
797 
798 	FDERRPRINT(FDEP_L1, FDEM_ATTA,
799 	    (C, "attached 0x%x\n", ddi_get_instance(dip)));
800 
801 	return (DDI_SUCCESS);
802 }
803 
804 /*
805  * Finish mapping the registers and initializing structures
806  */
807 static int
808 fd_attach_map_regs(dev_info_t *dip, struct fdctlr *fdc)
809 {
810 	ddi_device_acc_attr_t attr;
811 
812 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
813 	attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
814 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
815 
816 	/* Map the DMA registers of the platform supports DMA */
817 	if (fdc->c_fdtype & FDCTYPE_SB) {
818 		if (ddi_regs_map_setup(dip, 1, (caddr_t *)&fdc->c_dma_regs,
819 		    0, sizeof (struct sb_dma_reg), &attr,
820 		    &fdc->c_handlep_dma)) {
821 			return (DDI_FAILURE);
822 		}
823 
824 
825 	} else if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
826 		if (ddi_regs_map_setup(dip, 1, (caddr_t *)&fdc->c_dma_regs,
827 		    0, sizeof (struct cheerio_dma_reg), &attr,
828 		    &fdc->c_handlep_dma)) {
829 			return (DDI_FAILURE);
830 		}
831 	}
832 
833 	/* Reset the DMA engine and enable floppy interrupts */
834 	reset_dma_controller(fdc);
835 	set_dma_control_register(fdc, DCSR_INIT_BITS);
836 
837 	/* Finish initializing structures associated with the device regs */
838 	switch (fdc->c_fdtype & FDCTYPE_CTRLMASK) {
839 	case FDCTYPE_82077:
840 		FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "type is 82077\n"));
841 		/*
842 		 * Initialize addrs of key registers
843 		 */
844 		fdc->c_control =
845 		    (uchar_t *)&fdc->c_reg->fdc_82077_reg.fdc_control;
846 		fdc->c_fifo = (uchar_t *)&fdc->c_reg->fdc_82077_reg.fdc_fifo;
847 		fdc->c_dor = (uchar_t *)&fdc->c_reg->fdc_82077_reg.fdc_dor;
848 		fdc->c_dir = (uchar_t *)&fdc->c_reg->fdc_82077_reg.fdc_dir;
849 
850 
851 		FDERRPRINT(FDEP_L1, FDEM_ATTA, ((int)C,
852 		    (char *)"fdattach: msr/dsr at %p\n",
853 		    (void *)fdc->c_control));
854 
855 		/*
856 		 * The 82077 doesn't use the first configuration parameter
857 		 * so let's adjust that while we know we're an 82077.
858 		 */
859 		fdconf[0] = 0;
860 
861 		quiesce_fd_interrupt(fdc);
862 		break;
863 	default:
864 		break;
865 	}
866 
867 	return (0);
868 }
869 
870 /*
871  * Determine which type of floppy controller is present and
872  * initialize the registers accordingly
873  */
874 static int
875 fd_attach_det_ctlr(dev_info_t *dip, struct fdctlr *fdc)
876 {
877 	ddi_device_acc_attr_t attr;
878 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
879 	/* DDI_NEVERSWAP_ACC since the controller has a byte interface. */
880 	attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
881 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
882 
883 	FDERRPRINT(FDEP_L1, FDEM_ATTA,
884 	    (C, "fdattach_det_cltr: start \n"));
885 
886 	/*
887 	 * First, map in the controller's registers
888 	 * The controller has an 8-bit interface, so byte
889 	 * swapping isn't needed
890 	 */
891 
892 	if (ddi_regs_map_setup(dip, 0, (caddr_t *)&fdc->c_reg,
893 	    0, sizeof (union fdcreg),
894 	    &attr,
895 	    &fdc->c_handlep_cont)) {
896 		return (DDI_FAILURE);
897 	}
898 
899 	FDERRPRINT(FDEP_L1, FDEM_ATTA,
900 	    (C, "fdattach_det_cltr: mapped floppy regs\n"));
901 
902 
903 	/*
904 	 * Set platform specific characteristics based on the device-tree
905 	 * node name.
906 	 */
907 
908 
909 	if (strcmp(ddi_get_name(dip), "SUNW,fdtwo") == 0) {
910 		fdc->c_fdtype |= FDCTYPE_SLAVIO;
911 		fdc->c_fdtype |= FDCTYPE_82077;
912 		fdc->c_auxiova = fd_getauxiova(dip);
913 		fdc->c_auxiodata = (uchar_t)(AUX_MBO4M|AUX_TC4M);
914 		fdc->c_auxiodata2 = (uchar_t)AUX_TC4M;
915 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
916 		    (C, "fdattach: slavio will be used!\n"));
917 
918 
919 /*
920  * Check the binding name to identify whether it is a South bridge based
921  * system or not.
922  */
923 	} else if (strcmp(ddi_get_name(dip), "pnpALI,1533,0") == 0) {
924 
925 		fdc->c_fdtype |= FDCTYPE_SB;
926 		fdc->c_fdtype |= FDCTYPE_82077;
927 		fdc->c_fdtype |= FDCTYPE_DMA;
928 
929 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
930 		    (C, "fdattach: southbridge will be used!\n"));
931 
932 		/*
933 		 * The driver assumes high density characteristics until
934 		 * the diskette is looked at.
935 		 */
936 
937 		fdc->c_fdtype |= FDCTYPE_DMA8237;
938 		FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: DMA used\n"));
939 
940 
941 	} else if (strcmp(ddi_get_name(dip), "fdthree") == 0) {
942 
943 		fdc->c_fdtype |= FDCTYPE_CHEERIO;
944 		fdc->c_fdtype |= FDCTYPE_82077;
945 
946 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
947 		    (C, "fdattach: cheerio will be used!\n"));
948 		/*
949 		 * The cheerio auxio register should be memory mapped.  The
950 		 * auxio register on other platforms is shared and mapped
951 		 * elsewhere in the kernel
952 		 */
953 		if (ddi_regs_map_setup(dip, 2, (caddr_t *)&fdc->c_auxio_reg,
954 		    0, sizeof (uint_t), &attr, &fdc->c_handlep_aux)) {
955 			return (DDI_FAILURE);
956 		}
957 
958 		/*
959 		 * The driver assumes high density characteristics until
960 		 * the diskette is looked at.
961 		 */
962 		Set_auxio(fdc, AUX_HIGH_DENSITY);
963 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
964 		    (C, "fdattach: auxio register 0x%x\n",
965 		    *fdc->c_auxio_reg));
966 
967 		fdc->c_fdtype |= FDCTYPE_DMA;
968 		FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: DMA used\n"));
969 
970 	}
971 
972 	if (fdc->c_fdtype == 0) {
973 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
974 		    (C, "fdattach: no controller!\n"));
975 		return (DDI_FAILURE);
976 	} else {
977 		return (0);
978 	}
979 }
980 
981 
982 /*
983  * Register the floppy interrupts
984  */
985 static int
986 fd_attach_register_interrupts(dev_info_t *dip, struct fdctlr *fdc, int *hard)
987 {
988 	ddi_iblock_cookie_t  iblock_cookie_soft;
989 	int status;
990 
991 	/*
992 	 * First call ddi_get_iblock_cookie() to retrieve the
993 	 * the interrupt block cookie so that the mutexes may
994 	 * be initialized before adding the interrupt.  If the
995 	 * mutexes are initialized after adding the interrupt, there
996 	 * could be a race condition.
997 	 */
998 	if (ddi_get_iblock_cookie(dip, 0, &fdc->c_block) != DDI_SUCCESS) {
999 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
1000 		    (C, "fdattach: ddi_get_iblock_cookie failed\n"));
1001 		return (DDI_FAILURE);
1002 
1003 	}
1004 
1005 	/* Initialize high level mutex */
1006 	mutex_init(&fdc->c_hilock, NULL, MUTEX_DRIVER, fdc->c_block);
1007 
1008 	/*
1009 	 * Try to register fast trap handler, if unable try standard
1010 	 * interrupt handler, else bad
1011 	 */
1012 
1013 	if (fdc->c_fdtype & FDCTYPE_DMA) {
1014 		if (ddi_add_intr(dip, 0, &fdc->c_block, 0,
1015 		    fdintr_dma, (caddr_t)0) == DDI_SUCCESS) {
1016 			FDERRPRINT(FDEP_L1, FDEM_ATTA,
1017 			    (C, "fdattach: standard intr\n"));
1018 
1019 				/*
1020 				 * When DMA is used, the low level lock
1021 				 * is used in the hard interrupt handler.
1022 				 */
1023 				mutex_init(&fdc->c_lolock, NULL,
1024 				    MUTEX_DRIVER, fdc->c_block);
1025 
1026 				*hard = 1;
1027 		} else {
1028 			FDERRPRINT(FDEP_L1, FDEM_ATTA,
1029 			    (C, "fdattach: can't add dma intr\n"));
1030 
1031 			mutex_destroy(&fdc->c_hilock);
1032 
1033 			return (DDI_FAILURE);
1034 		}
1035 	} else {
1036 		/*
1037 		 * Platforms that don't support DMA have both hard
1038 		 * and soft interrupts.
1039 		 */
1040 		if (ddi_add_intr(dip, 0, &fdc->c_block, 0,
1041 		    fd_intr, (caddr_t)0) == DDI_SUCCESS) {
1042 			FDERRPRINT(FDEP_L1, FDEM_ATTA,
1043 			    (C, "fdattach: standard intr\n"));
1044 			*hard = 1;
1045 
1046 			/* fast traps are not enabled */
1047 			fdc->c_fasttrap = 0;
1048 
1049 		} else {
1050 			FDERRPRINT(FDEP_L1, FDEM_ATTA,
1051 			    (C, "fdattach: can't add intr\n"));
1052 
1053 			mutex_destroy(&fdc->c_hilock);
1054 
1055 			return (DDI_FAILURE);
1056 		}
1057 
1058 
1059 		/*
1060 		 * Initialize the soft interrupt handler.  First call
1061 		 * ddi_get_soft_iblock_cookie() so that the mutex may
1062 		 * be initialized before the handler is added.
1063 		 */
1064 		status = ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_LOW,
1065 		    &iblock_cookie_soft);
1066 
1067 
1068 		if (status != DDI_SUCCESS) {
1069 			mutex_destroy(&fdc->c_hilock);
1070 			return (DDI_FAILURE);
1071 		}
1072 
1073 		/*
1074 		 * Initialize low level mutex which is used in the soft
1075 		 * interrupt handler
1076 		 */
1077 		mutex_init(&fdc->c_lolock, NULL, MUTEX_DRIVER,
1078 		    iblock_cookie_soft);
1079 
1080 		if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &fdc->c_softid,
1081 		    NULL, NULL,
1082 		    fd_lointr,
1083 		    (caddr_t)fdc) != DDI_SUCCESS) {
1084 
1085 			mutex_destroy(&fdc->c_hilock);
1086 			mutex_destroy(&fdc->c_lolock);
1087 
1088 			return (DDI_FAILURE);
1089 		}
1090 	}
1091 
1092 	fdc->c_intrstat = kstat_create("fd", 0, "fdc0", "controller",
1093 	    KSTAT_TYPE_INTR, 1, KSTAT_FLAG_PERSISTENT);
1094 	if (fdc->c_intrstat) {
1095 		fdc->c_hiintct = &KIOIP->intrs[KSTAT_INTR_HARD];
1096 		kstat_install(fdc->c_intrstat);
1097 	}
1098 
1099 	/* condition variable to wait on while an io transaction occurs */
1100 	cv_init(&fdc->c_iocv, NULL, CV_DRIVER, NULL);
1101 
1102 	/* condition variable for the csb */
1103 	cv_init(&fdc->c_csbcv, NULL, CV_DRIVER, NULL);
1104 
1105 	/* condition variable for motor on waiting period */
1106 	cv_init(&fdc->c_motoncv, NULL, CV_DRIVER, NULL);
1107 
1108 	/* semaphore to serialize opens and closes */
1109 	sema_init(&fdc->c_ocsem, 1, NULL, SEMA_DRIVER, NULL);
1110 
1111 	/* condition variable to wait on suspended floppy controller. */
1112 	cv_init(&fdc->c_suspend_cv, NULL, CV_DRIVER, NULL);
1113 
1114 	return (0);
1115 }
1116 
1117 /*
1118  * Make sure the drive is present
1119  * 	- acquires the low level lock
1120  */
1121 static int
1122 fd_attach_check_drive(struct fdctlr *fdc)
1123 {
1124 	int tmp_fderrlevel;
1125 	int unit = fdc->c_un->un_unit_no;
1126 
1127 	FDERRPRINT(FDEP_L1, FDEM_ATTA,
1128 	    (C, "fd_attach_check_drive\n"));
1129 
1130 
1131 	mutex_enter(&fdc->c_lolock);
1132 	switch (fdc->c_fdtype & FDCTYPE_CTRLMASK) {
1133 
1134 	/* insure that the eject line is reset */
1135 	case FDCTYPE_82077:
1136 
1137 		/*
1138 		 * Everything but the motor enable, drive select,
1139 		 * and reset bits are turned off.  These three
1140 		 * bits remain as they are.
1141 		 */
1142 		/* LINTED */
1143 		Set_dor(fdc, ~((MOTEN(unit))|DRVSEL|RESET), 0);
1144 
1145 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
1146 		    (C, "fdattach: Dor 0x%x\n", Dor(fdc)));
1147 
1148 		drv_usecwait(5);
1149 		if (unit == 0) {
1150 			/* LINTED */
1151 			Set_dor(fdc, RESET|DRVSEL, 1);
1152 		} else {
1153 
1154 			/* LINTED */
1155 			Set_dor(fdc, DRVSEL, 0);
1156 			/* LINTED */
1157 			Set_dor(fdc, RESET, 1);
1158 		}
1159 
1160 		drv_usecwait(5);
1161 
1162 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
1163 		    (C, "fdattach: Dor 0x%x\n", Dor(fdc)));
1164 
1165 		if (!((fdc->c_fdtype & FDCTYPE_CHEERIO) ||
1166 		    (fdc->c_fdtype & FDCTYPE_SB))) {
1167 			set_auxioreg(AUX_TC4M, 0);
1168 		}
1169 		break;
1170 	default:
1171 		break;
1172 	}
1173 
1174 
1175 	fdgetcsb(fdc);
1176 	if (fdreset(fdc) != 0) {
1177 		mutex_exit(&fdc->c_lolock);
1178 		return (DDI_FAILURE);
1179 	}
1180 
1181 
1182 	/* check for drive present */
1183 
1184 	tmp_fderrlevel = fderrlevel;
1185 
1186 
1187 	fderrlevel = FDEP_LMAX;
1188 
1189 	FDERRPRINT(FDEP_L1, FDEM_ATTA,
1190 	    (C, "fdattach: call fdrecalseek\n"));
1191 
1192 	/* Make sure the drive is present */
1193 	if (fdrecalseek(fdc, unit, -1, 0) != 0) {
1194 		timeout_id_t timeid = fdc->c_mtimeid;
1195 		fderrlevel = tmp_fderrlevel;
1196 		fdc->c_mtimeid = 0;
1197 		mutex_exit(&fdc->c_lolock);
1198 
1199 
1200 		/* Do not hold the mutex over the call to untimeout */
1201 		if (timeid) {
1202 			(void) untimeout(timeid);
1203 		}
1204 
1205 		FDERRPRINT(FDEP_L2, FDEM_ATTA,
1206 		    (C, "fd_attach: no drive?\n"));
1207 
1208 		return (DDI_FAILURE);
1209 	}
1210 
1211 	fderrlevel = tmp_fderrlevel;
1212 
1213 	fdselect(fdc, unit, 0);    /* deselect drive zero (used in fdreset) */
1214 	fdretcsb(fdc);
1215 	mutex_exit(&fdc->c_lolock);
1216 
1217 	return (0);
1218 }
1219 
1220 /*
1221  * Clean up routine used by fd_detach and fd_attach
1222  *
1223  * Note: if the soft id is non-zero, then ddi_add_softintr() completed
1224  * successfully.  I can not make the same assumption about the iblock_cookie
1225  * for the high level interrupt handler.  So, the hard parameter indicates
1226  * whether or not a high level interrupt handler has been added.
1227  *
1228  * If the locks parameter is nonzero, then all mutexes, semaphores and
1229  * condition variables will be destroyed.
1230  *
1231  * Does not assume the low level mutex is held.
1232  *
1233  */
1234 static void
1235 fd_cleanup(dev_info_t *dip, struct fdctlr *fdc, int hard, int locks)
1236 {
1237 
1238 
1239 	FDERRPRINT(FDEP_L1, FDEM_ATTA,
1240 	    (C, "fd_cleanup instance: %d ctlr: 0x%p\n",
1241 	    ddi_get_instance(dip), (void *)fdc));
1242 
1243 
1244 	if (fdc == NULL) {
1245 		return;
1246 	}
1247 
1248 	/*
1249 	 * Remove interrupt handlers first before anything else
1250 	 * is deallocated.
1251 	 */
1252 
1253 	/* Remove hard interrupt if one is registered */
1254 	if (hard) {
1255 		ddi_remove_intr(dip, (uint_t)0, fdc->c_block);
1256 	}
1257 
1258 	/* Remove soft interrupt if one is registered */
1259 	if (fdc->c_softid != NULL)
1260 		ddi_remove_softintr(fdc->c_softid);
1261 
1262 
1263 	/* Remove timers */
1264 	if (fdc->c_fdtype & FDCTYPE_82077) {
1265 		if (fdc->c_mtimeid)
1266 			(void) untimeout(fdc->c_mtimeid);
1267 		/*
1268 		 * Need to turn off motor (includes select/LED for South Bridge
1269 		 * chipset) just in case it was on when timer was removed
1270 		 */
1271 		fdmotoff(fdc);
1272 	}
1273 	if (fdc->c_timeid)
1274 		(void) untimeout(fdc->c_timeid);
1275 
1276 
1277 	/* Remove memory handles */
1278 	if (fdc->c_handlep_cont)
1279 		ddi_regs_map_free(&fdc->c_handlep_cont);
1280 
1281 	if (fdc->c_handlep_aux)
1282 		ddi_regs_map_free(&fdc->c_handlep_aux);
1283 
1284 	if (fdc->c_handlep_dma)
1285 		ddi_regs_map_free(&fdc->c_handlep_dma);
1286 
1287 	if (fdc->c_dma_buf_handle != NULL)
1288 		ddi_dma_mem_free(&fdc->c_dma_buf_handle);
1289 
1290 	if (fdc->c_dmahandle != NULL)
1291 		ddi_dma_free_handle(&fdc->c_dmahandle);
1292 
1293 
1294 	/* Remove all minor nodes */
1295 	ddi_remove_minor_node(dip, NULL);
1296 
1297 
1298 
1299 	/* Remove unit structure if one exists */
1300 	if (fdc->c_un != (struct fdunit *)NULL) {
1301 
1302 		ASSERT(!mutex_owned(&fdc->c_lolock));
1303 
1304 		if (fdc->c_un->un_iostat)
1305 			kstat_delete(fdc->c_un->un_iostat);
1306 		fdc->c_un->un_iostat = NULL;
1307 
1308 		if (fdc->c_un->un_chars)
1309 			kmem_free(fdc->c_un->un_chars, sizeof (struct fd_char));
1310 
1311 		if (fdc->c_un->un_drive)
1312 			kmem_free(fdc->c_un->un_drive,
1313 			    sizeof (struct fd_drive));
1314 
1315 		kmem_free((caddr_t)fdc->c_un, sizeof (struct fdunit));
1316 	}
1317 
1318 	if (fdc->c_intrstat) {
1319 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
1320 		    (C, "fd_cleanup: delete intrstat\n"));
1321 
1322 		kstat_delete(fdc->c_intrstat);
1323 	}
1324 
1325 	fdc->c_intrstat = NULL;
1326 
1327 	if (locks) {
1328 		cv_destroy(&fdc->c_iocv);
1329 		cv_destroy(&fdc->c_csbcv);
1330 		cv_destroy(&fdc->c_motoncv);
1331 		cv_destroy(&fdc->c_suspend_cv);
1332 		sema_destroy(&fdc->c_ocsem);
1333 		mutex_destroy(&fdc->c_hilock);
1334 		mutex_destroy(&fdc->c_lolock);
1335 	}
1336 
1337 
1338 	fdctlrs = fdc->c_next;
1339 	kmem_free(fdc, sizeof (*fdc));
1340 
1341 
1342 }
1343 
1344 
1345 static int
1346 fd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1347 {
1348 	int instance = ddi_get_instance(dip);
1349 	struct fdctlr *fdc = fd_getctlr(instance << FDINSTSHIFT);
1350 	timeout_id_t c_mtimeid;
1351 
1352 	FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_detach\n"));
1353 
1354 	switch (cmd) {
1355 
1356 	case DDI_DETACH:
1357 		/*
1358 		 * The hard parameter is set to 1.  If detach is called, then
1359 		 * attach must have passed meaning that the high level
1360 		 * interrupt handler was successfully added.
1361 		 * Similarly, the locks parameter is also set to 1.
1362 		 */
1363 		fd_cleanup(dip, fdc, 1, 1);
1364 
1365 		ddi_prop_remove_all(dip);
1366 
1367 		return (DDI_SUCCESS);
1368 
1369 	case DDI_SUSPEND:
1370 		if (!fdc)
1371 			return (DDI_FAILURE);
1372 
1373 
1374 		mutex_enter(&fdc->c_lolock);
1375 		fdgetcsb(fdc);	/* Wait for I/O to finish */
1376 		c_mtimeid = fdc->c_mtimeid;
1377 		fdretcsb(fdc);
1378 		mutex_exit(&fdc->c_lolock);
1379 
1380 		(void) untimeout(c_mtimeid);
1381 		/*
1382 		 * After suspend, the system could be powered off.
1383 		 * When it is later powered on the southbridge floppy
1384 		 * controller will tristate the interrupt line causing
1385 		 * continuous dma interrupts.
1386 		 * To avoid getting continuous fd interrupts we will remove the
1387 		 * dma interrupt handler installed. We will re-install the
1388 		 * handler when we RESUME.
1389 		 */
1390 		if (fdc->c_fdtype & FDCTYPE_SB)
1391 			ddi_remove_intr(dip, 0, fdc->c_block);
1392 
1393 		fdc->c_un->un_state = FD_STATE_SUSPENDED;
1394 
1395 		return (DDI_SUCCESS);
1396 
1397 	default:
1398 		return (DDI_FAILURE);
1399 	}
1400 }
1401 
1402 /* ARGSUSED */
1403 static int
1404 fd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
1405 {
1406 	register struct fdctlr *fdc;
1407 	register int error;
1408 
1409 	switch (infocmd) {
1410 
1411 	case DDI_INFO_DEVT2DEVINFO:
1412 		if ((fdc = fd_getctlr((dev_t)arg)) == NULL) {
1413 			error = DDI_FAILURE;
1414 		} else {
1415 			*result = fdc->c_dip;
1416 			error = DDI_SUCCESS;
1417 		}
1418 		break;
1419 
1420 	case DDI_INFO_DEVT2INSTANCE:
1421 		*result = 0;
1422 		error = DDI_SUCCESS;
1423 		break;
1424 
1425 	default:
1426 		error = DDI_FAILURE;
1427 	}
1428 	return (error);
1429 }
1430 
1431 /*
1432  * property operation routine.  return the number of blocks for the partition
1433  * in question or forward the request to the property facilities.
1434  */
1435 static int
1436 fd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1437     char *name, caddr_t valuep, int *lengthp)
1438 {
1439 	struct fdunit	*un;
1440 	struct fdctlr	*fdc;
1441 	uint64_t	nblocks64;
1442 
1443 	/*
1444 	 * Our dynamic properties are all device specific and size oriented.
1445 	 * Requests issued under conditions where size is valid are passed
1446 	 * to ddi_prop_op_nblocks with the size information, otherwise the
1447 	 * request is passed to ddi_prop_op.
1448 	 */
1449 	if (dev == DDI_DEV_T_ANY) {
1450 pass:  		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1451 		    name, valuep, lengthp));
1452 	} else {
1453 		fdc = fd_getctlr(dev);
1454 		if (fdc == NULL)
1455 			goto pass;
1456 
1457 		/* we have size if diskette opened and label read */
1458 		un = fdc->c_un;
1459 		if ((un == NULL) || !fd_unit_is_open(fdc->c_un))
1460 			goto pass;
1461 
1462 		/* get nblocks value */
1463 		nblocks64 = (ulong_t)
1464 		    un->un_label.dkl_map[FDPARTITION(dev)].dkl_nblk;
1465 
1466 		return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags,
1467 		    name, valuep, lengthp, nblocks64));
1468 	}
1469 }
1470 
1471 /* ARGSUSED3 */
1472 static int
1473 fd_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
1474 {
1475 	dev_t dev;
1476 	int  part;
1477 	struct fdctlr *fdc;
1478 	struct fdunit *un;
1479 	struct dk_map32 *dkm;
1480 	uchar_t	pbit;
1481 	int	err, part_is_open;
1482 	int 	unit;
1483 
1484 	dev = *devp;
1485 	fdc = fd_getctlr(dev);
1486 	if ((fdc == NULL) || ((un = fdc->c_un) == NULL)) {
1487 		return (ENXIO);
1488 	}
1489 
1490 	unit = fdc->c_un->un_unit_no;
1491 
1492 	/*
1493 	 * Serialize opens/closes
1494 	 */
1495 
1496 	sema_p(&fdc->c_ocsem);
1497 
1498 	/* check partition */
1499 	part = FDPARTITION(dev);
1500 	pbit = 1 << part;
1501 	dkm = &un->un_label.dkl_map[part];
1502 	if (dkm->dkl_nblk == 0) {
1503 		sema_v(&fdc->c_ocsem);
1504 		return (ENXIO);
1505 	}
1506 
1507 	FDERRPRINT(FDEP_L1, FDEM_OPEN,
1508 	    (C, "fdopen: ctlr %d unit %d part %d\n",
1509 	    ddi_get_instance(fdc->c_dip), unit, part));
1510 
1511 	FDERRPRINT(FDEP_L1, FDEM_OPEN,
1512 	    (C, "fdopen: flag 0x%x", flag));
1513 
1514 
1515 	/*
1516 	 * Insure that drive is present with a recalibrate on first open.
1517 	 */
1518 	(void) pm_busy_component(fdc->c_dip, 0);
1519 
1520 	mutex_enter(&fdc->c_lolock);
1521 
1522 	CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc);
1523 
1524 	if (fdc->c_un->un_state == FD_STATE_STOPPED) {
1525 		mutex_exit(&fdc->c_lolock);
1526 		if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON))
1527 		    != DDI_SUCCESS) {
1528 			FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power change \
1529 			    failed. \n"));
1530 
1531 				sema_v(&fdc->c_ocsem);
1532 				(void) pm_idle_component(fdc->c_dip, 0);
1533 				return (EIO);
1534 		}
1535 		mutex_enter(&fdc->c_lolock);
1536 	}
1537 	if (fd_unit_is_open(un) == 0) {
1538 		fdgetcsb(fdc);
1539 		/*
1540 		 * no check changed!
1541 		 */
1542 		err = fdrecalseek(fdc, unit, -1, 0);
1543 		fdretcsb(fdc);
1544 		if (err) {
1545 			FDERRPRINT(FDEP_L3, FDEM_OPEN,
1546 			    (C, "fd%d: drive not ready\n", 0));
1547 			/* deselect drv on last close */
1548 			fdselect(fdc, unit, 0);
1549 			mutex_exit(&fdc->c_lolock);
1550 			sema_v(&fdc->c_ocsem);
1551 			(void) pm_idle_component(fdc->c_dip, 0);
1552 			return (EIO);
1553 		}
1554 	}
1555 
1556 	/*
1557 	 * Check for previous exclusive open, or trying to exclusive open
1558 	 */
1559 	if (otyp == OTYP_LYR) {
1560 		part_is_open = (un->un_lyropen[part] != 0);
1561 	} else {
1562 		part_is_open = fd_part_is_open(un, part);
1563 	}
1564 	if ((un->un_exclmask & pbit) || ((flag & FEXCL) && part_is_open)) {
1565 		mutex_exit(&fdc->c_lolock);
1566 		sema_v(&fdc->c_ocsem);
1567 		FDERRPRINT(FDEP_L2, FDEM_OPEN, (C, "fd:just return\n"));
1568 		(void) pm_idle_component(fdc->c_dip, 0);
1569 		return (EBUSY);
1570 	}
1571 
1572 	/* don't attempt access, just return successfully */
1573 	if (flag & (FNDELAY | FNONBLOCK)) {
1574 		FDERRPRINT(FDEP_L2, FDEM_OPEN,
1575 		    (C, "fd: return busy..\n"));
1576 		goto out;
1577 	}
1578 
1579 	fdc->c_csb.csb_unit = (uchar_t)unit;
1580 	if (fdgetlabel(fdc, unit)) {
1581 		/* didn't find label (couldn't read anything) */
1582 		FDERRPRINT(FDEP_L3, FDEM_OPEN,
1583 		    (C,
1584 		    "fd%d: unformatted diskette or no diskette in the drive\n",
1585 		    0));
1586 		if (fd_unit_is_open(un) == 0) {
1587 			/* deselect drv on last close */
1588 			fdselect(fdc, unit, 0);
1589 		}
1590 
1591 		mutex_exit(&fdc->c_lolock);
1592 		sema_v(&fdc->c_ocsem);
1593 		(void) pm_idle_component(fdc->c_dip, 0);
1594 		return (EIO);
1595 	}
1596 
1597 	/*
1598 	 * if opening for writing, check write protect on diskette
1599 	 */
1600 	if (flag & FWRITE) {
1601 		fdgetcsb(fdc);
1602 		err = fdsensedrv(fdc, unit) & WP_SR3;
1603 		fdretcsb(fdc);
1604 		if (err) {
1605 			if (fd_unit_is_open(un) == 0)
1606 				fdselect(fdc, unit, 0);
1607 			mutex_exit(&fdc->c_lolock);
1608 			sema_v(&fdc->c_ocsem);
1609 			(void) pm_idle_component(fdc->c_dip, 0);
1610 			return (EROFS);
1611 		}
1612 	}
1613 
1614 out:
1615 	/*
1616 	 * mark open as having succeeded
1617 	 */
1618 	if (flag & FEXCL) {
1619 		un->un_exclmask |= pbit;
1620 	}
1621 	if (otyp == OTYP_LYR) {
1622 		un->un_lyropen[part]++;
1623 	} else {
1624 		un->un_regopen[otyp] |= pbit;
1625 	}
1626 	mutex_exit(&fdc->c_lolock);
1627 	sema_v(&fdc->c_ocsem);
1628 	(void) pm_idle_component(fdc->c_dip, 0);
1629 	return (0);
1630 }
1631 /*
1632  * fd_part_is_open
1633  *	return 1 if the partition is open
1634  *	return 0 otherwise
1635  */
1636 static int
1637 fd_part_is_open(struct fdunit *un, int part)
1638 {
1639 	int i;
1640 	for (i = 0; i < OTYPCNT - 1; i++)
1641 		if (un->un_regopen[i] & (1 << part))
1642 			return (1);
1643 	return (0);
1644 }
1645 
1646 
1647 /* ARGSUSED */
1648 static int
1649 fd_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
1650 {
1651 	int unit, part_is_closed, part;
1652 	register struct fdctlr *fdc;
1653 	register struct fdunit *un;
1654 
1655 	fdc = fd_getctlr(dev);
1656 	if (!fdc || !(un = fdc->c_un))
1657 		return (ENXIO);
1658 
1659 
1660 	unit = fdc->c_un->un_unit_no;
1661 	FDERRPRINT(FDEP_L1, FDEM_CLOS, (C, "fd_close\n"));
1662 	part = FDPARTITION(dev);
1663 
1664 	sema_p(&fdc->c_ocsem);
1665 	mutex_enter(&fdc->c_lolock);
1666 
1667 	if (otyp == OTYP_LYR) {
1668 		un->un_lyropen[part]--;
1669 		part_is_closed = (un->un_lyropen[part] == 0);
1670 	} else {
1671 		un->un_regopen[otyp] &= ~(1<<part);
1672 		part_is_closed = 1;
1673 	}
1674 	if (part_is_closed)
1675 		un->un_exclmask &= ~(1<<part);
1676 
1677 	if (fd_unit_is_open(un) == 0) {
1678 		/* deselect drive on last close */
1679 		fdselect(fdc, unit, 0);
1680 		un->un_flags &= ~FDUNIT_CHANGED;
1681 	}
1682 	mutex_exit(&fdc->c_lolock);
1683 	sema_v(&fdc->c_ocsem);
1684 
1685 	return (0);
1686 }
1687 
1688 /*
1689  * fd_strategy
1690  *	checks operation, hangs buf struct off fdctlr, calls fdstart
1691  *	if not already busy.  Note that if we call start, then the operation
1692  *	will already be done on return (start sleeps).
1693  */
1694 static int
1695 fd_strategy(register struct buf *bp)
1696 {
1697 	struct fdctlr *fdc;
1698 	struct fdunit *un;
1699 	uint_t	phys_blkno;
1700 	struct dk_map32 *dkm;
1701 
1702 	FDERRPRINT(FDEP_L1, FDEM_STRA,
1703 	    (C, "fd_strategy: bp = 0x%p, dev = 0x%lx\n",
1704 	    (void *)bp, bp->b_edev));
1705 	FDERRPRINT(FDEP_L1, FDEM_STRA,
1706 	    (C, "b_blkno=%x b_flags=%x b_count=%x\n",
1707 	    (int)bp->b_blkno, bp->b_flags, (int)bp->b_bcount));
1708 	fdc = fd_getctlr(bp->b_edev);
1709 	un = fdc->c_un;
1710 	dkm = &un->un_label.dkl_map[FDPARTITION(bp->b_edev)];
1711 
1712 	/*
1713 	 * If it's medium density and the block no. isn't a multiple
1714 	 * of 1K, then return an error.
1715 	 */
1716 	if (un->un_chars->fdc_medium) {
1717 		phys_blkno = (uint_t)bp->b_blkno >> 1;
1718 		if (bp->b_blkno & 1) {
1719 			FDERRPRINT(FDEP_L3, FDEM_STRA,
1720 			    (C, "b_blkno=0x%lx is not 1k aligned\n",
1721 			    (long)bp->b_blkno));
1722 			bp->b_error = EINVAL;
1723 			bp->b_resid = bp->b_bcount;
1724 			bp->b_flags |= B_ERROR;
1725 			biodone(bp);
1726 			return (0);
1727 		}
1728 	} else {
1729 		phys_blkno = (uint_t)bp->b_blkno;
1730 	}
1731 
1732 
1733 	/* If the block number is past the end, return an error */
1734 	if ((phys_blkno > dkm->dkl_nblk)) {
1735 		FDERRPRINT(FDEP_L3, FDEM_STRA,
1736 		    (C, "fd%d: block %ld is past the end! (nblk=%d)\n",
1737 		    0, (long)bp->b_blkno, dkm->dkl_nblk));
1738 		bp->b_error = ENOSPC;
1739 		bp->b_resid = bp->b_bcount;
1740 		bp->b_flags |= B_ERROR;
1741 		biodone(bp);
1742 		return (0);
1743 	}
1744 
1745 	/* if at end of file, skip out now */
1746 	if (phys_blkno == dkm->dkl_nblk) {
1747 		FDERRPRINT(FDEP_L1, FDEM_STRA,
1748 		    (C, "b_blkno is at the end!\n"));
1749 
1750 		if ((bp->b_flags & B_READ) == 0) {
1751 			/* a write needs to get an error! */
1752 			bp->b_error = ENOSPC;
1753 			bp->b_flags |= B_ERROR;
1754 
1755 			FDERRPRINT(FDEP_L1, FDEM_STRA,
1756 			    (C, "block is at end and this is a write\n"));
1757 
1758 		}
1759 
1760 		bp->b_resid = bp->b_bcount;
1761 		biodone(bp);
1762 		return (0);
1763 	}
1764 
1765 	/* if operation not a multiple of sector size, is error! */
1766 	if (bp->b_bcount % un->un_chars->fdc_sec_size)	{
1767 		FDERRPRINT(FDEP_L3, FDEM_STRA,
1768 		    (C, "fd%d: requested transfer size(0x%lx) is not"
1769 		    " multiple of sector size(0x%x)\n", 0,
1770 		    bp->b_bcount, un->un_chars->fdc_sec_size));
1771 		FDERRPRINT(FDEP_L3, FDEM_STRA,
1772 		    (C, "	b_blkno=0x%lx b_flags=0x%x\n",
1773 		    (long)bp->b_blkno, bp->b_flags));
1774 		bp->b_error = EINVAL;
1775 		bp->b_resid = bp->b_bcount;
1776 		bp->b_flags |= B_ERROR;
1777 		biodone(bp);
1778 		return (0);
1779 
1780 	}
1781 
1782 	/*
1783 	 * Put the buf request in the controller's queue, FIFO.
1784 	 */
1785 	bp->av_forw = 0;
1786 	sema_p(&fdc->c_ocsem);
1787 
1788 	(void) pm_busy_component(fdc->c_dip, 0);
1789 
1790 	mutex_enter(&fdc->c_lolock);
1791 
1792 	CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc);
1793 
1794 	if (fdc->c_un->un_state == FD_STATE_STOPPED) {
1795 		mutex_exit(&fdc->c_lolock);
1796 		if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON))
1797 		    != DDI_SUCCESS) {
1798 			sema_v(&fdc->c_ocsem);
1799 			(void) pm_idle_component(fdc->c_dip, 0);
1800 			bp->b_error = EIO;
1801 			bp->b_resid = bp->b_bcount;
1802 			bp->b_flags |= B_ERROR;
1803 			biodone(bp);
1804 			return (0);
1805 		} else {
1806 			mutex_enter(&fdc->c_lolock);
1807 		}
1808 	}
1809 	if (un->un_iostat) {
1810 		kstat_waitq_enter(KIOSP);
1811 	}
1812 	if (fdc->c_actf)
1813 		fdc->c_actl->av_forw = bp;
1814 	else
1815 		fdc->c_actf = bp;
1816 	fdc->c_actl = bp;
1817 
1818 
1819 	/* call fdstart to start the transfer */
1820 	fdstart(fdc);
1821 
1822 	mutex_exit(&fdc->c_lolock);
1823 	sema_v(&fdc->c_ocsem);
1824 	(void) pm_idle_component(fdc->c_dip, 0);
1825 	return (0);
1826 }
1827 
1828 /* ARGSUSED2 */
1829 static int
1830 fd_read(dev_t dev, struct uio *uio, cred_t *cred_p)
1831 {
1832 	FDERRPRINT(FDEP_L1, FDEM_RDWR, (C, "fd_read\n"));
1833 	return (physio(fd_strategy, NULL, dev, B_READ, minphys, uio));
1834 }
1835 
1836 /* ARGSUSED2 */
1837 static int
1838 fd_write(dev_t dev, struct uio *uio, cred_t *cred_p)
1839 {
1840 	FDERRPRINT(FDEP_L1, FDEM_RDWR, (C, "fd_write\n"));
1841 	return (physio(fd_strategy, NULL, dev, B_WRITE, minphys, uio));
1842 }
1843 
1844 static void
1845 fdmotoff(void *arg)
1846 {
1847 	struct fdctlr *fdc = arg;
1848 	int unit = fdc->c_un->un_unit_no;
1849 
1850 	mutex_enter(&fdc->c_lolock);
1851 
1852 	/* Just return if we're about to call untimeout */
1853 	if (fdc->c_mtimeid == 0) {
1854 		mutex_exit(&fdc->c_lolock);
1855 		return;
1856 	}
1857 
1858 	FDERRPRINT(FDEP_L1, FDEM_MOFF, (C, "fdmotoff\n"));
1859 
1860 	fdc->c_mtimeid = 0;
1861 
1862 	if (!(Msr(fdc) & CB) && (Dor(fdc) & (MOTEN(unit)))) {
1863 		/* LINTED */
1864 		Set_dor(fdc, MOTEN(unit), 0);
1865 	}
1866 
1867 	mutex_exit(&fdc->c_lolock);
1868 }
1869 
1870 /* ARGSUSED */
1871 static int
1872 fd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag,
1873 	cred_t *cred_p, int *rval_p)
1874 {
1875 	union {
1876 		struct dk_cinfo dki;
1877 		struct dk_geom dkg;
1878 		struct dk_allmap32 dka;
1879 		struct fd_char fdchar;
1880 		struct fd_drive drvchar;
1881 		int	temp;
1882 	} cpy;
1883 
1884 	struct vtoc	vtoc;
1885 	struct fdunit *un;
1886 	struct fdctlr *fdc;
1887 	int unit, dkunit;
1888 	int err = 0;
1889 	uint_t	sec_size;
1890 	enum dkio_state state;
1891 	int	transfer_rate;
1892 
1893 	FDERRPRINT(FDEP_L1, FDEM_IOCT,
1894 	    (C, "fd_ioctl: cmd 0x%x, arg 0x%lx\n", cmd, (long)arg));
1895 
1896 	/* The minor number should always be 0 */
1897 	if (FDUNIT(dev) != 0)
1898 		return (ENXIO);
1899 
1900 	fdc = fd_getctlr(dev);
1901 	unit = fdc->c_un->un_unit_no;
1902 	un = fdc->c_un;
1903 	sec_size = un->un_chars->fdc_sec_size;
1904 	bzero(&cpy, sizeof (cpy));
1905 
1906 	switch (cmd) {
1907 	case DKIOCINFO:
1908 		cpy.dki.dki_addr = 0;
1909 
1910 		/*
1911 		 * The meaning of the dki_slave and dki_unit fields
1912 		 * is unclear.  The sparc floppy driver follows the same
1913 		 * convention as sd.c in that the instance number is
1914 		 * returned in the dki_cnum field.  The dki_slave field is
1915 		 * ignored.
1916 		 *
1917 		 * The dki_cnum contains the controller instance
1918 		 * and its value can be any positive number. Even
1919 		 * though currently Sparc platforms only support
1920 		 * one controller, the controller instance number
1921 		 * can be any number since it is assigned by the
1922 		 * system depending on the device properties.
1923 		 */
1924 
1925 		cpy.dki.dki_cnum = FDCTLR(dev);
1926 
1927 		/*
1928 		 * Sparc platforms support only one floppy drive.
1929 		 * The device node for the controller is the same as
1930 		 * the device node for the drive.  The x86 driver is
1931 		 * different in that it has a node for the controller
1932 		 * and a child node for each drive. Since Sparc supports
1933 		 * only one drive, the unit number will always be zero.
1934 		 */
1935 
1936 		cpy.dki.dki_unit = FDUNIT(dev);
1937 
1938 		/*
1939 		 * The meaning of the dki_slave field is unclear.
1940 		 * So, I will leave it set to 0.
1941 		 */
1942 
1943 		cpy.dki.dki_slave = 0;
1944 
1945 		cpy.dki.dki_ctype = (ushort_t)-1;
1946 		if (fdc->c_fdtype & FDCTYPE_82077)
1947 			cpy.dki.dki_ctype = DKC_INTEL82077;
1948 		cpy.dki.dki_flags = DKI_FMTTRK;
1949 		cpy.dki.dki_partition = FDPARTITION(dev);
1950 		cpy.dki.dki_maxtransfer = maxphys / DEV_BSIZE;
1951 		if (ddi_copyout((caddr_t)&cpy.dki, (caddr_t)arg,
1952 		    sizeof (cpy.dki), flag))
1953 			err = EFAULT;
1954 		break;
1955 	case DKIOCGGEOM:
1956 		cpy.dkg.dkg_ncyl = un->un_chars->fdc_ncyl;
1957 		cpy.dkg.dkg_nhead = un->un_chars->fdc_nhead;
1958 		cpy.dkg.dkg_nsect = un->un_chars->fdc_secptrack;
1959 		cpy.dkg.dkg_intrlv = un->un_label.dkl_intrlv;
1960 		cpy.dkg.dkg_rpm = un->un_label.dkl_rpm;
1961 		cpy.dkg.dkg_pcyl = un->un_chars->fdc_ncyl;
1962 		cpy.dkg.dkg_read_reinstruct =
1963 		    (int)(cpy.dkg.dkg_nsect * cpy.dkg.dkg_rpm * 4) / 60000;
1964 		cpy.dkg.dkg_write_reinstruct = cpy.dkg.dkg_read_reinstruct;
1965 		if (ddi_copyout((caddr_t)&cpy.dkg, (caddr_t)arg,
1966 		    sizeof (cpy.dkg), flag))
1967 			err = EFAULT;
1968 		break;
1969 	case DKIOCSGEOM:
1970 		FDERRPRINT(FDEP_L3, FDEM_IOCT,
1971 		    (C, "fd_ioctl: DKIOCSGEOM not supported\n"));
1972 		err = ENOTTY;
1973 		break;
1974 
1975 	/*
1976 	 * return the map of all logical partitions
1977 	 */
1978 	case DKIOCGAPART:
1979 		/*
1980 		 * We don't have anything to do if the application is ILP32
1981 		 * because the label map has a 32-bit format. Otherwise
1982 		 * convert.
1983 		 */
1984 		if ((flag & DATAMODEL_MASK) == DATAMODEL_ILP32) {
1985 			if (ddi_copyout(&un->un_label.dkl_map,
1986 			    (void *)arg, sizeof (struct dk_allmap32), flag))
1987 				err = EFAULT;
1988 		}
1989 #ifdef _MULTI_DATAMODEL
1990 		else {
1991 			struct dk_allmap dk_allmap;
1992 
1993 			ASSERT((flag & DATAMODEL_MASK) == DATAMODEL_LP64);
1994 			for (dkunit = 0; dkunit < NDKMAP; dkunit++) {
1995 				dk_allmap.dka_map[dkunit].dkl_cylno =
1996 				    un->un_label.dkl_map[dkunit].dkl_cylno;
1997 				dk_allmap.dka_map[dkunit].dkl_nblk =
1998 				    un->un_label.dkl_map[dkunit].dkl_nblk;
1999 			}
2000 			if (ddi_copyout(&dk_allmap, (void *)arg,
2001 			    sizeof (struct dk_allmap), flag))
2002 				err = EFAULT;
2003 		}
2004 #endif /* _MULTI_DATAMODEL */
2005 		break;
2006 
2007 	/*
2008 	 * Set the map of all logical partitions
2009 	 */
2010 	case DKIOCSAPART:
2011 		if ((flag & DATAMODEL_MASK) == DATAMODEL_ILP32) {
2012 			if (ddi_copyin((const void *)arg, &cpy.dka,
2013 			    sizeof (cpy.dka), flag))
2014 				return (EFAULT);
2015 			else {
2016 				mutex_enter(&fdc->c_lolock);
2017 				for (dkunit = 0; dkunit < NDKMAP; dkunit++) {
2018 					un->un_label.dkl_map[dkunit] =
2019 					    cpy.dka.dka_map[dkunit];
2020 				}
2021 				mutex_exit(&fdc->c_lolock);
2022 			}
2023 		}
2024 #ifdef _MULTI_DATAMODEL
2025 		else {
2026 			struct dk_allmap dk_allmap;
2027 
2028 			ASSERT((flag & DATAMODEL_MASK) == DATAMODEL_LP64);
2029 			if (ddi_copyin((const void *)arg, &dk_allmap,
2030 			    sizeof (dk_allmap), flag))
2031 				return (EFAULT);
2032 			else {
2033 				mutex_enter(&fdc->c_lolock);
2034 				for (dkunit = 0; dkunit < NDKMAP; dkunit++) {
2035 					un->un_label.dkl_map[dkunit].dkl_cylno =
2036 					    dk_allmap.dka_map[dkunit].dkl_cylno;
2037 					un->un_label.dkl_map[dkunit].dkl_nblk =
2038 					    dk_allmap.dka_map[dkunit].dkl_nblk;
2039 				}
2040 				mutex_exit(&fdc->c_lolock);
2041 			}
2042 		}
2043 #endif /* _MULTI_DATAMODEL */
2044 		break;
2045 
2046 	case DKIOCGVTOC:
2047 		mutex_enter(&fdc->c_lolock);
2048 
2049 		/*
2050 		 * Exit if the diskette has no label.
2051 		 * Also, get the label to make sure the
2052 		 * correct one is being used since the diskette
2053 		 * may have changed
2054 		 */
2055 		if (fdgetlabel(fdc, unit)) {
2056 			mutex_exit(&fdc->c_lolock);
2057 			err = EINVAL;
2058 			break;
2059 		}
2060 
2061 		/* Build a vtoc from the diskette's label */
2062 		fd_build_user_vtoc(un, &vtoc);
2063 		mutex_exit(&fdc->c_lolock);
2064 
2065 #ifdef _MULTI_DATAMODEL
2066 		switch (ddi_model_convert_from(flag & FMODELS)) {
2067 		case DDI_MODEL_ILP32: {
2068 			struct vtoc32 vtoc32;
2069 
2070 			vtoctovtoc32(vtoc, vtoc32);
2071 			if (ddi_copyout(&vtoc32, (void *)arg,
2072 			    sizeof (struct vtoc32), flag))
2073 				return (EFAULT);
2074 			break;
2075 		}
2076 
2077 		case DDI_MODEL_NONE:
2078 			if (ddi_copyout(&vtoc, (void *)arg,
2079 			    sizeof (vtoc), flag))
2080 				return (EFAULT);
2081 			break;
2082 		}
2083 #else /* ! _MULTI_DATAMODEL */
2084 		if (ddi_copyout(&vtoc, (void *)arg, sizeof (vtoc), flag))
2085 			return (EFAULT);
2086 #endif /* _MULTI_DATAMODEL */
2087 		break;
2088 
2089 	case DKIOCSVTOC:
2090 
2091 #ifdef _MULTI_DATAMODEL
2092 		switch (ddi_model_convert_from(flag & FMODELS)) {
2093 		case DDI_MODEL_ILP32: {
2094 			struct vtoc32 vtoc32;
2095 
2096 			if (ddi_copyin((const void *)arg, &vtoc32,
2097 			    sizeof (struct vtoc32), flag)) {
2098 				return (EFAULT);
2099 			}
2100 			vtoc32tovtoc(vtoc32, vtoc);
2101 			break;
2102 		}
2103 
2104 		case DDI_MODEL_NONE:
2105 			if (ddi_copyin((const void *)arg, &vtoc,
2106 			    sizeof (vtoc), flag)) {
2107 				return (EFAULT);
2108 			}
2109 			break;
2110 		}
2111 #else /* ! _MULTI_DATAMODEL */
2112 		if (ddi_copyin((const void *)arg, &vtoc, sizeof (vtoc), flag))
2113 			return (EFAULT);
2114 #endif /* _MULTI_DATAMODEL */
2115 
2116 		mutex_enter(&fdc->c_lolock);
2117 
2118 		/*
2119 		 * The characteristics structure must be filled in because
2120 		 * it helps build the vtoc.
2121 		 */
2122 		if ((un->un_chars->fdc_ncyl == 0) ||
2123 		    (un->un_chars->fdc_nhead == 0) ||
2124 		    (un->un_chars->fdc_secptrack == 0)) {
2125 			mutex_exit(&fdc->c_lolock);
2126 			err = EINVAL;
2127 			break;
2128 		}
2129 
2130 		if ((err = fd_build_label_vtoc(un, &vtoc)) != 0) {
2131 			mutex_exit(&fdc->c_lolock);
2132 			break;
2133 		}
2134 
2135 		(void) pm_busy_component(fdc->c_dip, 0);
2136 
2137 		err = fdrw(fdc, unit, FDWRITE, 0, 0, 1,
2138 		    (caddr_t)&un->un_label, sizeof (struct dk_label));
2139 		mutex_exit(&fdc->c_lolock);
2140 		(void) pm_idle_component(fdc->c_dip, 0);
2141 		break;
2142 
2143 	case DKIOCSTATE:
2144 		if (ddi_copyin((caddr_t)arg, (caddr_t)&state,
2145 		    sizeof (int), flag)) {
2146 			err = EFAULT;
2147 			break;
2148 		}
2149 		(void) pm_busy_component(fdc->c_dip, 0);
2150 
2151 		err = fd_check_media(dev, state);
2152 		(void) pm_idle_component(fdc->c_dip, 0);
2153 
2154 		if (ddi_copyout((caddr_t)&un->un_media_state,
2155 		    (caddr_t)arg, sizeof (int), flag))
2156 			err = EFAULT;
2157 		break;
2158 
2159 	case FDIOGCHAR:
2160 		if (ddi_copyout((caddr_t)un->un_chars, (caddr_t)arg,
2161 		    sizeof (struct fd_char), flag))
2162 			err = EFAULT;
2163 		break;
2164 
2165 	case FDIOSCHAR:
2166 		if (ddi_copyin((caddr_t)arg, (caddr_t)&cpy.fdchar,
2167 				sizeof (struct fd_char), flag)) {
2168 			err = EFAULT;
2169 			break;
2170 		}
2171 
2172 		/*
2173 		 * Check the fields in the fdchar structure that are either
2174 		 * driver or controller dependent.
2175 		 */
2176 
2177 		transfer_rate = cpy.fdchar.fdc_transfer_rate;
2178 		if ((transfer_rate != 500) && (transfer_rate != 300) &&
2179 		    (transfer_rate != 250) && (transfer_rate != 1000)) {
2180 			FDERRPRINT(FDEP_L3, FDEM_IOCT,
2181 			    (C, "fd_ioctl: FDIOSCHAR odd transfer rate %d\n",
2182 			    cpy.fdchar.fdc_transfer_rate));
2183 			err = EINVAL;
2184 			break;
2185 		}
2186 
2187 		if ((cpy.fdchar.fdc_nhead < 1) ||
2188 		    (cpy.fdchar.fdc_nhead > 2)) {
2189 			FDERRPRINT(FDEP_L3, FDEM_IOCT,
2190 			    (C, "fd_ioctl: FDIOSCHAR bad no. of heads %d\n",
2191 			    cpy.fdchar.fdc_nhead));
2192 			err = EINVAL;
2193 			break;
2194 		}
2195 
2196 		/*
2197 		 * The number of cylinders must be between 0 and 255
2198 		 */
2199 		if ((cpy.fdchar.fdc_ncyl < 0) || (cpy.fdchar.fdc_ncyl > 255)) {
2200 			FDERRPRINT(FDEP_L3, FDEM_IOCT,
2201 			    (C, "fd_ioctl: FDIOSCHAR bad cyl no %d\n",
2202 			    cpy.fdchar.fdc_ncyl));
2203 			err = EINVAL;
2204 			break;
2205 		}
2206 
2207 		/* Copy the fdchar structure */
2208 
2209 		mutex_enter(&fdc->c_lolock);
2210 		*(un->un_chars) = cpy.fdchar;
2211 
2212 		un->un_curfdtype = -1;
2213 
2214 		mutex_exit(&fdc->c_lolock);
2215 
2216 		break;
2217 	case FDEJECT:  /* eject disk */
2218 	case DKIOCEJECT:
2219 
2220 		/*
2221 		 * Fail the ioctl if auto-eject isn't supported
2222 		 */
2223 		if (fdc->c_un->un_drive->fdd_ejectable == 0) {
2224 
2225 			err = ENOSYS;
2226 
2227 		} else {
2228 			(void) pm_busy_component(fdc->c_dip, 0);
2229 
2230 			mutex_enter(&fdc->c_lolock);
2231 
2232 			CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc);
2233 
2234 			if (fdc->c_un->un_state == FD_STATE_STOPPED) {
2235 				mutex_exit(&fdc->c_lolock);
2236 				if ((pm_raise_power(fdc->c_dip, 0,
2237 				    PM_LEVEL_ON)) != DDI_SUCCESS) {
2238 					(void) pm_idle_component(fdc->c_dip, 0);
2239 					err = EIO;
2240 				}
2241 				mutex_enter(&fdc->c_lolock);
2242 			}
2243 		}
2244 		if (err == 0) {
2245 			fdselect(fdc, unit, 1);
2246 			fdeject(fdc, unit);
2247 			mutex_exit(&fdc->c_lolock);
2248 		}
2249 
2250 		(void) pm_idle_component(fdc->c_dip, 0);
2251 
2252 		/*
2253 		 * Make sure the drive is turned off
2254 		 */
2255 		if (fdc->c_fdtype & FDCTYPE_82077) {
2256 			if (fdc->c_mtimeid == 0) {
2257 				fdc->c_mtimeid = timeout(fdmotoff, fdc,
2258 				    Motoff_delay);
2259 			}
2260 		}
2261 
2262 		break;
2263 	case FDGETCHANGE: /* disk changed */
2264 
2265 		if (ddi_copyin((caddr_t)arg, (caddr_t)&cpy.temp,
2266 		    sizeof (int), flag)) {
2267 			err = EFAULT;
2268 			break;
2269 		}
2270 
2271 		/* zero out the user's parameter */
2272 		cpy.temp = 0;
2273 
2274 		(void) pm_busy_component(fdc->c_dip, 0);
2275 
2276 		mutex_enter(&fdc->c_lolock);
2277 
2278 		CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc);
2279 
2280 		if (fdc->c_un->un_state == FD_STATE_STOPPED) {
2281 			mutex_exit(&fdc->c_lolock);
2282 			if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON))
2283 			    != DDI_SUCCESS) {
2284 				FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power \
2285 				    change failed. \n"));
2286 				(void) pm_idle_component(fdc->c_dip, 0);
2287 				return (EIO);
2288 			}
2289 
2290 			mutex_enter(&fdc->c_lolock);
2291 		}
2292 		if (un->un_flags & FDUNIT_CHANGED)
2293 			cpy.temp |= FDGC_HISTORY;
2294 		else
2295 			cpy.temp &= ~FDGC_HISTORY;
2296 		un->un_flags &= ~FDUNIT_CHANGED;
2297 
2298 		if (fd_pollable) {
2299 			/*
2300 			 * If it's a "pollable" floppy, then we don't
2301 			 * have to do all the fdcheckdisk nastyness to
2302 			 * figure out if the thing is still there.
2303 			 */
2304 			if (fdsense_chng(fdc, unit)) {
2305 				cpy.temp |= FDGC_CURRENT;
2306 			} else {
2307 				cpy.temp &= ~FDGC_CURRENT;
2308 			}
2309 		} else {
2310 
2311 			if (fdsense_chng(fdc, unit)) {
2312 				/*
2313 				 * check disk change signal is asserted.
2314 				 * Now find out if the floppy is
2315 				 * inserted
2316 				 */
2317 				if (fdcheckdisk(fdc, unit)) {
2318 					cpy.temp |= FDGC_CURRENT;
2319 				} else {
2320 					/*
2321 					 * Yes, the floppy was
2322 					 * reinserted. Implies
2323 					 * floppy change.
2324 					 */
2325 					cpy.temp &= ~FDGC_CURRENT;
2326 					cpy.temp |= FDGC_HISTORY;
2327 				}
2328 			} else {
2329 				cpy.temp &= ~FDGC_CURRENT;
2330 			}
2331 		}
2332 
2333 		/*
2334 		 * For a pollable floppy, the floppy_change signal
2335 		 * reflects whether the floppy is in there or not.
2336 		 * We can not detect a floppy change if we don't poll
2337 		 * this signal when the floppy is being changed.
2338 		 * Because as soon as the floppy is put back, the
2339 		 * signal is reset.
2340 		 * BUT the pollable floppies are available only on
2341 		 * Sparcstation Voyager Voyagers (Gypsy) only and
2342 		 * those are motorized floppies. For motorized floppies,
2343 		 * the floppy can only (assuming the user doesn't use a
2344 		 * pin to take out the floppy) be taken out by
2345 		 * issuing 'eject' command which sets the
2346 		 * un->un_ejected flag. So, if the following
2347 		 * condition is true, we can assume there
2348 		 * was a floppy change.
2349 		 */
2350 		if (un->un_ejected && !(cpy.temp & FDGC_CURRENT)) {
2351 			cpy.temp |= FDGC_HISTORY;
2352 		}
2353 		un->un_ejected = 0;
2354 
2355 
2356 		/* return the write-protection status */
2357 		fdgetcsb(fdc);
2358 		if (fdsensedrv(fdc, unit) & WP_SR3) {
2359 			cpy.temp |= FDGC_CURWPROT;
2360 		}
2361 		fdretcsb(fdc);
2362 		mutex_exit(&fdc->c_lolock);
2363 
2364 		if (ddi_copyout((caddr_t)&cpy.temp, (caddr_t)arg,
2365 		    sizeof (int), flag))
2366 			err = EFAULT;
2367 		(void) pm_idle_component(fdc->c_dip, 0);
2368 		break;
2369 
2370 	case FDGETDRIVECHAR:
2371 
2372 		if (ddi_copyin((caddr_t)arg, (caddr_t)&cpy.drvchar,
2373 				sizeof (struct fd_drive), flag)) {
2374 			err = EFAULT;
2375 			break;
2376 		}
2377 
2378 		/*
2379 		 * Return the ejectable value based on the FD_MANUAL_EJECT
2380 		 * property
2381 		 */
2382 		cpy.drvchar.fdd_ejectable = fdc->c_un->un_drive->fdd_ejectable;
2383 		cpy.drvchar.fdd_maxsearch = nfdtypes; /* 3 - hi m lo density */
2384 		if (fd_pollable)	/* pollable device */
2385 			cpy.drvchar.fdd_flags |= FDD_POLLABLE;
2386 
2387 		/* the rest of the fd_drive struct is meaningless to us */
2388 
2389 		if (ddi_copyout((caddr_t)&cpy.drvchar, (caddr_t)arg,
2390 		    sizeof (struct fd_drive), flag))
2391 			err = EFAULT;
2392 		break;
2393 
2394 	case FDSETDRIVECHAR:
2395 		FDERRPRINT(FDEP_L3, FDEM_IOCT,
2396 		    (C, "fd_ioctl: FDSETDRIVECHAR not supportedn\n"));
2397 		err = ENOTTY;
2398 		break;
2399 
2400 	case DKIOCREMOVABLE: {
2401 		int	i = 1;
2402 
2403 		/* no brainer: floppies are always removable */
2404 		if (ddi_copyout((caddr_t)&i, (caddr_t)arg, sizeof (int),
2405 		    flag)) {
2406 			err = EFAULT;
2407 		}
2408 		break;
2409 	}
2410 	case DKIOCGMEDIAINFO:
2411 		err = fd_get_media_info(un, (caddr_t)arg, flag);
2412 		break;
2413 
2414 
2415 	case FDIOCMD:
2416 	{
2417 		struct fd_cmd fc;
2418 		int cyl, hd, spc, spt;
2419 		int nblks; /* total no. of blocks */
2420 
2421 #ifdef _MULTI_DATAMODEL
2422 		switch (ddi_model_convert_from(flag & FMODELS)) {
2423 		case DDI_MODEL_ILP32: {
2424 			struct fd_cmd32 fc32;
2425 
2426 			if (ddi_copyin((const void *)arg, &fc32,
2427 			    sizeof (fc32), flag)) {
2428 				return (EFAULT);
2429 			}
2430 			fc.fdc_cmd	= fc32.fdc_cmd;
2431 			fc.fdc_flags	= fc32.fdc_flags;
2432 			fc.fdc_blkno	= (daddr_t)fc32.fdc_blkno;
2433 			fc.fdc_secnt	= fc32.fdc_secnt;
2434 			fc.fdc_bufaddr	= (caddr_t)(uintptr_t)fc32.fdc_bufaddr;
2435 			fc.fdc_buflen	= fc32.fdc_buflen;
2436 			fc.fdc_cmd	= fc32.fdc_cmd;
2437 
2438 			break;
2439 		}
2440 
2441 		case DDI_MODEL_NONE:
2442 			if (ddi_copyin((const void *)arg, &fc,
2443 			    sizeof (fc), flag)) {
2444 				return (EFAULT);
2445 			}
2446 			break;
2447 		}
2448 #else /* ! _MULTI_DATAMODEL */
2449 		if (ddi_copyin((const void *)arg, &fc, sizeof (fc), flag)) {
2450 			return (EFAULT);
2451 		}
2452 #endif /* _MULTI_DATAMODEL */
2453 
2454 		if (fc.fdc_cmd == FDCMD_READ || fc.fdc_cmd == FDCMD_WRITE) {
2455 			auto struct iovec aiov;
2456 			auto struct uio auio;
2457 			struct uio *uio = &auio;
2458 
2459 			spc = (fc.fdc_cmd == FDCMD_READ)? B_READ: B_WRITE;
2460 
2461 			bzero(&auio, sizeof (struct uio));
2462 			bzero(&aiov, sizeof (struct iovec));
2463 			aiov.iov_base = fc.fdc_bufaddr;
2464 			aiov.iov_len = (uint_t)fc.fdc_secnt * sec_size;
2465 			uio->uio_iov = &aiov;
2466 
2467 			uio->uio_iovcnt = 1;
2468 			uio->uio_resid = aiov.iov_len;
2469 			uio->uio_segflg = UIO_USERSPACE;
2470 			FDERRPRINT(FDEP_L2, FDEM_IOCT,
2471 			    (C, "fd_ioctl: call physio\n"));
2472 			err = physio(fd_strategy, NULL, dev,
2473 			    spc, minphys, uio);
2474 			break;
2475 		} else if (fc.fdc_cmd != FDCMD_FORMAT_TRACK) {
2476 
2477 			/*
2478 			 * The manpage states that only the FDCMD_WRITE,
2479 			 * FDCMD_READ, and the FDCMD_FORMAT_TR are available.
2480 			 */
2481 			FDERRPRINT(FDEP_L1, FDEM_IOCT,
2482 			    (C, "fd_ioctl: FDIOCMD invalid command\n"));
2483 			err = EINVAL;
2484 			break;
2485 		}
2486 
2487 		/* The command is FDCMD_FORMAT_TRACK */
2488 
2489 		spt = un->un_chars->fdc_secptrack;	/* sec/trk */
2490 		spc = un->un_chars->fdc_nhead * spt;	/* sec/cyl */
2491 		cyl = fc.fdc_blkno / spc;
2492 		hd = (fc.fdc_blkno % spc) / spt;
2493 
2494 		/*
2495 		 * Make sure the specified block number is in the correct
2496 		 * range. (block numbers start at 0)
2497 		 */
2498 		nblks = spc * un->un_chars->fdc_ncyl;
2499 
2500 		if (fc.fdc_blkno < 0 || fc.fdc_blkno > (nblks - 1)) {
2501 			err = EINVAL;
2502 			break;
2503 		}
2504 
2505 		(void) pm_busy_component(fdc->c_dip, 0);
2506 
2507 		mutex_enter(&fdc->c_lolock);
2508 		CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc);
2509 		if (fdc->c_un->un_state == FD_STATE_STOPPED) {
2510 			mutex_exit(&fdc->c_lolock);
2511 			if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON))
2512 			    != DDI_SUCCESS) {
2513 				FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power \
2514 				    change failed. \n"));
2515 				(void) pm_idle_component(fdc->c_dip, 0);
2516 				return (EIO);
2517 			}
2518 
2519 			mutex_enter(&fdc->c_lolock);
2520 		}
2521 
2522 		if (fdformat(fdc, unit, cyl, hd))
2523 			err = EIO;
2524 
2525 		mutex_exit(&fdc->c_lolock);
2526 		(void) pm_idle_component(fdc->c_dip, 0);
2527 
2528 		break;
2529 	}
2530 
2531 	case FDRAW:
2532 
2533 		(void) pm_busy_component(fdc->c_dip, 0);
2534 		err = fdrawioctl(fdc, unit, arg, flag);
2535 
2536 		(void) pm_idle_component(fdc->c_dip, 0);
2537 
2538 		break;
2539 #ifdef FD_DEBUG
2540 	case IOCTL_DEBUG:
2541 		fderrlevel--;
2542 		if (fderrlevel < 0)
2543 			fderrlevel = 3;
2544 		cmn_err(C, "fdioctl: CHANGING debug to %d", fderrlevel);
2545 		return (0);
2546 #endif /* FD_DEBUG */
2547 	default:
2548 		FDERRPRINT(FDEP_L2, FDEM_IOCT,
2549 		    (C, "fd_ioctl: invalid ioctl 0x%x\n", cmd));
2550 		err = ENOTTY;
2551 		break;
2552 	}
2553 
2554 	return (err);
2555 }
2556 
2557 /*
2558  * fdrawioctl
2559  *
2560  * 	- acquires the low level lock
2561  */
2562 
2563 static int
2564 fdrawioctl(struct fdctlr *fdc, int unit, intptr_t arg, int mode)
2565 {
2566 	struct fd_raw fdr;
2567 #ifdef _MULTI_DATAMODEL
2568 	struct fd_raw32 fdr32;
2569 #endif
2570 	struct fdcsb *csb;
2571 	int i, err, flag;
2572 	caddr_t fa;
2573 	uint_t	fc;
2574 	size_t	real_length;
2575 	int	res;
2576 	ddi_device_acc_attr_t attr;
2577 	ddi_acc_handle_t	mem_handle;
2578 
2579 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
2580 	attr.devacc_attr_endian_flags  = DDI_STRUCTURE_BE_ACC;
2581 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
2582 
2583 	ASSERT(fdc->c_un->un_unit_no == unit);
2584 
2585 	FDERRPRINT(FDEP_L1, FDEM_RAWI,
2586 	    (C, "fdrawioctl: cmd[0]=0x%x\n", fdr.fdr_cmd[0]));
2587 
2588 	flag = B_READ;
2589 	err = 0;
2590 	fa = NULL;
2591 	fc = (uint_t)0;
2592 
2593 	/* Copy in the arguments */
2594 	switch (ddi_model_convert_from(mode)) {
2595 #ifdef _MULTI_DATAMODEL
2596 	case DDI_MODEL_ILP32:
2597 		if (ddi_copyin((caddr_t)arg, (caddr_t)&fdr32,
2598 		    sizeof (fdr32), mode)) {
2599 			FDERRPRINT(FDEP_L1, FDEM_RAWI,
2600 			    (C, "fdrawioctl: copyin error, args32\n"));
2601 			return (EFAULT);
2602 		}
2603 		bcopy(fdr32.fdr_cmd, fdr.fdr_cmd, sizeof (fdr.fdr_cmd));
2604 		fdr.fdr_cnum = fdr32.fdr_cnum;
2605 		bcopy(fdr32.fdr_result, fdr.fdr_result,
2606 		    sizeof (fdr.fdr_result));
2607 		fdr.fdr_nbytes = fdr32.fdr_nbytes;
2608 		fdr.fdr_addr = (caddr_t)(uintptr_t)fdr32.fdr_addr;
2609 		break;
2610 #endif
2611 	default:
2612 	case DDI_MODEL_NONE:
2613 		if (ddi_copyin((caddr_t)arg, (caddr_t)&fdr,
2614 		    sizeof (fdr), mode)) {
2615 			FDERRPRINT(FDEP_L1, FDEM_RAWI,
2616 			    (C, "fdrawioctl: copyin error, args\n"));
2617 			return (EFAULT);
2618 		}
2619 		break;
2620 	}
2621 
2622 	mutex_enter(&fdc->c_lolock);
2623 
2624 	CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc);
2625 
2626 	if (fdc->c_un->un_state == FD_STATE_STOPPED) {
2627 		mutex_exit(&fdc->c_lolock);
2628 		if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON))
2629 		    != DDI_SUCCESS) {
2630 			FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power change \
2631 			    failed. \n"));
2632 
2633 			(void) pm_idle_component(fdc->c_dip, 0);
2634 			return (EIO);
2635 		}
2636 		mutex_enter(&fdc->c_lolock);
2637 	}
2638 
2639 	fdgetcsb(fdc);
2640 	csb = &fdc->c_csb;
2641 	csb->csb_unit = (uchar_t)unit;
2642 
2643 	/* copy cmd bytes into csb */
2644 	for (i = 0; i <= fdr.fdr_cnum; i++)
2645 		csb->csb_cmds[i] = fdr.fdr_cmd[i];
2646 	csb->csb_ncmds = (uchar_t)fdr.fdr_cnum;
2647 
2648 	csb->csb_maxretry = 0;	/* let the application deal with errors */
2649 	csb->csb_retrys = 0;
2650 
2651 	switch (fdr.fdr_cmd[0] & 0x0f) {
2652 
2653 	case FDRAW_SPECIFY:
2654 		/*
2655 		 * Ensure that the right DMA mode is selected.  There is
2656 		 * currently no way for the user to tell if DMA is
2657 		 * happening so set the value for the user.
2658 		 */
2659 
2660 		if (fdc->c_fdtype & FDCTYPE_DMA)
2661 			csb->csb_cmds[2] = csb->csb_cmds[2] & 0xFE;
2662 		else
2663 			csb->csb_cmds[2] = csb->csb_cmds[2] | 0x1;
2664 
2665 		csb->csb_opflags = CSB_OFNORESULTS;
2666 		csb->csb_nrslts = 0;
2667 		break;
2668 
2669 	case FDRAW_SENSE_DRV:
2670 		/* Insert the appropriate drive number */
2671 		csb->csb_cmds[1] = csb->csb_cmds[1] | (unit & DRV_MASK);
2672 		csb->csb_opflags = CSB_OFIMMEDIATE;
2673 		csb->csb_nrslts = 1;
2674 		break;
2675 
2676 	case FDRAW_REZERO:
2677 	case FDRAW_SEEK:
2678 		/* Insert the appropriate drive number */
2679 		csb->csb_cmds[1] = csb->csb_cmds[1] | (unit & DRV_MASK);
2680 		csb->csb_opflags = CSB_OFSEEKOPS + CSB_OFTIMEIT;
2681 		csb->csb_nrslts = 2;
2682 		break;
2683 
2684 	case FDRAW_FORMAT:
2685 		FDERRPRINT(FDEP_L1, FDEM_RAWI,
2686 		    (C, "fdrawioctl: cmd is fdfraw format\n"));
2687 
2688 		/* Insert the appropriate drive number */
2689 		csb->csb_cmds[1] = csb->csb_cmds[1] | (unit & DRV_MASK);
2690 		csb->csb_opflags = CSB_OFXFEROPS + CSB_OFTIMEIT;
2691 		csb->csb_nrslts = NRBRW;
2692 		flag = B_WRITE;
2693 
2694 		/*
2695 		 * Allocate memory for the command.
2696 		 * If PIO is being used, then add an extra 16 bytes
2697 		 */
2698 		if (fdc->c_fdtype & FDCTYPE_DMA) {
2699 
2700 			fc = (uint_t)(fdr.fdr_nbytes);
2701 			mutex_enter(&fdc->c_hilock);
2702 
2703 			res = ddi_dma_mem_alloc(fdc->c_dmahandle, fc,
2704 			    &attr, DDI_DMA_STREAMING,
2705 			    DDI_DMA_DONTWAIT, 0, &fa, &real_length,
2706 			    &mem_handle);
2707 
2708 			if (res != DDI_SUCCESS) {
2709 				fdretcsb(fdc);
2710 				mutex_exit(&fdc->c_lolock);
2711 				mutex_exit(&fdc->c_hilock);
2712 				return (EIO);
2713 			}
2714 
2715 			fdc->c_csb.csb_read = CSB_WRITE;
2716 			if (fdstart_dma(fdc, fa, fc) != 0) {
2717 				ddi_dma_mem_free(&mem_handle);
2718 				fdretcsb(fdc);
2719 				mutex_exit(&fdc->c_lolock);
2720 				mutex_exit(&fdc->c_hilock);
2721 				return (EIO);
2722 			}
2723 			mutex_exit(&fdc->c_hilock);
2724 
2725 		} else {
2726 			fc = (uint_t)(fdr.fdr_nbytes + 16);
2727 			fa = kmem_zalloc(fc, KM_SLEEP);
2728 		}
2729 
2730 		/* copy in the user's command bytes */
2731 		if (ddi_copyin(fdr.fdr_addr, fa,
2732 		    (uint_t)fdr.fdr_nbytes, mode)) {
2733 			fdretcsb(fdc);
2734 			mutex_exit(&fdc->c_lolock);
2735 
2736 			if (fdc->c_fdtype & FDCTYPE_DMA) {
2737 				ddi_dma_mem_free(&mem_handle);
2738 				FDERRPRINT(FDEP_L1, FDEM_RAWI,
2739 				    (C, "fdrawioctl: (err)free dma memory\n"));
2740 			} else {
2741 				kmem_free(fa, fc);
2742 			}
2743 
2744 			FDERRPRINT(FDEP_L1, FDEM_RAWI,
2745 			    (C, "fdrawioctl: ddi_copyin error\n"));
2746 			return (EFAULT);
2747 		}
2748 
2749 		break;
2750 	case FDRAW_WRCMD:
2751 	case FDRAW_WRITEDEL:
2752 		flag = B_WRITE;
2753 		/* FALLTHROUGH */
2754 	case FDRAW_RDCMD:
2755 	case FDRAW_READDEL:
2756 	case FDRAW_READTRACK:
2757 		/* Insert the appropriate drive number */
2758 		csb->csb_cmds[1] = csb->csb_cmds[1] | (unit & DRV_MASK);
2759 		if (fdc->c_fdtype & FDCTYPE_SB)
2760 			csb->csb_cmds[1] |= IPS;
2761 		csb->csb_opflags = CSB_OFXFEROPS + CSB_OFTIMEIT;
2762 		csb->csb_nrslts = NRBRW;
2763 		break;
2764 
2765 	default:
2766 		fdretcsb(fdc);
2767 		mutex_exit(&fdc->c_lolock);
2768 		return (EINVAL);
2769 	}
2770 
2771 	if ((csb->csb_opflags & CSB_OFXFEROPS) && (fdr.fdr_nbytes == 0)) {
2772 		fdretcsb(fdc);
2773 		mutex_exit(&fdc->c_lolock);
2774 		return (EINVAL);
2775 	}
2776 	csb->csb_opflags |= CSB_OFRAWIOCTL;
2777 
2778 	FDERRPRINT(FDEP_L1, FDEM_RAWI,
2779 	    (C, "fdrawioctl: nbytes = %u\n", fdr.fdr_nbytes));
2780 
2781 	if ((fdr.fdr_cmd[0] & 0x0f) != FDRAW_FORMAT) {
2782 		if ((fc = (uint_t)fdr.fdr_nbytes) > 0) {
2783 			/*
2784 			 * In SunOS 4.X, we used to as_fault things in.
2785 			 * We really cannot do this in 5.0/SVr4. Unless
2786 			 * someone really believes that speed is of the
2787 			 * essence here, it is just much simpler to do
2788 			 * this in kernel space and use copyin/copyout.
2789 			 */
2790 			if (fdc->c_fdtype & FDCTYPE_DMA) {
2791 				mutex_enter(&fdc->c_hilock);
2792 				res = ddi_dma_mem_alloc(fdc->c_dmahandle, fc,
2793 				    &attr, DDI_DMA_STREAMING,
2794 				    DDI_DMA_DONTWAIT, 0, &fa, &real_length,
2795 				    &mem_handle);
2796 
2797 				if (res != DDI_SUCCESS) {
2798 					fdretcsb(fdc);
2799 					mutex_exit(&fdc->c_lolock);
2800 					mutex_exit(&fdc->c_hilock);
2801 					return (EIO);
2802 				}
2803 
2804 				if (flag == B_WRITE)
2805 					fdc->c_csb.csb_read = CSB_WRITE;
2806 				else
2807 					fdc->c_csb.csb_read = CSB_READ;
2808 
2809 				if (fdstart_dma(fdc, fa, fc) != 0) {
2810 					ddi_dma_mem_free(&mem_handle);
2811 					fdretcsb(fdc);
2812 					mutex_exit(&fdc->c_lolock);
2813 					mutex_exit(&fdc->c_hilock);
2814 					return (EIO);
2815 				}
2816 				mutex_exit(&fdc->c_hilock);
2817 
2818 			} else {
2819 				fa = kmem_zalloc(fc, KM_SLEEP);
2820 			}
2821 
2822 			if (flag == B_WRITE) {
2823 				if (ddi_copyin(fdr.fdr_addr, fa, fc, mode)) {
2824 					if (fdc->c_fdtype & FDCTYPE_DMA)
2825 						ddi_dma_mem_free(&mem_handle);
2826 					else
2827 						kmem_free(fa, fc);
2828 					fdretcsb(fdc);
2829 					mutex_exit(&fdc->c_lolock);
2830 					FDERRPRINT(FDEP_L1, FDEM_RAWI, (C,
2831 					    "fdrawioctl: can't copy data\n"));
2832 
2833 					return (EFAULT);
2834 				}
2835 			}
2836 			csb->csb_addr = fa;
2837 			csb->csb_len = fc;
2838 		} else {
2839 			csb->csb_addr = 0;
2840 			csb->csb_len = 0;
2841 		}
2842 	} else {
2843 		csb->csb_addr = fa;
2844 		csb->csb_len = fc;
2845 	}
2846 
2847 	FDERRPRINT(FDEP_L1, FDEM_RAWI,
2848 	    (C, "cmd: %x %x %x %x %x %x %x %x %x %x\n", csb->csb_cmds[0],
2849 	    csb->csb_cmds[1], csb->csb_cmds[2], csb->csb_cmds[3],
2850 	    csb->csb_cmds[4], csb->csb_cmds[5], csb->csb_cmds[6],
2851 	    csb->csb_cmds[7], csb->csb_cmds[8], csb->csb_cmds[9]));
2852 	FDERRPRINT(FDEP_L1, FDEM_RAWI,
2853 	    (C, "nbytes: %x, opflags: %x, addr: %p, len: %x\n",
2854 	    csb->csb_ncmds, csb->csb_opflags, (void *)csb->csb_addr,
2855 	    csb->csb_len));
2856 
2857 
2858 	/*
2859 	 * Note that we ignore any error return s from fdexec.
2860 	 * This is the way the driver has been, and it may be
2861 	 * that the raw ioctl senders simply don't want to
2862 	 * see any errors returned in this fashion.
2863 	 */
2864 
2865 	if ((csb->csb_opflags & CSB_OFNORESULTS) ||
2866 	    (csb->csb_opflags & CSB_OFIMMEDIATE)) {
2867 		(void) fdexec(fdc, 0); /* don't sleep, don't check change */
2868 	} else {
2869 		(void) fdexec(fdc, FDXC_SLEEP | FDXC_CHECKCHG);
2870 	}
2871 
2872 
2873 	FDERRPRINT(FDEP_L1, FDEM_RAWI,
2874 	    (C, "rslt: %x %x %x %x %x %x %x %x %x %x\n", csb->csb_rslt[0],
2875 	    csb->csb_rslt[1], csb->csb_rslt[2], csb->csb_rslt[3],
2876 	    csb->csb_rslt[4], csb->csb_rslt[5], csb->csb_rslt[6],
2877 	    csb->csb_rslt[7], csb->csb_rslt[8], csb->csb_rslt[9]));
2878 
2879 	if ((fdr.fdr_cmd[0] & 0x0f) != FDRAW_FORMAT && fc &&
2880 	    flag == B_READ && err == 0) {
2881 		if (ddi_copyout(fa, fdr.fdr_addr, fc, mode)) {
2882 			FDERRPRINT(FDEP_L1, FDEM_RAWI,
2883 			    (C, "fdrawioctl: can't copy read data\n"));
2884 
2885 			err = EFAULT;
2886 		}
2887 	}
2888 
2889 
2890 	if (fc) {
2891 		if (fdc->c_fdtype & FDCTYPE_DMA) {
2892 			ddi_dma_mem_free(&mem_handle);
2893 			FDERRPRINT(FDEP_L1, FDEM_RAWI,
2894 			    (C, "fdrawioctl: free dma memory\n"));
2895 		} else {
2896 			kmem_free(fa, fc);
2897 		}
2898 	}
2899 
2900 
2901 	/* copy cmd results into fdr */
2902 	for (i = 0; (int)i <= (int)csb->csb_nrslts; i++)
2903 		fdr.fdr_result[i] = csb->csb_rslt[i];
2904 	fdr.fdr_nbytes = fdc->c_csb.csb_rlen; /* return resid */
2905 
2906 	switch (ddi_model_convert_from(mode)) {
2907 #ifdef _MULTI_DATAMODEL
2908 	case DDI_MODEL_ILP32:
2909 		bcopy(fdr.fdr_cmd, fdr32.fdr_cmd, sizeof (fdr32.fdr_cmd));
2910 		fdr32.fdr_cnum = fdr.fdr_cnum;
2911 		bcopy(fdr.fdr_result, fdr32.fdr_result,
2912 		    sizeof (fdr32.fdr_result));
2913 		fdr32.fdr_nbytes = fdr.fdr_nbytes;
2914 		fdr32.fdr_addr = (caddr32_t)(uintptr_t)fdr.fdr_addr;
2915 		if (ddi_copyout(&fdr32, (caddr_t)arg, sizeof (fdr32), mode)) {
2916 			FDERRPRINT(FDEP_L1, FDEM_RAWI,
2917 			    (C, "fdrawioctl: can't copy results32\n"));
2918 			err = EFAULT;
2919 		}
2920 		break;
2921 #endif
2922 	case DDI_MODEL_NONE:
2923 	default:
2924 		if (ddi_copyout(&fdr, (caddr_t)arg, sizeof (fdr), mode)) {
2925 			FDERRPRINT(FDEP_L1, FDEM_RAWI,
2926 			    (C, "fdrawioctl: can't copy results\n"));
2927 			err = EFAULT;
2928 		}
2929 		break;
2930 	}
2931 
2932 	fdretcsb(fdc);
2933 	mutex_exit(&fdc->c_lolock);
2934 	return (0);
2935 }
2936 
2937 /*
2938  * fdformat
2939  *	format a track
2940  * For PIO, builds a table of sector data values with 16 bytes
2941  * (sizeof fdc's fifo) of dummy on end.	 This is so than when fdc->c_len
2942  * goes to 0 and fd_intr sends a TC that all the real formatting will
2943  * have already been done.
2944  *
2945  *	- called with the low level lock held
2946  */
2947 static int
2948 fdformat(struct fdctlr *fdc, int unit, int cyl, int hd)
2949 {
2950 	struct fdcsb *csb;
2951 	struct fdunit *un;
2952 	struct fd_char *ch;
2953 	int	cmdresult;
2954 	uchar_t	*fmthdrs;
2955 	caddr_t fd;
2956 	int	i;
2957 	size_t	real_length;
2958 	ddi_device_acc_attr_t attr;
2959 	ddi_acc_handle_t mem_handle;
2960 
2961 	FDERRPRINT(FDEP_L1, FDEM_FORM,
2962 	    (C, "fdformat cyl %d, hd %d\n", cyl, hd));
2963 	fdgetcsb(fdc);
2964 
2965 	ASSERT(fdc->c_un->un_unit_no == unit);
2966 
2967 	csb = &fdc->c_csb;
2968 	un = fdc->c_un;
2969 	ch = un->un_chars;
2970 
2971 	/* setup common things in csb */
2972 	csb->csb_unit = (uchar_t)unit;
2973 
2974 	/*
2975 	 * The controller needs to do a seek before
2976 	 * each format to get to right cylinder.
2977 	 */
2978 	if (fdrecalseek(fdc, unit, cyl, FDXC_CHECKCHG)) {
2979 		fdretcsb(fdc);
2980 		return (EIO);
2981 	}
2982 
2983 	/*
2984 	 * now do the format itself
2985 	 */
2986 	csb->csb_nrslts = NRBRW;
2987 	csb->csb_opflags = CSB_OFXFEROPS | CSB_OFTIMEIT;
2988 
2989 	csb->csb_cmds[0] = FDRAW_FORMAT;
2990 	/* always or in MFM bit */
2991 	csb->csb_cmds[0] |= MFM;
2992 	csb->csb_cmds[1] = (hd << 2) | (unit & 0x03);
2993 	csb->csb_cmds[2] = ch->fdc_medium ? 3 : 2;
2994 	csb->csb_cmds[3] = ch->fdc_secptrack;
2995 	csb->csb_cmds[4] = GPLF;
2996 	csb->csb_cmds[5] = FDATA;
2997 	csb->csb_ncmds = 6;
2998 	csb->csb_maxretry = rwretry;
2999 	csb->csb_retrys = 0;
3000 
3001 	/*
3002 	 * NOTE: have to add size of fifo also - for dummy format action
3003 	 * if PIO is being used.
3004 	 */
3005 
3006 
3007 	if (fdc->c_fdtype & FDCTYPE_DMA) {
3008 
3009 		csb->csb_len = (uint_t)4 * ch->fdc_secptrack;
3010 
3011 		attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3012 		attr.devacc_attr_endian_flags  = DDI_STRUCTURE_BE_ACC;
3013 		attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3014 
3015 		mutex_enter(&fdc->c_hilock);
3016 
3017 		cmdresult = ddi_dma_mem_alloc(fdc->c_dmahandle, csb->csb_len,
3018 		    &attr, DDI_DMA_STREAMING,
3019 		    DDI_DMA_DONTWAIT, 0, &fd, &real_length,
3020 		    &mem_handle);
3021 
3022 		if (cmdresult != DDI_SUCCESS) {
3023 			mutex_exit(&fdc->c_hilock);
3024 			return (cmdresult);
3025 		}
3026 
3027 		fdc->c_csb.csb_read = CSB_WRITE;
3028 		if (fdstart_dma(fdc, fd,  csb->csb_len) != 0) {
3029 			ddi_dma_mem_free(&mem_handle);
3030 			mutex_exit(&fdc->c_hilock);
3031 			return (-1);
3032 		}
3033 		mutex_exit(&fdc->c_hilock);
3034 
3035 
3036 	} else {
3037 		csb->csb_len = (uint_t)4 * ch->fdc_secptrack + 16;
3038 		fd = kmem_zalloc(csb->csb_len, KM_SLEEP);
3039 		fmthdrs = (uchar_t *)fd;
3040 	}
3041 
3042 	csb->csb_addr = (caddr_t)fd;
3043 
3044 	for (i = 1; i <= ch->fdc_secptrack; i++) {
3045 		*fd++ = (uchar_t)cyl;		/* cylinder */
3046 		*fd++ = (uchar_t)hd;		/* head */
3047 		*fd++ = (uchar_t)i;	/* sector number */
3048 		*fd++ = ch->fdc_medium ? 3 : 2; /* sec_size code */
3049 	}
3050 
3051 	if ((cmdresult = fdexec(fdc, FDXC_SLEEP | FDXC_CHECKCHG)) == 0) {
3052 		if (csb->csb_cmdstat)
3053 			cmdresult = EIO;	/* XXX TBD NYD for now */
3054 	}
3055 
3056 	if (fdc->c_fdtype & FDCTYPE_DMA) {
3057 		ddi_dma_mem_free(&mem_handle);
3058 	} else {
3059 		kmem_free((caddr_t)fmthdrs, csb->csb_len);
3060 	}
3061 
3062 	fdretcsb(fdc);
3063 
3064 	return (cmdresult);
3065 }
3066 
3067 /*
3068  * fdstart
3069  *	called from fd_strategy() or from fdXXXX() to setup and
3070  *	start operations of read or write only (using buf structs).
3071  *	Because the chip doesn't handle crossing cylinder boundaries on
3072  *	the fly, this takes care of those boundary conditions.	Note that
3073  *	it sleeps until the operation is done *within fdstart* - so that
3074  *	when fdstart returns, the operation is already done.
3075  *
3076  *	- called with the low level lock held
3077  *
3078  */
3079 
3080 static int slavio_index_pulse_work_around = 0;
3081 
3082 static void
3083 fdstart(struct fdctlr *fdc)
3084 {
3085 	struct buf *bp;
3086 	struct fdcsb *csb;
3087 	struct fdunit *un;
3088 	struct fd_char *ch;
3089 	struct dk_map32 *dkm;
3090 	uint_t	part;		/* partition number for the transfer */
3091 	uint_t	start_part;	/* starting block of the partition */
3092 	uint_t	last_part;	/* last block of the partition */
3093 	uint_t	blk;		/* starting block of transfer on diskette */
3094 	uint_t	sect;		/* starting block's offset into track */
3095 	uint_t	cyl;		/* starting cylinder of the transfer */
3096 	uint_t	bincyl;		/* starting blocks's offset into cylinder */
3097 	uint_t	secpcyl;	/* number of sectors per cylinder */
3098 	uint_t	phys_blkno;	/* no. of blocks on the diskette */
3099 	uint_t	head;		/* one of two diskette heads */
3100 	uint_t	unit;
3101 	uint_t	len, tlen;
3102 	caddr_t addr;
3103 	caddr_t temp_addr;
3104 	uint_t	partial_read = 0;
3105 	int sb_temp_buf_used = 0;
3106 
3107 	bp = fdc->c_actf;
3108 
3109 	while (bp != NULL) {
3110 
3111 		fdc->c_actf = bp->av_forw;
3112 		fdc->c_current = bp;
3113 
3114 		/*
3115 		 * Initialize the buf structure.  The residual count is
3116 		 * initially the number of bytes to be read or written
3117 		 */
3118 		bp->b_flags &= ~B_ERROR;
3119 		bp->b_error = 0;
3120 		bp->b_resid = bp->b_bcount;
3121 		bp_mapin(bp);			/* map in buffers */
3122 
3123 		addr = bp->b_un.b_addr;		/* assign buffer address */
3124 
3125 		/*
3126 		 * Find the unit and partition numbers.
3127 		 */
3128 		unit = fdc->c_un->un_unit_no;
3129 		un = fdc->c_un;
3130 		ch = un->un_chars;
3131 		part = FDPARTITION(bp->b_edev);
3132 		dkm = &un->un_label.dkl_map[part];
3133 
3134 		if (un->un_chars->fdc_medium) {
3135 			phys_blkno = bp->b_blkno >> 1;
3136 		} else {
3137 			phys_blkno = bp->b_blkno;
3138 		}
3139 
3140 		if (un->un_iostat) {
3141 			kstat_waitq_to_runq(KIOSP);
3142 		}
3143 
3144 		FDERRPRINT(FDEP_L1, FDEM_STRT,
3145 		    (C, "fdstart: bp=0x%p blkno=0x%x bcount=0x%x\n",
3146 		    (void *)bp, (int)bp->b_blkno, (int)bp->b_bcount));
3147 
3148 		/*
3149 		 * Get the csb and initialize the values that are the same
3150 		 * for DMA and PIO.
3151 		 */
3152 		fdgetcsb(fdc);		/* get csb (maybe wait for it) */
3153 		csb = &fdc->c_csb;
3154 		csb->csb_unit = unit;		/* floppy unit number */
3155 
3156 
3157 		/*
3158 		 * bugID:4133425 : If the controller is SLAVIO, and
3159 		 * the read does not reach end of track, then modify
3160 		 * the tlen to read until the end of track to a temp
3161 		 * buffer and disable MT. After the read is over,
3162 		 * copy the useful portion of the data to 'addr'.
3163 		 * Enable this feature only when
3164 		 * slavio_index_pulse_work_aound variable is
3165 		 * set in /etc/system.
3166 		 */
3167 
3168 
3169 		if (bp->b_flags & B_READ) {
3170 			if (((fdc->c_fdtype & FDCTYPE_SLAVIO) &&
3171 			    slavio_index_pulse_work_around) ||
3172 			    (fdc->c_fdtype & FDCTYPE_TCBUG))
3173 				csb->csb_cmds[0] = SK | FDRAW_RDCMD | MFM;
3174 			else
3175 				csb->csb_cmds[0] = MT | SK | FDRAW_RDCMD | MFM;
3176 		} else {
3177 			if (fdc->c_fdtype & FDCTYPE_TCBUG)
3178 				csb->csb_cmds[0] = FDRAW_WRCMD | MFM;
3179 			else
3180 				csb->csb_cmds[0] = MT | FDRAW_WRCMD | MFM;
3181 		}
3182 
3183 
3184 		if (bp->b_flags & B_READ)
3185 			fdc->c_csb.csb_read = CSB_READ;
3186 		else
3187 			fdc->c_csb.csb_read = CSB_WRITE;
3188 
3189 
3190 		csb->csb_cmds[5] = ch->fdc_medium ? 3 : 2; /* sector size  */
3191 		csb->csb_cmds[6] = ch->fdc_secptrack; /* EOT-# of sectors/trk */
3192 		csb->csb_cmds[7] = GPLN;	/* GPL - gap 3 size code */
3193 		csb->csb_cmds[8] = SSSDTL;	/* DTL - be 0xFF if N != 0 */
3194 
3195 		csb->csb_ncmds = NCBRW;		/* number of command bytes */
3196 		csb->csb_nrslts = NRBRW;	/* number of result bytes */
3197 
3198 
3199 		/*
3200 		 * opflags for interrupt handler, et.al.
3201 		 */
3202 		csb->csb_opflags = CSB_OFXFEROPS | CSB_OFTIMEIT;
3203 
3204 
3205 		/*
3206 		 * Make sure the transfer does not go off the end
3207 		 * of the partition.  Limit the actual amount transferred
3208 		 * to fit the partition.
3209 		 */
3210 
3211 		blk = phys_blkno;
3212 		start_part = (dkm->dkl_cylno * ch->fdc_secptrack
3213 		    * ch->fdc_nhead);
3214 		blk = blk + start_part;
3215 		last_part = start_part + dkm->dkl_nblk;
3216 
3217 		if ((blk + (bp->b_bcount / ch->fdc_sec_size)) > last_part)
3218 			len = (last_part - blk) * ch->fdc_sec_size;
3219 		else
3220 			len = (uint_t)bp->b_bcount;
3221 
3222 		/*
3223 		 * now we have the real start blk,
3224 		 * addr and len for xfer op
3225 		 * sectors per cylinder
3226 		 */
3227 		secpcyl = ch->fdc_nhead * ch->fdc_secptrack;
3228 
3229 		/*
3230 		 * The controller can transfer up to a cylinder at a time.
3231 		 * Early revs of the 82077 have a bug that causes the chip to
3232 		 * fail to respond to the Terminal Count signal.  Due to this
3233 		 * bug, controllers with type FDCTYPE_TCBUG, only transfer up
3234 		 * to a track at a time.
3235 		 * See earlier comment for bugID:4133425 for index pulse
3236 		 * work around.
3237 		 */
3238 
3239 		while (len != 0) {
3240 
3241 			cyl = blk / secpcyl;	/* cylinder of transfer */
3242 			bincyl = blk % secpcyl;	/* blk within cylinder */
3243 			head = bincyl / ch->fdc_secptrack;
3244 			sect = (bincyl % ch->fdc_secptrack) + 1;
3245 						/* sect w/in track */
3246 
3247 			/*
3248 			 * If the desired block and length will go beyond the
3249 			 * cylinder end, limit it to the cylinder end.
3250 			 */
3251 
3252 			if ((fdc->c_fdtype & FDCTYPE_SLAVIO) &&
3253 			    slavio_index_pulse_work_around &&
3254 			    (fdc->c_csb.csb_read == CSB_READ)) {
3255 
3256 				tlen = (ch->fdc_secptrack - sect + 1) *
3257 				    ch->fdc_sec_size;
3258 				if (len < tlen) {
3259 					partial_read = 1;
3260 					temp_addr = (caddr_t)kmem_alloc(tlen,
3261 					    KM_SLEEP);
3262 				}
3263 
3264 			} else if (fdc->c_fdtype & FDCTYPE_TCBUG) {
3265 				tlen = len;
3266 				if (len > ((ch->fdc_secptrack - sect + 1) *
3267 				    ch->fdc_sec_size))
3268 					tlen = (ch->fdc_secptrack - sect + 1)
3269 					    * ch->fdc_sec_size;
3270 			} else {
3271 				if (len > ((secpcyl - bincyl)
3272 				    * ch->fdc_sec_size))
3273 					tlen = (secpcyl - bincyl)
3274 					    * ch->fdc_sec_size;
3275 
3276 				else
3277 					tlen = len;
3278 			}
3279 			if (fdc->c_fdtype & FDCTYPE_SB) {
3280 				/*
3281 				 * To avoid underrun errors during IFB activity.
3282 				 */
3283 				if (tlen > max_fd_dma_len)
3284 					tlen = max_fd_dma_len;
3285 			}
3286 
3287 			FDERRPRINT(FDEP_L1, FDEM_STRT,
3288 			    (C, "	blk 0x%x, addr 0x%p, len 0x%x\n",
3289 			    blk, (void *)addr, len));
3290 			FDERRPRINT(FDEP_L1, FDEM_STRT,
3291 			    (C, "cyl:%x, head:%x, sec:%x\n",
3292 			    cyl, head, sect));
3293 
3294 			FDERRPRINT(FDEP_L1, FDEM_STRT,
3295 			    (C, "	resid 0x%lx, tlen %d\n",
3296 			    bp->b_resid, tlen));
3297 
3298 			/*
3299 			 * Finish programming the command
3300 			 */
3301 			csb->csb_cmds[1] = (head << 2) | unit;
3302 			if (fdc->c_fdtype & FDCTYPE_SB)
3303 				csb->csb_cmds[1] |= IPS;
3304 
3305 			csb->csb_cmds[2] = cyl;	/* C - cylinder address */
3306 			csb->csb_cmds[3] = head;	/* H - head number */
3307 			csb->csb_cmds[4] = sect;	/* R - sector number */
3308 			if (fdc->c_fdtype & FDCTYPE_TCBUG)
3309 				csb->csb_cmds[6] = sect +
3310 				    (tlen / ch->fdc_sec_size) - 1;
3311 
3312 			csb->csb_len = tlen;
3313 			if (partial_read)
3314 				csb->csb_addr = temp_addr;
3315 			else
3316 				csb->csb_addr = addr;
3317 
3318 			/* retry this many times max */
3319 			csb->csb_maxretry = rwretry;
3320 			csb->csb_retrys = 0;
3321 
3322 			/* If platform supports DMA, set up DMA resources */
3323 			if (fdc->c_fdtype & FDCTYPE_DMA) {
3324 				if ((fdc->c_fdtype & FDCTYPE_SB) &&
3325 				    (((uint32_t)(uintptr_t)addr & 0xFFFF0000) !=
3326 				    (((uint32_t)(uintptr_t)addr + tlen) &
3327 				    0xFFFF0000))) {
3328 					csb->csb_addr = fdc->dma_buf;
3329 					sb_temp_buf_used = 1;
3330 					if (csb->csb_read != CSB_READ) {
3331 						bcopy(addr, fdc->dma_buf, tlen);
3332 				}
3333 			}
3334 				mutex_enter(&fdc->c_hilock);
3335 
3336 				if (fdstart_dma(fdc, csb->csb_addr,
3337 				    tlen) != 0) {
3338 
3339 					bp->b_flags |= B_ERROR;
3340 					bp->b_error = EAGAIN;
3341 
3342 					mutex_exit(&fdc->c_hilock);
3343 					FDERRPRINT(FDEP_L1, FDEM_STRT,
3344 					    (C, "fdstart: no dma resources\n"));
3345 
3346 					break;
3347 				}
3348 				mutex_exit(&fdc->c_hilock);
3349 
3350 			}
3351 
3352 			bp->b_error = fdexec(fdc, FDXC_SLEEP|FDXC_CHECKCHG);
3353 			if (bp->b_error != 0) {
3354 				/*
3355 				 * error in fdexec
3356 				 */
3357 				FDERRPRINT(FDEP_L1, FDEM_STRT, (C,
3358 				    "fdstart: bad exec of bp: 0x%p, err %d\n",
3359 				    (void *)bp, bp->b_error));
3360 
3361 				bp->b_flags |= B_ERROR;
3362 				if (partial_read) {
3363 					partial_read = 0;
3364 					kmem_free(temp_addr, tlen);
3365 				}
3366 				break;
3367 			}
3368 
3369 			/*
3370 			 * If it was a partial read, copy the useful
3371 			 * portion of data to 'addr'.
3372 			 */
3373 			if (partial_read) {
3374 				partial_read = 0;
3375 				bcopy(temp_addr, addr, len);
3376 				kmem_free(temp_addr, tlen);
3377 				tlen = len;
3378 			}
3379 			if ((fdc->c_fdtype & FDCTYPE_SB) &&
3380 			    (csb->csb_read == CSB_READ)) {
3381 				if (sb_temp_buf_used) {
3382 					bcopy(fdc->dma_buf, addr, tlen);
3383 					sb_temp_buf_used = 0;
3384 				}
3385 			}
3386 
3387 			blk += tlen / ch->fdc_sec_size;
3388 			len -= tlen;
3389 			addr += tlen;
3390 			bp->b_resid -= tlen;
3391 
3392 		}
3393 
3394 		FDERRPRINT(FDEP_L1, FDEM_STRT,
3395 		    (C, "fdstart done: b_resid %lu, b_count %lu, csb_rlen %d\n",
3396 		    bp->b_resid, bp->b_bcount, fdc->c_csb.csb_rlen));
3397 
3398 		fdc->c_current = 0;
3399 		fdretcsb(fdc);
3400 		if (un->un_iostat) {
3401 			if (bp->b_flags & B_READ) {
3402 				KIOSP->reads++;
3403 				KIOSP->nread +=
3404 				    (bp->b_bcount - bp->b_resid);
3405 			} else {
3406 				KIOSP->writes++;
3407 				KIOSP->nwritten += (bp->b_bcount - bp->b_resid);
3408 			}
3409 			kstat_runq_exit(KIOSP);
3410 		}
3411 		biodone(bp);
3412 
3413 		/*
3414 		 * Look at the next buffer
3415 		 */
3416 		bp = fdc->c_actf;
3417 
3418 	}
3419 }
3420 
3421 /*
3422  * Set up DMA resources
3423  * The DMA handle was initialized in fd_attach()
3424  * Assumes the handle has already been allocated by fd_attach()
3425  */
3426 static int
3427 fdstart_dma(struct fdctlr *fdc, caddr_t addr, uint_t len)
3428 {
3429 	int		flags;		/* flags for setting up resources */
3430 	int		res;
3431 
3432 	FDERRPRINT(FDEP_L1, FDEM_SDMA, (C, "fdstart_dma: start\n"));
3433 
3434 	if (fdc->c_csb.csb_read == CSB_READ) {
3435 		flags = DDI_DMA_READ;
3436 	} else {
3437 		flags = DDI_DMA_WRITE;
3438 	}
3439 
3440 
3441 	/* allow partial mapping to maximize the portability of the driver */
3442 	flags = flags | DDI_DMA_PARTIAL;
3443 
3444 	FDERRPRINT(FDEP_L1, FDEM_SDMA, (C, "fdstart_dma: amt. asked for %d\n",
3445 	    len));
3446 
3447 	/*
3448 	 * Zero out the current cookie.  This is done to ensure that
3449 	 * the previous transfers cookie information can in no way be
3450 	 * used.
3451 	 */
3452 	bzero((char *)&fdc->c_csb.csb_dmacookie,
3453 	    sizeof (fdc->c_csb.csb_dmacookie));
3454 	fdc->c_csb.csb_nwin = 0;
3455 	fdc->c_csb.csb_windex = 0;
3456 	fdc->c_csb.csb_ccount = 0;
3457 
3458 	res = ddi_dma_addr_bind_handle(fdc->c_dmahandle, NULL, addr, len,
3459 	    flags, DDI_DMA_DONTWAIT, 0,  &fdc->c_csb.csb_dmacookie,
3460 	    &fdc->c_csb.csb_ccount);
3461 
3462 	switch (res) {
3463 		case DDI_DMA_MAPPED:
3464 			/*
3465 			 * There is one window. csb_windex is the index
3466 			 * into the array of windows. If there are n
3467 			 * windows then, (0 <= windex <= n-1).  csb_windex
3468 			 * represents the index of the next window
3469 			 * to be processed.
3470 			 */
3471 			fdc->c_csb.csb_nwin = 1;
3472 			fdc->c_csb.csb_windex = 1;
3473 
3474 
3475 			FDERRPRINT(FDEP_L1, FDEM_SDMA,
3476 			    (C, "fdstart_dma: DDI_DMA_MAPPED\n"));
3477 
3478 			break;
3479 		case DDI_DMA_PARTIAL_MAP:
3480 
3481 			/*
3482 			 * obtain the number of DMA windows
3483 			 */
3484 			if (ddi_dma_numwin(fdc->c_dmahandle,
3485 			    &fdc->c_csb.csb_nwin) != DDI_SUCCESS) {
3486 				return (-1);
3487 			}
3488 
3489 
3490 			FDERRPRINT(FDEP_L1, FDEM_SDMA,
3491 			    (C, "fdstart_dma: partially mapped %d windows\n",
3492 			    fdc->c_csb.csb_nwin));
3493 
3494 			/*
3495 			 * The DMA window currently in use is window number
3496 			 * one.
3497 			 */
3498 			fdc->c_csb.csb_windex = 1;
3499 
3500 			break;
3501 		case DDI_DMA_NORESOURCES:
3502 			FDERRPRINT(FDEP_L1, FDEM_SDMA,
3503 			    (C, "fdstart_dma: no resources\n"));
3504 			return (-1);
3505 		case DDI_DMA_NOMAPPING:
3506 			FDERRPRINT(FDEP_L1, FDEM_SDMA,
3507 			    (C, "fdstart_dma: no mapping\n"));
3508 			return (-1);
3509 		case DDI_DMA_TOOBIG:
3510 			FDERRPRINT(FDEP_L1, FDEM_SDMA,
3511 			    (C, "fdstart_dma: too big\n"));
3512 			return (-1);
3513 
3514 		case DDI_DMA_INUSE:
3515 			FDERRPRINT(FDEP_L1, FDEM_SDMA,
3516 			    (C, "fdstart_dma: dma inuse\n"));
3517 			return (-1);
3518 		default:
3519 			FDERRPRINT(FDEP_L1, FDEM_SDMA,
3520 			    (C, "fdstart_dma: result is 0x%x\n", res));
3521 			return (-1);
3522 
3523 	};
3524 
3525 	FDERRPRINT(FDEP_L1, FDEM_SDMA,
3526 	    (C, "fdstart_dma: bound the handle\n"));
3527 
3528 	ASSERT(fdc->c_csb.csb_dmacookie.dmac_size);
3529 
3530 	FDERRPRINT(FDEP_L1, FDEM_SDMA, (C, "fdstart_dma: done\n"));
3531 	return (0);
3532 }
3533 
3534 
3535 /*
3536  * fd_unbind_handle: unbind a dma handle if one exists
3537  *		return EIO if unbind failes
3538  */
3539 static int
3540 fd_unbind_handle(struct fdctlr *fdc)
3541 {
3542 	if ((fdc->c_fdtype & FDCTYPE_DMA) &&
3543 	    ((fdc->c_csb.csb_read == CSB_READ) ||
3544 	    (fdc->c_csb.csb_read == CSB_WRITE))) {
3545 		mutex_enter(&fdc->c_hilock);
3546 
3547 		if (fdc->c_fdtype & FDCTYPE_SB) {
3548 			if (fdc->sb_dma_lock) {
3549 				release_sb_dma(fdc);
3550 			}
3551 		}
3552 
3553 		/*
3554 		 * If the byte count isn't zero, then the DMA engine is
3555 		 * still doing a transfer.  If the byte count is nonzero,
3556 		 * reset the DMA engine to cause it to drain.
3557 		 */
3558 
3559 		if (get_data_count_register(fdc) != 0) {
3560 			FDERRPRINT(FDEP_L1, FDEM_EXEC,
3561 			    (C, "unbind & byte count isn't zero\n"));
3562 
3563 			reset_dma_controller(fdc);
3564 			set_dma_control_register(fdc, DCSR_INIT_BITS);
3565 		}
3566 
3567 		if (ddi_dma_unbind_handle(fdc->c_dmahandle) != DDI_SUCCESS) {
3568 			FDERRPRINT(FDEP_L1, FDEM_EXEC,
3569 			    (C, "problem unbinding the handle\n"));
3570 			mutex_exit(&fdc->c_hilock);
3571 			return (EIO);
3572 		}
3573 		mutex_exit(&fdc->c_hilock);
3574 	}
3575 	return (0);
3576 }
3577 
3578 /*
3579  * fdexec
3580  *	all commands go through here.  Assumes the command block
3581  *	fdctlr.c_csb is filled in.  The bytes are sent to the
3582  *	controller and then we do whatever else the csb says -
3583  *	like wait for immediate results, etc.
3584  *
3585  *	All waiting for operations done is in here - to allow retrys
3586  *	and checking for disk changed - so we don't have to worry
3587  *	about sleeping at interrupt level.
3588  *
3589  * RETURNS: 0 if all ok,
3590  *	ENXIO - diskette not in drive
3591  *	EBUSY - if chip is locked or busy
3592  *	EIO - for timeout during sending cmds to chip
3593  *
3594  * to sleep: set FDXC_SLEEP, to check for disk
3595  * changed: set FDXC_CHECKCHG
3596  *
3597  *	- called with the lock held
3598  */
3599 static int
3600 fdexec(struct fdctlr *fdc, int flags)
3601 {
3602 	struct fdcsb *csb;
3603 	int	i;
3604 	int	to, unit;
3605 	uchar_t	tmp;
3606 	caddr_t a = (caddr_t)fdc;
3607 
3608 	FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: flags:%x\n", flags));
3609 
3610 	ASSERT(mutex_owned(&fdc->c_lolock));
3611 
3612 	csb = &fdc->c_csb;
3613 	unit = csb->csb_unit;
3614 
3615 
3616 	ASSERT(unit == fdc->c_un->un_unit_no);
3617 
3618 retry:
3619 	FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: cmd is %s\n",
3620 	    fdcmds[csb->csb_cmds[0] & 0x1f].cmdname));
3621 	FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: transfer rate = %d\n",
3622 	    fdc->c_un->un_chars->fdc_transfer_rate));
3623 	FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: sec size = %d\n",
3624 	    fdc->c_un->un_chars->fdc_sec_size));
3625 	FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: nblocks (512) = %d\n",
3626 	    fdc->c_un->un_label.dkl_map[2].dkl_nblk));
3627 
3628 	if ((fdc->c_fdtype & FDCTYPE_CTRLMASK) == FDCTYPE_82077) {
3629 		fdexec_turn_on_motor(fdc, flags, unit);
3630 	}
3631 
3632 
3633 	fdselect(fdc, unit, 1);	/* select drive */
3634 
3635 	/*
3636 	 * select data rate for this unit/command
3637 	 */
3638 	switch (fdc->c_un->un_chars->fdc_transfer_rate) {
3639 	case 500:
3640 		Dsr(fdc, 0);
3641 		break;
3642 	case 300:
3643 		Dsr(fdc, 1);
3644 		break;
3645 	case 250:
3646 		Dsr(fdc, 2);
3647 		break;
3648 	}
3649 	drv_usecwait(2);
3650 
3651 
3652 	/*
3653 	 * If checking for changed is enabled (i.e., not seeking in checkdisk),
3654 	 * we sample the DSKCHG line to see if the diskette has wandered away.
3655 	 */
3656 	if ((flags & FDXC_CHECKCHG) && fdsense_chng(fdc, unit)) {
3657 		FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "diskette changed\n"));
3658 		fdc->c_un->un_flags |= FDUNIT_CHANGED;
3659 
3660 		if (fdcheckdisk(fdc, unit)) {
3661 
3662 			(void) fd_unbind_handle(fdc);
3663 			return (ENXIO);
3664 
3665 		}
3666 	}
3667 
3668 	/*
3669 	 * gather some statistics
3670 	 */
3671 	switch (csb->csb_cmds[0] & 0x1f) {
3672 	case FDRAW_RDCMD:
3673 		fdc->fdstats.rd++;
3674 		break;
3675 	case FDRAW_WRCMD:
3676 		fdc->fdstats.wr++;
3677 		break;
3678 	case FDRAW_REZERO:
3679 		fdc->fdstats.recal++;
3680 		break;
3681 	case FDRAW_FORMAT:
3682 		fdc->fdstats.form++;
3683 		break;
3684 	default:
3685 		fdc->fdstats.other++;
3686 		break;
3687 	}
3688 
3689 	/*
3690 	 * Always set the opmode *prior* to poking the chip.
3691 	 * This way we don't have to do any locking at high level.
3692 	 */
3693 	csb->csb_raddr = 0;
3694 	csb->csb_rlen = 0;
3695 	if (csb->csb_opflags & CSB_OFSEEKOPS) {
3696 		csb->csb_opmode = 2;
3697 	} else if (csb->csb_opflags & CSB_OFIMMEDIATE) {
3698 		csb->csb_opmode = 0;
3699 	} else {
3700 		csb->csb_opmode = 1;	/* normal data xfer commands */
3701 		csb->csb_raddr = csb->csb_addr;
3702 		csb->csb_rlen = csb->csb_len;
3703 	}
3704 
3705 	bzero((caddr_t)csb->csb_rslt, 10);
3706 	csb->csb_status = 0;
3707 	csb->csb_cmdstat = 0;
3708 
3709 
3710 	/*
3711 	 * Program the DMA engine with the length and address of the transfer
3712 	 * (DMA is only used on a read or a write)
3713 	 */
3714 	if ((fdc->c_fdtype & FDCTYPE_DMA) &&
3715 	    ((fdc->c_csb.csb_read == CSB_READ) ||
3716 	    (fdc->c_csb.csb_read == CSB_WRITE)))  {
3717 		mutex_enter(&fdc->c_hilock);
3718 
3719 		/* Reset the dcsr to clear it of all errors */
3720 
3721 		reset_dma_controller(fdc);
3722 
3723 		FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "cookie addr 0x%p\n",
3724 		    (void *)fdc->c_csb.csb_dmacookie.dmac_laddress));
3725 
3726 		FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "cookie length %ld\n",
3727 		    fdc->c_csb.csb_dmacookie.dmac_size));
3728 		ASSERT(fdc->c_csb.csb_dmacookie.dmac_size);
3729 
3730 		set_data_count_register(fdc,
3731 		    fdc->c_csb.csb_dmacookie.dmac_size);
3732 		set_data_address_register(fdc,
3733 		    fdc->c_csb.csb_dmacookie.dmac_laddress);
3734 
3735 		/* Program the DCSR */
3736 
3737 		if (fdc->c_csb.csb_read == CSB_READ)
3738 			set_dma_mode(fdc, CSB_READ);
3739 		else
3740 			set_dma_mode(fdc, CSB_WRITE);
3741 		mutex_exit(&fdc->c_hilock);
3742 	}
3743 
3744 	/*
3745 	 * I saw this (chip unexpectedly busy) happen when i shoved the
3746 	 * floppy into the drive while
3747 	 * running a dd if= /dev/rfd0c.	so it *is* possible for this to happen.
3748 	 * we need to do a ctlr reset ...
3749 	 */
3750 
3751 	if (Msr(fdc) & CB) {
3752 		/* tried to give command to chip when it is busy! */
3753 		FDERRPRINT(FDEP_L3, FDEM_EXEC,
3754 		    (C, "fdc: unexpectedly busy-stat 0x%x\n", Msr(fdc)));
3755 		csb->csb_cmdstat = 1;	/* XXX TBD ERRS NYD for now */
3756 
3757 		(void) fd_unbind_handle(fdc);
3758 		return (EBUSY);
3759 	}
3760 
3761 	/* Give command to the controller */
3762 	for (i = 0; i < (int)csb->csb_ncmds; i++) {
3763 
3764 		/* Test the readiness of the controller to receive the cmd */
3765 		for (to = FD_CRETRY; to; to--) {
3766 			if ((Msr(fdc) & (DIO|RQM)) == RQM)
3767 				break;
3768 		}
3769 		if (to == 0) {
3770 			FDERRPRINT(FDEP_L2, FDEM_EXEC,
3771 			    (C, "fdc: no RQM - stat 0x%x\n", Msr(fdc)));
3772 			csb->csb_cmdstat = 1;
3773 
3774 			(void) fd_unbind_handle(fdc);
3775 			return (EIO);
3776 		}
3777 
3778 		Set_Fifo(fdc, csb->csb_cmds[i]);
3779 
3780 		FDERRPRINT(FDEP_L1, FDEM_EXEC,
3781 		    (C, "fdexec: sent 0x%x, Msr 0x%x\n", csb->csb_cmds[i],
3782 		    Msr(fdc)));
3783 
3784 	}
3785 
3786 
3787 	/*
3788 	 * Start watchdog timer on data transfer type commands - required
3789 	 * in case a diskette is not present or is unformatted
3790 	 */
3791 	if (csb->csb_opflags & CSB_OFTIMEIT) {
3792 		fdc->c_timeid = timeout(fdwatch, a,
3793 		    tosec * drv_usectohz(1000000));
3794 	}
3795 
3796 	FDERRPRINT(FDEP_L1, FDEM_EXEC,
3797 	    (C, "fdexec: cmd sent, Msr 0x%x\n", Msr(fdc)));
3798 
3799 	/* If the operation has no results - then just return */
3800 	if (csb->csb_opflags & CSB_OFNORESULTS) {
3801 		if (fdc->c_fdtype & FDCTYPE_82077) {
3802 			if (fdc->c_mtimeid == 0) {
3803 				fdc->c_mtimeid = timeout(fdmotoff, a,
3804 				    Motoff_delay);
3805 			}
3806 		}
3807 		FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: O K ..\n"));
3808 
3809 		/*
3810 		 * Make sure the last byte is received well by the
3811 		 * controller. On faster CPU, it may still be busy
3812 		 * by the time another command comes here.
3813 		 */
3814 		for (to = FD_CRETRY; to; to--) {
3815 			if ((Msr(fdc) & (DIO|RQM)) == RQM)
3816 				break;
3817 			}
3818 		if (to == 0) {
3819 			csb->csb_cmdstat = 1;
3820 			return (EIO);
3821 		}
3822 
3823 		/*
3824 		 * An operation that has no results isn't doing DMA so,
3825 		 * there is no reason to try to unbind a handle
3826 		 */
3827 		return (0);
3828 	}
3829 
3830 	/*
3831 	 * If this operation has no interrupt AND an immediate result
3832 	 * then we just busy wait for the results and stuff them into
3833 	 * the csb
3834 	 */
3835 	if (csb->csb_opflags & CSB_OFIMMEDIATE) {
3836 		to = FD_RRETRY;
3837 		csb->csb_nrslts = 0;
3838 		/*
3839 		 * Wait while this command is still going on.
3840 		 */
3841 		while ((tmp = Msr(fdc)) & CB) {
3842 			/*
3843 			 * If RQM + DIO, then a result byte is at hand.
3844 			 */
3845 			if ((tmp & (RQM|DIO|CB)) == (RQM|DIO|CB)) {
3846 				csb->csb_rslt[csb->csb_nrslts++] =
3847 				    Fifo(fdc);
3848 				/*
3849 				 * FDERRPRINT(FDEP_L4, FDEM_EXEC,
3850 				 *    (C, "fdexec: got result 0x%x\n",
3851 				 *    csb->csb_nrslts));
3852 				 */
3853 			} else if (--to == 0) {
3854 				FDERRPRINT(FDEP_L4, FDEM_EXEC,
3855 				    (C, "fdexec: timeout, Msr%x, nr%x\n",
3856 				    Msr(fdc), csb->csb_nrslts));
3857 
3858 				csb->csb_status = 2;
3859 				if (fdc->c_fdtype & FDCTYPE_82077) {
3860 					if (fdc->c_mtimeid == 0) {
3861 						fdc->c_mtimeid = timeout(
3862 						    fdmotoff, a, Motoff_delay);
3863 					}
3864 				}
3865 				/*
3866 				 * There is no DMA happening.  No need to
3867 				 * try freeing a handle.
3868 				 */
3869 
3870 				return (EIO);
3871 			}
3872 		}
3873 	}
3874 
3875 	/*
3876 	 * If told to sleep here, well then sleep!
3877 	 */
3878 
3879 	if (flags & FDXC_SLEEP) {
3880 		fdc->c_flags |= FDCFLG_WAITING;
3881 		while (fdc->c_flags & FDCFLG_WAITING) {
3882 			cv_wait(&fdc->c_iocv, &fdc->c_lolock);
3883 		}
3884 	}
3885 
3886 	/*
3887 	 * kludge for end-of-cylinder error which must be ignored!!!
3888 	 */
3889 
3890 	if ((fdc->c_fdtype & FDCTYPE_TCBUG) &&
3891 	    ((csb->csb_rslt[0] & IC_SR0) == 0x40) &&
3892 	    (csb->csb_rslt[1] & EN_SR1))
3893 		csb->csb_rslt[0] &= ~IC_SR0;
3894 
3895 	/*
3896 	 * See if there was an error detected, if so, fdrecover()
3897 	 * will check it out and say what to do.
3898 	 *
3899 	 * Don't do this, though, if this was the Sense Drive Status
3900 	 * or the Dump Registers command.
3901 	 */
3902 	if (((csb->csb_rslt[0] & IC_SR0) || (fdc->c_csb.csb_dcsr_rslt) ||
3903 	    (csb->csb_status)) &&
3904 	    ((csb->csb_cmds[0] != FDRAW_SENSE_DRV) &&
3905 	    (csb->csb_cmds[0] != DUMPREG))) {
3906 		/* if it can restarted OK, then do so, else return error */
3907 		if (fdrecover(fdc) != 0) {
3908 			if (fdc->c_fdtype & FDCTYPE_82077) {
3909 				if (fdc->c_mtimeid == 0) {
3910 					fdc->c_mtimeid = timeout(fdmotoff,
3911 					    a, Motoff_delay);
3912 				}
3913 			}
3914 
3915 			/*
3916 			 * If this was a dma transfer, unbind the handle so
3917 			 * that other transfers may use it.
3918 			 */
3919 
3920 			(void) fd_unbind_handle(fdc);
3921 			return (EIO);
3922 		} else {
3923 			/* ASSUMES that cmd is still intact in csb */
3924 			goto retry;
3925 		}
3926 	}
3927 
3928 	/* things went ok */
3929 	if (fdc->c_fdtype & FDCTYPE_82077) {
3930 		if (fdc->c_mtimeid == 0) {
3931 			fdc->c_mtimeid = timeout(fdmotoff, a, Motoff_delay);
3932 		}
3933 	}
3934 	FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: O K ..........\n"));
3935 
3936 	if (fd_unbind_handle(fdc))
3937 		return (EIO);
3938 
3939 	return (0);
3940 }
3941 
3942 /*
3943  * Turn on the drive's motor
3944  *
3945  *	- called with the low level lock held
3946  */
3947 static void
3948 fdexec_turn_on_motor(struct fdctlr *fdc, int flags,  uint_t unit)
3949 {
3950 	clock_t local_lbolt;
3951 	timeout_id_t timeid;
3952 
3953 	/*
3954 	 * The low level mutex may not be held over the call to
3955 	 * untimeout().  See the manpage for details.
3956 	 */
3957 	timeid = fdc->c_mtimeid;
3958 	fdc->c_mtimeid = 0;
3959 	if (timeid) {
3960 		mutex_exit(&fdc->c_lolock);
3961 		(void) untimeout(timeid);
3962 		mutex_enter(&fdc->c_lolock);
3963 	}
3964 
3965 	ASSERT(fdc->c_un->un_unit_no == unit);
3966 
3967 
3968 	set_rotational_speed(fdc, unit);
3969 
3970 	if (!(Dor(fdc) & (MOTEN(unit)))) {
3971 		/*
3972 		 * Turn on the motor
3973 		 */
3974 		FDERRPRINT(FDEP_L1, FDEM_EXEC,
3975 		    (C, "fdexec: turning on motor\n"));
3976 
3977 		/* LINTED */
3978 		Set_dor(fdc, (MOTEN(unit)), 1);
3979 
3980 		if (flags & FDXC_SLEEP) {
3981 			local_lbolt = ddi_get_lbolt();
3982 			(void) cv_timedwait(&fdc->c_motoncv,
3983 			    &fdc->c_lolock, local_lbolt + Moton_delay);
3984 		} else {
3985 			drv_usecwait(1000000);
3986 		}
3987 	}
3988 
3989 }
3990 
3991 /*
3992  * fdrecover
3993  *	see if possible to retry an operation.
3994  *	All we can do is restart the operation.	 If we are out of allowed
3995  *	retries - return non-zero so that the higher levels will be notified.
3996  *
3997  * RETURNS: 0 if ok to restart, !0 if can't or out of retries
3998  *	- called with the low level lock held
3999  */
4000 static int
4001 fdrecover(struct fdctlr *fdc)
4002 {
4003 	struct fdcsb *csb;
4004 
4005 	FDERRPRINT(FDEP_L1, FDEM_RECO, (C, "fdrecover\n"));
4006 	csb = &fdc->c_csb;
4007 
4008 	if (fdc->c_flags & FDCFLG_TIMEDOUT) {
4009 		struct fdcsb savecsb;
4010 
4011 		fdc->c_flags ^= FDCFLG_TIMEDOUT;
4012 		csb->csb_rslt[1] |= TO_SR1;
4013 		FDERRPRINT(FDEP_L1, FDEM_RECO,
4014 		    (C, "fd%d: %s timed out\n", csb->csb_unit,
4015 		    fdcmds[csb->csb_cmds[0] & 0x1f].cmdname));
4016 
4017 		/* use private csb */
4018 		savecsb = fdc->c_csb;
4019 		bzero(&fdc->c_csb, sizeof (struct fdcsb));
4020 		FDERRPRINT(FDEP_L1, FDEM_RECO, (C, "fdc: resetting\n"));
4021 
4022 		(void) fdreset(fdc);
4023 
4024 		if (fdc->c_fdtype & FDCTYPE_DMA) {
4025 			mutex_enter(&fdc->c_hilock);
4026 			/* Reset the DMA engine as well */
4027 			reset_dma_controller(fdc);
4028 			set_dma_control_register(fdc, DCSR_INIT_BITS);
4029 			mutex_exit(&fdc->c_hilock);
4030 		}
4031 
4032 
4033 		/* check change first?? */
4034 		/* don't ckchg in fdexec, too convoluted */
4035 		(void) fdrecalseek(fdc, savecsb.csb_unit, -1, 0);
4036 		fdc->c_csb = savecsb; /* restore original csb */
4037 	}
4038 
4039 	/*
4040 	 * gather statistics on errors
4041 	 */
4042 	if (csb->csb_rslt[1] & DE_SR1) {
4043 		fdc->fdstats.de++;
4044 	}
4045 	if (csb->csb_rslt[1] & OR_SR1) {
4046 		fdc->fdstats.run++;
4047 	}
4048 	if (csb->csb_rslt[1] & (ND_SR1+MA_SR1)) {
4049 		fdc->fdstats.bfmt++;
4050 	}
4051 	if (csb->csb_rslt[1] & TO_SR1) {
4052 		fdc->fdstats.to++;
4053 	}
4054 
4055 	/*
4056 	 * If raw ioctl don't examine results just pass status
4057 	 * back via fdraw. Raw commands are timed too, so put this
4058 	 * after the above check.
4059 	 */
4060 	if (csb->csb_opflags & CSB_OFRAWIOCTL) {
4061 		return (1);
4062 	}
4063 
4064 
4065 	/*
4066 	 * if there was a pci bus error, do not retry
4067 	 */
4068 
4069 		if (csb->csb_dcsr_rslt == 1) {
4070 			FDERRPRINT(FDEP_L3, FDEM_RECO,
4071 			    (C, "fd%d: host bus error\n", 0));
4072 		return (1);
4073 		}
4074 
4075 	/*
4076 	 * If there was an error with the DMA functions, do not retry
4077 	 */
4078 	if (csb->csb_dma_rslt == 1) {
4079 			FDERRPRINT(FDEP_L1, FDEM_RECO,
4080 			    (C, "fd%d: DMA interface error\n", csb->csb_unit));
4081 		return (1);
4082 	}
4083 
4084 
4085 	/*
4086 	 * if we have run out of retries, return an error
4087 	 * XXX need better status interp
4088 	 */
4089 
4090 	csb->csb_retrys++;
4091 	if (csb->csb_retrys > csb->csb_maxretry) {
4092 		FDERRPRINT(FDEP_L3, FDEM_RECO,
4093 		    (C, "fd%d: %s failed (%x %x %x)\n",
4094 		    0, fdcmds[csb->csb_cmds[0] & 0x1f].cmdname,
4095 		    csb->csb_rslt[0], csb->csb_rslt[1], csb->csb_rslt[2]));
4096 		if (csb->csb_rslt[1] & NW_SR1) {
4097 			FDERRPRINT(FDEP_L3, FDEM_RECO,
4098 			    (C, "fd%d: not writable\n", 0));
4099 		}
4100 		if (csb->csb_rslt[1] & DE_SR1) {
4101 			FDERRPRINT(FDEP_L3, FDEM_RECO,
4102 			    (C, "fd%d: crc error blk %d\n", 0,
4103 			    (int)fdc->c_current->b_blkno));
4104 		}
4105 		if (csb->csb_rslt[1] & OR_SR1) {
4106 			if (fdc->c_fdtype & FDCTYPE_SB) {
4107 				/*
4108 				 * When using southbridge chip we need to
4109 				 * retry atleast 10 times to shake off the
4110 				 * underrun err.
4111 				 */
4112 				if (csb->csb_retrys <= rwretry)
4113 					return (0);
4114 			}
4115 			FDERRPRINT(FDEP_L3, FDEM_RECO,
4116 			    (C, "fd%d: over/underrun\n", 0));
4117 		}
4118 
4119 		if (csb->csb_rslt[1] & (ND_SR1+MA_SR1)) {
4120 			FDERRPRINT(FDEP_L3, FDEM_RECO,
4121 			    (C, "fd%d: bad format\n", 0));
4122 		}
4123 
4124 		if (csb->csb_rslt[1] & TO_SR1) {
4125 			FDERRPRINT(FDEP_L3, FDEM_RECO,
4126 			    (C, "fd%d: timeout\n", 0));
4127 		}
4128 
4129 		csb->csb_cmdstat = 1; /* failed - give up */
4130 		return (1);
4131 	}
4132 
4133 	if (csb->csb_opflags & CSB_OFSEEKOPS) {
4134 		/* seek, recal type commands - just look at st0 */
4135 		FDERRPRINT(FDEP_L2, FDEM_RECO,
4136 		    (C, "fd%d: %s error : st0 0x%x\n", csb->csb_unit,
4137 		    fdcmds[csb->csb_cmds[0] & 0x1f].cmdname,
4138 		    csb->csb_rslt[0]));
4139 	}
4140 	if (csb->csb_opflags & CSB_OFXFEROPS) {
4141 		/* rd, wr, fmt type commands - look at st0, st1, st2 */
4142 		FDERRPRINT(FDEP_L2, FDEM_RECO,
4143 		    (C, "fd%d: %s error : st0=0x%x st1=0x%x st2=0x%x\n",
4144 		    csb->csb_unit, fdcmds[csb->csb_cmds[0] & 0x1f].cmdname,
4145 		    csb->csb_rslt[0], csb->csb_rslt[1], csb->csb_rslt[2]));
4146 	}
4147 
4148 	return (0);	/* tell fdexec to retry */
4149 }
4150 
4151 /*
4152  * Interrupt handle for DMA
4153  */
4154 
4155 static uint_t
4156 fdintr_dma()
4157 {
4158 	struct fdctlr   *fdc;
4159 	off_t		off;
4160 	size_t		len;
4161 	uint_t		ccount;
4162 	uint_t		windex;
4163 	uint_t		done = 0;
4164 	int		tmp_dcsr;
4165 	int		to;
4166 	uchar_t		tmp;
4167 	int		i = 0;
4168 	int		res = DDI_INTR_UNCLAIMED;
4169 	int		not_cheerio = 1;
4170 
4171 	/* search for a controller that's expecting an interrupt */
4172 	fdc = fdctlrs;
4173 
4174 	if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
4175 		tmp_dcsr = get_dma_control_register(fdc);
4176 		if (!(tmp_dcsr & DCSR_INT_PEND) && !(DCSR_ERR_PEND & tmp_dcsr))
4177 			return (res);
4178 		not_cheerio = 0;
4179 	}
4180 
4181 	mutex_enter(&fdc->c_hilock);
4182 
4183 	if (fdc->c_csb.csb_opmode == 0x0) {
4184 		fdc->c_csb.csb_opmode = 2;
4185 	}
4186 	if (fdc->sb_dma_lock) {
4187 		release_sb_dma(fdc);
4188 	}
4189 
4190 	/*
4191 	 * An interrupt can come from either the floppy controller or
4192 	 * or the DMA engine.  The DMA engine will only issue an
4193 	 * interrupt if there was an error.
4194 	 */
4195 
4196 	switch (fdc->c_csb.csb_opmode) {
4197 		case 0x1:
4198 			/* read/write/format data-xfer case */
4199 
4200 			FDERRPRINT(FDEP_L1, FDEM_INTR,
4201 			    (C, "fdintr_dma: opmode 1\n"));
4202 
4203 			/*
4204 			 * See if the interrupt is from the floppy
4205 			 * controller.  If there is, take out the status bytes.
4206 			 */
4207 
4208 			if (not_cheerio || (tmp_dcsr & DCSR_INT_PEND)) {
4209 
4210 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4211 				    (C, "fdintr_dma: INT_PEND \n"));
4212 
4213 				res = DDI_INTR_CLAIMED;
4214 
4215 				to = FD_RRETRY;
4216 				fdc->c_csb.csb_nrslts = 0;
4217 
4218 				/* check status */
4219 				i = 0;
4220 
4221 				/*
4222 				 * CB turns off once all the result bytes are
4223 				 *  read.
4224 				 *
4225 				 * NOTE: the counters are there so that the
4226 				 * handler will never get stuck in a loop.
4227 				 * If the counters do reach their maximum
4228 				 * values, then a catastrophic error has
4229 				 * occurred.  This should never be the case.
4230 				 * The counters only came into play during
4231 				 * development.
4232 				 */
4233 				while (((tmp = Msr(fdc)) & CB) &&
4234 				    (i < 1000001)) {
4235 
4236 					/*
4237 					 * If RQM + DIO, then a result byte
4238 					 * is at hand.
4239 					 */
4240 					if ((tmp & (RQM|DIO|CB)) ==
4241 					    (RQM|DIO|CB)) {
4242 						fdc->c_csb.csb_rslt
4243 						    [fdc->c_csb.csb_nrslts++]
4244 						    = Fifo(fdc);
4245 
4246 						FDERRPRINT(FDEP_L1, FDEM_INTR,
4247 						    (C,
4248 						    "fdintr_dma: res 0x%x\n",
4249 						    fdc->c_csb.csb_rslt
4250 						    [fdc->c_csb.csb_nrslts
4251 						    - 1]));
4252 
4253 					} else if (--to == 0) {
4254 						/*
4255 						 * controller was never
4256 						 * ready to give results
4257 						 */
4258 						fdc->c_csb.csb_status = 2;
4259 						break;
4260 					}
4261 					i++;
4262 				}
4263 				if (i == 10000) {
4264 					FDERRPRINT(FDEP_L1, FDEM_INTR,
4265 					    (C, "First loop overran\n"));
4266 				}
4267 			}
4268 
4269 			/*
4270 			 * See if the interrupt is from the DMA engine,
4271 			 * which will only interrupt on an error
4272 			 */
4273 			if ((!not_cheerio) && (tmp_dcsr & DCSR_ERR_PEND)) {
4274 
4275 				res = DDI_INTR_CLAIMED;
4276 
4277 				done = 1;
4278 				fdc->c_csb.csb_dcsr_rslt = 1;
4279 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4280 				    (C, "fdintr_dma: Error pending\n"));
4281 				reset_dma_controller(fdc);
4282 				set_dma_control_register(fdc, DCSR_INIT_BITS);
4283 				break;
4284 			}
4285 
4286 			/* TCBUG kludge */
4287 			if ((fdc->c_fdtype & FDCTYPE_TCBUG) &&
4288 			    ((fdc->c_csb.csb_rslt[0] & IC_SR0) == 0x40) &&
4289 			    (fdc->c_csb.csb_rslt[1] & EN_SR1)) {
4290 
4291 				fdc->c_csb.csb_rslt[0] &= ~IC_SR0;
4292 
4293 				fdc->c_csb.csb_rslt[1] &= ~EN_SR1;
4294 
4295 
4296 			}
4297 
4298 
4299 			/* Exit if there were errors in the DMA */
4300 			if (((fdc->c_csb.csb_rslt[0] & IC_SR0) != 0) ||
4301 			    (fdc->c_csb.csb_rslt[1] != 0) ||
4302 			    (fdc->c_csb.csb_rslt[2] != 0)) {
4303 				done = 1;
4304 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4305 				    (C, "fdintr_dma: errors in command\n"));
4306 
4307 
4308 				break;
4309 			}
4310 
4311 
4312 			FDERRPRINT(FDEP_L1, FDEM_INTR,
4313 			    (C, "fdintr_dma: dbcr 0x%x\n",
4314 			    get_data_count_register(fdc)));
4315 			/*
4316 			 * The csb_ccount is the number of cookies that still
4317 			 * need to be processed.  A cookie was just processed
4318 			 * so decrement the cookie counter.
4319 			 */
4320 			if (fdc->c_csb.csb_ccount == 0) {
4321 				done = 1;
4322 				break;
4323 			}
4324 			fdc->c_csb.csb_ccount--;
4325 			ccount = fdc->c_csb.csb_ccount;
4326 
4327 			windex = fdc->c_csb.csb_windex;
4328 
4329 			/*
4330 			 * If there are no more cookies and all the windows
4331 			 * have been DMA'd, then DMA is done.
4332 			 *
4333 			 */
4334 			if ((ccount == 0) && (windex == fdc->c_csb.csb_nwin)) {
4335 
4336 				done = 1;
4337 
4338 				/*
4339 				 * The handle is unbound in fdexec
4340 				 */
4341 
4342 				break;
4343 			}
4344 
4345 			if (ccount != 0) {
4346 				/* process the next cookie */
4347 				ddi_dma_nextcookie(fdc->c_dmahandle,
4348 				    &fdc->c_csb.csb_dmacookie);
4349 
4350 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4351 				    (C, "cookie addr 0x%" PRIx64 "\n",
4352 				    fdc->c_csb.csb_dmacookie.dmac_laddress));
4353 
4354 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4355 				    (C, "cookie length %lu\n",
4356 				    fdc->c_csb.csb_dmacookie.dmac_size));
4357 
4358 			} else {
4359 
4360 				(void) ddi_dma_getwin(fdc->c_dmahandle,
4361 				    fdc->c_csb.csb_windex,
4362 				    &off, &len,
4363 				    &fdc->c_csb.csb_dmacookie,
4364 				    &fdc->c_csb.csb_ccount);
4365 				fdc->c_csb.csb_windex++;
4366 
4367 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4368 				    (C, "fdintr_dma: process %d window\n",
4369 				    fdc->c_csb.csb_windex));
4370 
4371 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4372 				    (C, "fdintr_dma: process no. cookies %d\n",
4373 				    fdc->c_csb.csb_ccount));
4374 
4375 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4376 				    (C, "cookie addr 0x%" PRIx64 "\n",
4377 				    fdc->c_csb.csb_dmacookie.dmac_laddress));
4378 
4379 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4380 				    (C, "cookie length %lu\n",
4381 				    fdc->c_csb.csb_dmacookie.dmac_size));
4382 			}
4383 
4384 			/*
4385 			 * Program the DMA engine with the length and
4386 			 * the address of the transfer
4387 			 */
4388 
4389 			ASSERT(fdc->c_csb.csb_dmacookie.dmac_size);
4390 
4391 			set_data_count_register(fdc,
4392 			    fdc->c_csb.csb_dmacookie.dmac_size);
4393 			set_data_address_register(fdc,
4394 			    fdc->c_csb.csb_dmacookie.dmac_laddress);
4395 
4396 			FDERRPRINT(FDEP_L1, FDEM_INTR, (C,
4397 			    "fdintr_dma: size 0x%lx\n",
4398 			    fdc->c_csb.csb_dmacookie.dmac_size));
4399 
4400 
4401 			/* reprogram the controller */
4402 			fdc->c_csb.csb_cmds[2] = fdc->c_csb.csb_rslt[3];
4403 			fdc->c_csb.csb_cmds[3] = fdc->c_csb.csb_rslt[4];
4404 			fdc->c_csb.csb_cmds[4] = fdc->c_csb.csb_rslt[5];
4405 			fdc->c_csb.csb_cmds[1] = (fdc->c_csb.csb_cmds[1]
4406 			    & ~0x04) | (fdc->c_csb.csb_rslt[4] << 2);
4407 
4408 			for (i = 0; i < (int)fdc->c_csb.csb_ncmds; i++) {
4409 
4410 				/*
4411 				 * Test the readiness of the controller
4412 				 * to receive the cmd
4413 				 */
4414 				for (to = FD_CRETRY; to; to--) {
4415 					if ((Msr(fdc) & (DIO|RQM)) == RQM)
4416 						break;
4417 				}
4418 				if (to == 0) {
4419 					FDERRPRINT(FDEP_L2, FDEM_EXEC,
4420 					    (C,
4421 					    "fdc: no RQM - stat 0x%x\n",
4422 					    Msr(fdc)));
4423 					/* stop the DMA from happening */
4424 					fdc->c_csb.csb_status = 2;
4425 					done = 1;
4426 					break;
4427 				}
4428 
4429 				Set_Fifo(fdc, fdc->c_csb.csb_cmds[i]);
4430 
4431 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4432 				    (C,
4433 				    "fdintr_dma: sent 0x%x, Msr 0x%x\n",
4434 				    fdc->c_csb.csb_cmds[i], Msr(fdc)));
4435 			}
4436 
4437 			/* reenable DMA */
4438 			if ((!not_cheerio) && (!done))
4439 				set_dma_control_register(fdc, tmp_dcsr |
4440 				    DCSR_EN_DMA);
4441 			break;
4442 
4443 		case 0x2:
4444 		/* seek/recal type cmd */
4445 			FDERRPRINT(FDEP_L1, FDEM_INTR,
4446 			    (C, "fintr_dma: opmode 2\n"));
4447 
4448 			/*
4449 			 *  See if the interrupt is from the DMA engine,
4450 			 *  which will only interrupt if there was an error.
4451 			 */
4452 			if ((!not_cheerio) && (tmp_dcsr & DCSR_ERR_PEND)) {
4453 				res = DDI_INTR_CLAIMED;
4454 				done = 1;
4455 				fdc->c_csb.csb_dcsr_rslt = 1;
4456 				reset_dma_controller(fdc);
4457 				set_dma_control_register(fdc, DCSR_INIT_BITS);
4458 
4459 				break;
4460 			}
4461 
4462 
4463 			/* See if the interrupt is from the floppy controller */
4464 			if (not_cheerio || (tmp_dcsr & DCSR_INT_PEND)) {
4465 
4466 				res = DDI_INTR_CLAIMED;
4467 
4468 
4469 				/*
4470 				 * Wait until there's no longer a command
4471 				 * in progress
4472 				 */
4473 
4474 				FDERRPRINT(FDEP_L1, FDEM_INTR,
4475 				    (C, "fdintr_dma: interrupt pending\n"));
4476 				i = 0;
4477 				while (((Msr(fdc) & CB)) && (i < 10000)) {
4478 					i++;
4479 				}
4480 
4481 				if (i == 10000)
4482 					FDERRPRINT(FDEP_L1, FDEM_INTR,
4483 					    (C, "2nd loop overran !!!\n"));
4484 
4485 				/*
4486 				 * Check the RQM bit to see if the controller is
4487 				 * ready to transfer status of the command.
4488 				 */
4489 				i = 0;
4490 				while ((!(Msr(fdc) & RQM)) && (i < 10000)) {
4491 					i++;
4492 				}
4493 
4494 				if (i == 10000)
4495 					FDERRPRINT(FDEP_L1, FDEM_INTR,
4496 					    (C, "3rd loop overran !!!\n"));
4497 
4498 				/*
4499 				 * Issue the Sense Interrupt Status Command
4500 				 */
4501 				Set_Fifo(fdc, SNSISTAT);
4502 
4503 				i = 0;
4504 				while ((!(Msr(fdc) & RQM)) && (i < 10000)) {
4505 					i++;
4506 				}
4507 				if (i == 10000)
4508 					FDERRPRINT(FDEP_L1, FDEM_INTR,
4509 					    (C, "4th loop overran !!!\n"));
4510 
4511 				/* Store the first result byte */
4512 				fdc->c_csb.csb_rslt[0] = Fifo(fdc);
4513 
4514 				i = 0;
4515 				while ((!(Msr(fdc) & RQM)) && (i < 10000)) {
4516 					i++;
4517 				}
4518 				if (i == 10000)
4519 					FDERRPRINT(FDEP_L1, FDEM_INTR,
4520 					    (C, "5th loop overran !!!\n"));
4521 
4522 				/* Store the second  result byte */
4523 				fdc->c_csb.csb_rslt[1] = Fifo(fdc);
4524 
4525 				done = 1;
4526 			}
4527 
4528 		}
4529 
4530 	/*
4531 	 * We are done with the actual interrupt handling here.
4532 	 * The portion below should be actually be done by fd_lointr().
4533 	 * We should be triggering the fd_lointr here and exiting.
4534 	 * However for want of time this will be done in the next FIX.
4535 	 *
4536 	 * Hence for now we will release hilock only and keep the remaining
4537 	 * code as it is.
4538 	 * Releasing of hilock ensures that we don't hold on to the
4539 	 * lolock and hilock at the same time.
4540 	 * hilock is acquired each time dma related  registers are accessed.
4541 	 */
4542 	mutex_exit(&fdc->c_hilock);
4543 	/* Make signal and get out of interrupt handler */
4544 	if (done) {
4545 		mutex_enter(&fdc->c_lolock);
4546 
4547 		fdc->c_csb.csb_opmode = 0;
4548 
4549 		/*  reset watchdog timer if armed and not already triggered */
4550 
4551 
4552 		if (fdc->c_timeid) {
4553 			timeout_id_t timeid = fdc->c_timeid;
4554 			fdc->c_timeid = 0;
4555 			mutex_exit(&fdc->c_lolock);
4556 			(void) untimeout(timeid);
4557 			mutex_enter(&fdc->c_lolock);
4558 		}
4559 
4560 
4561 		if (fdc->c_flags & FDCFLG_WAITING) {
4562 			/*
4563 			 * somebody's waiting on finish of fdctlr/csb,
4564 			 * wake them
4565 			 */
4566 
4567 			FDERRPRINT(FDEP_L1, FDEM_INTR,
4568 			    (C, "fdintr_dma: signal the waiter\n"));
4569 
4570 			fdc->c_flags ^= FDCFLG_WAITING;
4571 			cv_signal(&fdc->c_iocv);
4572 
4573 			/*
4574 			 * FDCFLG_BUSY is NOT cleared, NOR is the csb given
4575 			 * back; the operation just finished can look at the csb
4576 			 */
4577 		} else {
4578 			FDERRPRINT(FDEP_L1, FDEM_INTR,
4579 			    (C, "fdintr_dma: nobody sleeping (%x %x %x)\n",
4580 			    fdc->c_csb.csb_rslt[0], fdc->c_csb.csb_rslt[1],
4581 			    fdc->c_csb.csb_rslt[2]));
4582 		}
4583 		mutex_exit(&fdc->c_lolock);
4584 	}
4585 	/* update high level interrupt counter */
4586 	if (fdc->c_intrstat)
4587 		KIOIP->intrs[KSTAT_INTR_HARD]++;
4588 
4589 
4590 	FDERRPRINT(FDEP_L1, FDEM_INTR, (C, "fdintr_dma: done\n"));
4591 	return (res);
4592 }
4593 
4594 /*
4595  * fd_lointr
4596  *	This is the low level SW interrupt handler triggered by the high
4597  *	level interrupt handler (or by fdwatch).
4598  */
4599 static uint_t
4600 fd_lointr(caddr_t arg)
4601 {
4602 	struct fdctlr *fdc = (struct fdctlr *)arg;
4603 	struct fdcsb *csb;
4604 
4605 	csb = &fdc->c_csb;
4606 	FDERRPRINT(FDEP_L1, FDEM_INTR, (C, "fdintr: opmode %d\n",
4607 	    csb->csb_opmode));
4608 	/*
4609 	 * Check that lowlevel interrupt really meant to trigger us.
4610 	 */
4611 	if (csb->csb_opmode != 4) {
4612 		/*
4613 		 * This should probably be protected, but, what the
4614 		 * heck...the cost isn't worth the accuracy for this
4615 		 * statistic.
4616 		 */
4617 		if (fdc->c_intrstat)
4618 			KIOIP->intrs[KSTAT_INTR_SPURIOUS]++;
4619 		return (DDI_INTR_UNCLAIMED);
4620 	}
4621 
4622 	mutex_enter(&fdc->c_lolock);
4623 	csb->csb_opmode = 0;
4624 
4625 	/*  reset watchdog timer if armed and not already triggered */
4626 	if (fdc->c_timeid) {
4627 		timeout_id_t timeid = fdc->c_timeid;
4628 		fdc->c_timeid = 0;
4629 		mutex_exit(&fdc->c_lolock);
4630 		(void) untimeout(timeid);
4631 		mutex_enter(&fdc->c_lolock);
4632 
4633 	}
4634 
4635 	if (fdc->c_flags & FDCFLG_WAITING) {
4636 		/*
4637 		 * somebody's waiting on finish of fdctlr/csb, wake them
4638 		 */
4639 		fdc->c_flags ^= FDCFLG_WAITING;
4640 		cv_signal(&fdc->c_iocv);
4641 
4642 		/*
4643 		 * FDCFLG_BUSY is NOT cleared, NOR is the csb given back; so
4644 		 * the operation just finished can look at the csb
4645 		 */
4646 	} else {
4647 		FDERRPRINT(FDEP_L3, FDEM_INTR,
4648 		    (C, "fdintr: nobody sleeping (%x %x %x)\n",
4649 		    csb->csb_rslt[0], csb->csb_rslt[1], csb->csb_rslt[2]));
4650 	}
4651 	if (fdc->c_intrstat)
4652 		KIOIP->intrs[KSTAT_INTR_SOFT]++;
4653 	mutex_exit(&fdc->c_lolock);
4654 	return (DDI_INTR_CLAIMED);
4655 }
4656 
4657 /*
4658  * fdwatch
4659  *	is called from timein() when a floppy operation has expired.
4660  */
4661 static void
4662 fdwatch(void *arg)
4663 {
4664 	struct fdctlr *fdc = arg;
4665 	int old_opmode;
4666 	struct fdcsb *csb;
4667 
4668 	FDERRPRINT(FDEP_L1, FDEM_WATC, (C, "fdwatch\n"));
4669 
4670 	mutex_enter(&fdc->c_lolock);
4671 	if (fdc->c_timeid == 0) {
4672 		/*
4673 		 * fdintr got here first, ergo, no timeout condition..
4674 		 */
4675 
4676 		FDERRPRINT(FDEP_L1, FDEM_WATC,
4677 		    (C, "fdwatch: no timeout\n"));
4678 
4679 		mutex_exit(&fdc->c_lolock);
4680 		return;
4681 	}
4682 	fdc->c_timeid = 0;
4683 	csb = &fdc->c_csb;
4684 
4685 	mutex_enter(&fdc->c_hilock);
4686 	/*
4687 	 * XXXX: We should probably reset the bloody chip
4688 	 */
4689 	old_opmode = csb->csb_opmode;
4690 
4691 	FDERRPRINT(FDEP_L1, FDEM_WATC,
4692 	    (C, "fd%d: timeout, opmode:%d\n", csb->csb_unit, old_opmode));
4693 
4694 	csb->csb_opmode = 4;
4695 	mutex_exit(&fdc->c_hilock);
4696 
4697 	FDERRPRINT(FDEP_L1, FDEM_WATC, (C, "fdwatch: cmd %s timed out\n",
4698 	    fdcmds[csb->csb_cmds[0] & 0x1f].cmdname));
4699 	fdc->c_flags |= FDCFLG_TIMEDOUT;
4700 	csb->csb_status = CSB_CMDTO;
4701 
4702 	if ((fdc->c_fdtype & FDCTYPE_DMA) == 0) {
4703 		ddi_trigger_softintr(fdc->c_softid);
4704 		KIOIP->intrs[KSTAT_INTR_WATCHDOG]++;
4705 		mutex_exit(&fdc->c_lolock);
4706 	} else {
4707 		mutex_exit(&fdc->c_lolock);
4708 		(void) fd_lointr((caddr_t)fdctlrs);
4709 	}
4710 }
4711 
4712 /*
4713  * fdgetcsb
4714  *	wait until the csb is free
4715  */
4716 static void
4717 fdgetcsb(struct fdctlr *fdc)
4718 {
4719 	FDERRPRINT(FDEP_L1, FDEM_GETC, (C, "fdgetcsb\n"));
4720 	ASSERT(mutex_owned(&fdc->c_lolock));
4721 	while (fdc->c_flags & FDCFLG_BUSY) {
4722 		fdc->c_flags |= FDCFLG_WANT;
4723 		cv_wait(&fdc->c_csbcv, &fdc->c_lolock);
4724 	}
4725 	fdc->c_flags |= FDCFLG_BUSY; /* got it! */
4726 }
4727 
4728 /*
4729  * fdretcsb
4730  *	return csb
4731  */
4732 static void
4733 fdretcsb(struct fdctlr *fdc)
4734 {
4735 
4736 	ASSERT(mutex_owned(&fdc->c_lolock));
4737 	FDERRPRINT(FDEP_L1, FDEM_RETC, (C, "fdretcsb\n"));
4738 	fdc->c_flags &= ~FDCFLG_BUSY; /* let go */
4739 
4740 	fdc->c_csb.csb_read = 0;
4741 
4742 	if (fdc->c_flags & FDCFLG_WANT) {
4743 		fdc->c_flags ^= FDCFLG_WANT;
4744 		/*
4745 		 * broadcast the signal.  One thread will wake up and
4746 		 * set the flags to FDCFLG_BUSY.  If more than one thread is
4747 		 * waiting then each thread will wake up in turn.  The first
4748 		 * thread to wake-up will set the FDCFLG_BUSY flag and the
4749 		 * subsequent threads will will wake-up, but reset the
4750 		 * flag to FDCFLG_WANT because the FDCFLG_BUSY bit is set.
4751 		 */
4752 		cv_broadcast(&fdc->c_csbcv);
4753 	}
4754 }
4755 
4756 
4757 /*
4758  * fdreset
4759  *	reset THE controller, and configure it to be
4760  *	the way it ought to be
4761  * ASSUMES: that it already owns the csb/fdctlr!
4762  *
4763  *	- called with the low level lock held
4764  */
4765 static int
4766 fdreset(struct fdctlr *fdc)
4767 {
4768 	struct fdcsb *csb;
4769 	clock_t local_lbolt = 0;
4770 	timeout_id_t timeid;
4771 
4772 	FDERRPRINT(FDEP_L1, FDEM_RESE, (C, "fdreset\n"));
4773 
4774 	ASSERT(mutex_owned(&fdc->c_lolock));
4775 
4776 	/* count resets */
4777 	fdc->fdstats.reset++;
4778 
4779 	/*
4780 	 * On the 82077, the DSR will clear itself after a reset.  Upon exiting
4781 	 * the reset, a polling interrupt will be generated.  If the floppy
4782 	 * interrupt is enabled, it's possible for cv_signal() to be called
4783 	 * before cv_wait().  This will cause the system to hang.  Turn off
4784 	 * the floppy interrupt to avoid this race condition
4785 	 */
4786 	if ((fdc->c_fdtype & FDCTYPE_CTRLMASK) == FDCTYPE_82077) {
4787 		/*
4788 		 * We need to perform any timeouts before we Reset the
4789 		 * controller. We cannot afford to drop the c_lolock mutex after
4790 		 * Resetting the controller. The reason is that we get a spate
4791 		 * of interrupts until we take the controller out of reset.
4792 		 * The way we avoid this spate of continuous interrupts is by
4793 		 * holding on to the c_lolock and forcing the fdintr_dma routine
4794 		 * to go to sleep waiting for this mutex.
4795 		 */
4796 		/* Do not hold the mutex across the untimeout call */
4797 		timeid = fdc->c_mtimeid;
4798 		fdc->c_mtimeid = 0;
4799 		if (timeid) {
4800 			mutex_exit(&fdc->c_lolock);
4801 			(void) untimeout(timeid);
4802 			mutex_enter(&fdc->c_lolock);
4803 		}
4804 		/* LINTED */
4805 		Set_dor(fdc, DMAGATE, 0);
4806 		FDERRPRINT(FDEP_L1, FDEM_RESE, (C, "fdreset: set dor\n"));
4807 	}
4808 
4809 	/* toggle software reset */
4810 	Dsr(fdc, SWR);
4811 
4812 	drv_usecwait(5);
4813 
4814 	FDERRPRINT(FDEP_L1, FDEM_RESE,
4815 	    (C, "fdreset: toggled software reset\n"));
4816 
4817 	/*
4818 	 * This sets the data rate to 500Kbps (for high density)
4819 	 * XXX should use current characteristics instead XXX
4820 	 */
4821 	Dsr(fdc, 0);
4822 	drv_usecwait(5);
4823 	switch (fdc->c_fdtype & FDCTYPE_CTRLMASK) {
4824 	case FDCTYPE_82077:
4825 		/*
4826 		 * when we bring the controller out of reset it will generate
4827 		 * a polling interrupt. fdintr() will field it and schedule
4828 		 * fd_lointr(). There will be no one sleeping but we are
4829 		 * expecting an interrupt so....
4830 		 */
4831 		fdc->c_flags |= FDCFLG_WAITING;
4832 
4833 		/*
4834 		 * The reset bit must be cleared to take the 077 out of
4835 		 * reset state and the DMAGATE bit must be high to enable
4836 		 * interrupts.
4837 		 */
4838 		/* LINTED */
4839 		Set_dor(fdc, DMAGATE|RESET, 1);
4840 
4841 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
4842 		    (C, "fdattach: Dor 0x%x\n", Dor(fdc)));
4843 
4844 		local_lbolt = ddi_get_lbolt();
4845 		if (cv_timedwait(&fdc->c_iocv, &fdc->c_lolock,
4846 		    local_lbolt + drv_usectohz(1000000)) == -1) {
4847 			return (-1);
4848 		}
4849 		break;
4850 
4851 	default:
4852 		fdc->c_flags |= FDCFLG_WAITING;
4853 
4854 		/*
4855 		 * A timed wait is not used because it's possible for the timer
4856 		 * to go off before the controller has a chance to interrupt.
4857 		 */
4858 		cv_wait(&fdc->c_iocv, &fdc->c_lolock);
4859 		break;
4860 	}
4861 	csb = &fdc->c_csb;
4862 
4863 	/* setup common things in csb */
4864 	csb->csb_unit = fdc->c_un->un_unit_no;
4865 	csb->csb_nrslts = 0;
4866 	csb->csb_opflags = CSB_OFNORESULTS;
4867 	csb->csb_maxretry = 0;
4868 	csb->csb_retrys = 0;
4869 
4870 	csb->csb_read = CSB_NULL;
4871 
4872 	/* send SPECIFY command to fdc */
4873 	/* csb->unit is don't care */
4874 	csb->csb_cmds[0] = FDRAW_SPECIFY;
4875 	csb->csb_cmds[1] = fdspec[0]; /* step rate, head unload time */
4876 	if (fdc->c_fdtype & FDCTYPE_DMA)
4877 		csb->csb_cmds[2] =  SPEC_DMA_MODE;
4878 	else
4879 		csb->csb_cmds[2] = fdspec[1];  /* head load time, DMA mode */
4880 
4881 	csb->csb_ncmds = 3;
4882 
4883 	/* XXX for now ignore errors, they "CAN'T HAPPEN" */
4884 	(void) fdexec(fdc, 0);	/* no FDXC_CHECKCHG, ... */
4885 	/* no results */
4886 
4887 	/* send CONFIGURE command to fdc */
4888 	/* csb->unit is don't care */
4889 	csb->csb_cmds[0] = CONFIGURE;
4890 	csb->csb_cmds[1] = fdconf[0]; /* motor info, motor delays */
4891 	csb->csb_cmds[2] = fdconf[1]; /* enaimplsk, disapoll, fifothru */
4892 	csb->csb_cmds[3] = fdconf[2]; /* track precomp */
4893 	csb->csb_ncmds = 4;
4894 
4895 	csb->csb_read = CSB_NULL;
4896 
4897 	csb->csb_retrys = 0;
4898 
4899 	/* XXX for now ignore errors, they "CAN'T HAPPEN" */
4900 	(void) fdexec(fdc, 0); /* no FDXC_CHECKCHG, ... */
4901 	return (0);
4902 }
4903 
4904 /*
4905  * fdrecalseek
4906  *	performs recalibrates or seeks if the "arg" is -1 does a
4907  *	recalibrate on a drive, else it seeks to the cylinder of
4908  *	the drive.  The recalibrate is also used to find a drive,
4909  *	ie if the drive is not there, the controller says "error"
4910  *	on the operation
4911  * NOTE: that there is special handling of this operation in the hardware
4912  * interrupt routine - it causes the operation to appear to have results;
4913  * ie the results of the SENSE INTERRUPT STATUS that the hardware interrupt
4914  * function did for us.
4915  * NOTE: because it uses sleep/wakeup it must be protected in a critical
4916  * section so create one before calling it!
4917  *
4918  * RETURNS: 0 for ok,
4919  *	else	errno from fdexec,
4920  *	or	ENODEV if error (infers hardware type error)
4921  *
4922  *	- called with the low level lock held
4923  */
4924 static int
4925 fdrecalseek(struct fdctlr *fdc, int unit, int arg, int execflg)
4926 {
4927 	struct fdcsb *csb;
4928 	int result;
4929 
4930 	ASSERT(fdc->c_un->un_unit_no == unit);
4931 
4932 	FDERRPRINT(FDEP_L1, FDEM_RECA, (C, "fdrecalseek to %d\n", arg));
4933 
4934 	/* XXX TODO: check see argument for <= num cyls OR < 256 */
4935 
4936 	csb = &fdc->c_csb;
4937 	csb->csb_unit = (uchar_t)unit;
4938 	csb->csb_cmds[1] = unit & 0x03;
4939 
4940 	if (arg == -1) {			/* is recal... */
4941 		csb->csb_cmds[0] = FDRAW_REZERO;
4942 		csb->csb_ncmds = 2;
4943 	} else {
4944 		csb->csb_cmds[0] = FDRAW_SEEK;
4945 		csb->csb_cmds[2] = (uchar_t)arg;
4946 		csb->csb_ncmds = 3;
4947 	}
4948 	csb->csb_nrslts = 2;	/* 2 for SENSE INTERRUPTS */
4949 	csb->csb_opflags = CSB_OFSEEKOPS | CSB_OFTIMEIT;
4950 	/*
4951 	 * MAYBE NYD need to set retries to different values? - depending on
4952 	 * drive characteristics - if we get to high capacity drives
4953 	 */
4954 	csb->csb_maxretry = skretry;
4955 	csb->csb_retrys = 0;
4956 
4957 	/* send cmd off to fdexec */
4958 	if (result = fdexec(fdc, FDXC_SLEEP | execflg)) {
4959 		goto out;
4960 	}
4961 
4962 	/*
4963 	 * if recal, test for equipment check error
4964 	 * ASSUMES result = 0 from above call
4965 	 */
4966 	if (arg == -1) {
4967 		result = 0;
4968 	} else {
4969 		/* for seeks, any old error will do */
4970 		if ((csb->csb_rslt[0] & IC_SR0) || csb->csb_cmdstat)
4971 			result = ENODEV;
4972 	}
4973 
4974 out:
4975 	return (result);
4976 }
4977 
4978 /*
4979  * fdsensedrv
4980  *	do a sense_drive command.  used by fdopen and fdcheckdisk.
4981  *
4982  *	- called with the lock held
4983  */
4984 static int
4985 fdsensedrv(struct fdctlr *fdc, int unit)
4986 {
4987 	struct fdcsb *csb;
4988 
4989 	ASSERT(fdc->c_un->un_unit_no == unit);
4990 
4991 	csb = &fdc->c_csb;
4992 
4993 	/* setup common things in csb */
4994 	csb->csb_unit = (uchar_t)unit;
4995 	csb->csb_opflags = CSB_OFIMMEDIATE;
4996 	csb->csb_cmds[0] = FDRAW_SENSE_DRV;
4997 	/* MOT bit set means don't delay */
4998 	csb->csb_cmds[1] = MOT | (unit & 0x03);
4999 	csb->csb_ncmds = 2;
5000 	csb->csb_nrslts = 1;
5001 	csb->csb_maxretry = skretry;
5002 	csb->csb_retrys = 0;
5003 
5004 	/* XXX for now ignore errors, they "CAN'T HAPPEN" */
5005 	(void) fdexec(fdc, 0);	/* DON't check changed!, no sleep */
5006 
5007 	FDERRPRINT(FDEP_L1, FDEM_CHEK,
5008 	    (C, "fdsensedrv: result 0x%x", csb->csb_rslt[0]));
5009 
5010 	return (csb->csb_rslt[0]); /* return status byte 3 */
5011 }
5012 
5013 /*
5014  * fdcheckdisk
5015  *	check to see if the disk is still there - do a recalibrate,
5016  *	then see if DSKCHG line went away, if so, diskette is in; else
5017  *	it's (still) out.
5018  */
5019 
5020 static int
5021 fdcheckdisk(struct fdctlr *fdc, int unit)
5022 {
5023 	auto struct fdcsb savecsb;
5024 	struct fdcsb *csb;
5025 	int	err, st3;
5026 	int	seekto;			/* where to seek for reset of DSKCHG */
5027 
5028 	FDERRPRINT(FDEP_L1, FDEM_CHEK,
5029 	    (C, "fdcheckdisk, unit %d\n", unit));
5030 
5031 	ASSERT(fdc->c_un->un_unit_no == unit);
5032 
5033 	/*
5034 	 * save old csb
5035 	 */
5036 
5037 	csb = &fdc->c_csb;
5038 	savecsb = fdc->c_csb;
5039 	bzero((caddr_t)csb, sizeof (*csb));
5040 
5041 	/*
5042 	 * Read drive status to see if at TRK0, if so, seek to cyl 1,
5043 	 * else seek to cyl 0.	We do this because the controller is
5044 	 * "smart" enough to not send any step pulses (which are how
5045 	 * the DSKCHG line gets reset) if it sees TRK0 'cause it
5046 	 * knows the drive is already recalibrated.
5047 	 */
5048 	st3 = fdsensedrv(fdc, unit);
5049 
5050 	/* check TRK0 bit in status */
5051 	if (st3 & T0_SR3)
5052 		seekto = 1;	/* at TRK0, seek out */
5053 	else
5054 		seekto = 0;
5055 
5056 	/*
5057 	 * DON'T recurse check changed
5058 	 */
5059 	err = fdrecalseek(fdc, unit, seekto, 0);
5060 
5061 	/* "restore" old csb, check change state */
5062 	fdc->c_csb = savecsb;
5063 
5064 	/* any recal/seek errors are too serious to attend to */
5065 	if (err) {
5066 		FDERRPRINT(FDEP_L2, FDEM_CHEK,
5067 		    (C, "fdcheckdisk err %d\n", err));
5068 		return (err);
5069 	}
5070 
5071 	/*
5072 	 * if disk change still asserted, no diskette in drive!
5073 	 */
5074 	if (fdsense_chng(fdc, csb->csb_unit)) {
5075 		FDERRPRINT(FDEP_L2, FDEM_CHEK,
5076 		    (C, "fdcheckdisk no disk\n"));
5077 		return (1);
5078 	}
5079 	return (0);
5080 }
5081 
5082 /*
5083  *	fdselect() - select drive, needed for external to chip select logic
5084  *	fdeject() - ejects drive, must be previously selected
5085  *	fdsense_chng() - sense disk changed line from previously selected drive
5086  *		return s 1 is signal asserted, else 0
5087  */
5088 /* ARGSUSED */
5089 static void
5090 fdselect(struct fdctlr *fdc, int unit, int on)
5091 {
5092 
5093 	ASSERT(fdc->c_un->un_unit_no == unit);
5094 
5095 	FDERRPRINT(FDEP_L1, FDEM_DSEL,
5096 	    (C, "fdselect, unit %d, on = %d\n", unit, on));
5097 
5098 	switch (fdc->c_fdtype & FDCTYPE_AUXIOMASK) {
5099 	case FDCTYPE_MACHIO:
5100 		set_auxioreg(AUX_DRVSELECT, on);
5101 		break;
5102 
5103 	case FDCTYPE_SLAVIO:
5104 	case FDCTYPE_CHEERIO:
5105 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
5106 		    (C, "fdselect: (before) Dor 0x%x\n", Dor(fdc)));
5107 
5108 		if (unit == 0) {
5109 			Set_dor(fdc, DRVSEL, !on);
5110 		} else {
5111 			Set_dor(fdc, DRVSEL, on);
5112 		}
5113 
5114 		FDERRPRINT(FDEP_L1, FDEM_ATTA,
5115 		    (C, "fdselect: Dor 0x%x\n", Dor(fdc)));
5116 
5117 		break;
5118 
5119 	default:
5120 		break;
5121 	}
5122 }
5123 
5124 /* ARGSUSED */
5125 static void
5126 fdeject(struct fdctlr *fdc, int unit)
5127 {
5128 	struct fdunit *un;
5129 
5130 	ASSERT(fdc->c_un->un_unit_no == unit);
5131 
5132 	un = fdc->c_un;
5133 
5134 	FDERRPRINT(FDEP_L1, FDEM_EJEC, (C, "fdeject\n"));
5135 	/*
5136 	 * assume delay of function calling sufficient settling time
5137 	 * eject line is NOT driven by inverter so it is true low
5138 	 */
5139 	switch (fdc->c_fdtype & FDCTYPE_AUXIOMASK) {
5140 	case FDCTYPE_MACHIO:
5141 		set_auxioreg(AUX_EJECT, 0);
5142 		drv_usecwait(2);
5143 		set_auxioreg(AUX_EJECT, 1);
5144 		break;
5145 
5146 	case FDCTYPE_SLAVIO:
5147 		if (!(Dor(fdc) & MOTEN(unit))) {
5148 			/* LINTED */
5149 			Set_dor(fdc, MOTEN(unit), 1);
5150 		}
5151 		drv_usecwait(2);	/* just to settle */
5152 		/* LINTED */
5153 		Set_dor(fdc, EJECT, 1);
5154 		drv_usecwait(2);
5155 		/* LINTED */
5156 		Set_dor(fdc, EJECT, 0);
5157 		break;
5158 	case FDCTYPE_CHEERIO:
5159 		if (!(Dor(fdc) & MOTEN(unit))) {
5160 			/* LINTED */
5161 			Set_dor(fdc, MOTEN(unit), 1);
5162 		}
5163 		drv_usecwait(2);	/* just to settle */
5164 		/* LINTED */
5165 		Set_dor(fdc, EJECT_DMA, 1);
5166 		drv_usecwait(2);
5167 		/* LINTED */
5168 		Set_dor(fdc, EJECT_DMA, 0);
5169 		break;
5170 	}
5171 	/*
5172 	 * XXX set ejected state?
5173 	 */
5174 	un->un_ejected = 1;
5175 }
5176 
5177 /* ARGSUSED */
5178 static int
5179 fdsense_chng(struct fdctlr *fdc, int unit)
5180 {
5181 	int changed = 0;
5182 
5183 	FDERRPRINT(FDEP_L1, FDEM_SCHG, (C, "fdsense_chng:start\n"));
5184 
5185 	ASSERT(fdc->c_un->un_unit_no == unit);
5186 
5187 	/*
5188 	 * Do not turn on the motor of a pollable drive
5189 	 */
5190 	if (fd_pollable) {
5191 	FDERRPRINT(FDEP_L1, FDEM_SCHG, (C, "pollable: don't turn on motor\n"));
5192 		/*
5193 		 * Invert the sense of the DSKCHG for pollable drives
5194 		 */
5195 		if (Dir(fdc) & DSKCHG)
5196 			changed = 0;
5197 		else
5198 			changed = 1;
5199 
5200 		return (changed);
5201 	}
5202 
5203 	switch (fdc->c_fdtype & FDCTYPE_AUXIOMASK) {
5204 	case FDCTYPE_MACHIO:
5205 		if (*fdc->c_auxiova & AUX_DISKCHG)
5206 			changed = 1;
5207 		break;
5208 
5209 	case FDCTYPE_SB:
5210 	case FDCTYPE_SLAVIO:
5211 	case FDCTYPE_CHEERIO:
5212 		if (!(Dor(fdc) & MOTEN(unit))) {
5213 			/* LINTED */
5214 			Set_dor(fdc, MOTEN(unit), 1);
5215 		}
5216 		drv_usecwait(2);	/* just to settle */
5217 		if (Dir(fdc) & DSKCHG)
5218 			changed = 1;
5219 		break;
5220 	}
5221 
5222 	FDERRPRINT(FDEP_L1, FDEM_SCHG, (C, "fdsense_chng:end\n"));
5223 
5224 	return (changed);
5225 }
5226 
5227 /*
5228  *	if it can read a valid label it does so, else it will use a
5229  *	default.  If it can`t read the diskette - that is an error.
5230  *
5231  * RETURNS: 0 for ok - meaning that it could at least read the device,
5232  *	!0 for error XXX TBD NYD error codes
5233  *
5234  *	- called with the low level lock held
5235  */
5236 static int
5237 fdgetlabel(struct fdctlr *fdc, int unit)
5238 {
5239 	struct dk_label *label = NULL;
5240 	struct fdunit *un;
5241 	short *sp;
5242 	short count;
5243 	short xsum;			/* checksum */
5244 	int	i, tries;
5245 	int	err = 0;
5246 	short	oldlvl;
5247 
5248 	FDERRPRINT(FDEP_L1, FDEM_GETL,
5249 	    (C, "fdgetlabel: unit %d\n", unit));
5250 
5251 	un = fdc->c_un;
5252 	un->un_flags &= ~(FDUNIT_UNLABELED);
5253 
5254 	ASSERT(fdc->c_un->un_unit_no == unit);
5255 
5256 	/* Do not print errors since this is a private cmd */
5257 
5258 	oldlvl = fderrlevel;
5259 
5260 
5261 	fderrlevel = FDEP_L4;
5262 
5263 	label = (struct dk_label *)
5264 	    kmem_zalloc(sizeof (struct dk_label), KM_SLEEP);
5265 
5266 	/*
5267 	 * try different characteristics (ie densities) by attempting to read
5268 	 * from the diskette.  The diskette may not be present or
5269 	 * is unformatted.
5270 	 *
5271 	 * First, the last sector of the first track is read.  If this
5272 	 * passes, attempt to read the last sector + 1 of the first track.
5273 	 * For example, for a high density diskette, sector 18 is read.  If
5274 	 * the diskette is high density, this will pass.  Next, try to
5275 	 * read sector 19 of the first track.  This should fail.  If it
5276 	 * passes, this is not a high density diskette.  Finally, read
5277 	 * the first sector which should contain a label.
5278 	 *
5279 	 * if un->un_curfdtype is -1 then the current characteristics
5280 	 * were set by FDIOSCHAR and need to try it as well as everything
5281 	 * in the table
5282 	 */
5283 	if (un->un_curfdtype == -1) {
5284 		tries = nfdtypes+1;
5285 		FDERRPRINT(FDEP_L1, FDEM_GETL,
5286 		    (C, "fdgetl: un_curfdtype is -1\n"));
5287 
5288 	} else {
5289 		tries = nfdtypes;
5290 
5291 		/* Always start with the highest density (1.7MB) */
5292 		un->un_curfdtype = 0;
5293 		*(un->un_chars) = fdtypes[un->un_curfdtype];
5294 	}
5295 
5296 	FDERRPRINT(FDEP_L1, FDEM_GETL,
5297 	    (C, "fdgetl: no. of tries %d\n", tries));
5298 	FDERRPRINT(FDEP_L1, FDEM_GETL,
5299 	    (C, "fdgetl: no. of curfdtype %d\n", un->un_curfdtype));
5300 
5301 	for (i = 0; i < tries; i++) {
5302 		FDERRPRINT(FDEP_L1, FDEM_GETL,
5303 		    (C, "fdgetl: trying %d\n", i));
5304 
5305 		if (!(err = fdrw(fdc, unit, FDREAD, 0, 0,
5306 		    un->un_chars->fdc_secptrack, (caddr_t)label,
5307 		    sizeof (struct dk_label))) &&
5308 
5309 		    fdrw(fdc, unit, FDREAD, 0, 0,
5310 		    un->un_chars->fdc_secptrack + 1,
5311 		    (caddr_t)label, sizeof (struct dk_label)) &&
5312 
5313 		    !(err = fdrw(fdc, unit, FDREAD, 0, 0, 1, (caddr_t)label,
5314 		    sizeof (struct dk_label)))) {
5315 
5316 			FDERRPRINT(FDEP_L1, FDEM_GETL,
5317 				(C, "fdgetl: succeeded\n"));
5318 
5319 			break;
5320 		}
5321 
5322 		/*
5323 		 * try the next entry in the characteristics tbl
5324 		 * If curfdtype is -1, the nxt entry in tbl is 0 (the first).
5325 		 */
5326 
5327 		un->un_curfdtype = (un->un_curfdtype + 1) % nfdtypes;
5328 		*(un->un_chars) = fdtypes[un->un_curfdtype];
5329 
5330 
5331 	}
5332 
5333 	/* print errors again */
5334 	fderrlevel = oldlvl;
5335 
5336 	/* Couldn't read anything */
5337 	if (err) {
5338 
5339 		/* The default characteristics are high density (1.4MB) */
5340 		un->un_curfdtype = 1;
5341 		*(un->un_chars) = fdtypes[un->un_curfdtype];
5342 
5343 		fdunpacklabel(&fdlbl_high_80, &un->un_label);
5344 
5345 		FDERRPRINT(FDEP_L1, FDEM_GETL,
5346 		    (C, "fdgetl: Can't autosense diskette\n"));
5347 
5348 		goto out;
5349 	}
5350 
5351 	FDERRPRINT(FDEP_L1, FDEM_GETL,
5352 	    (C, "fdgetl: fdtype=%d !!!\n", un->un_curfdtype));
5353 	FDERRPRINT(FDEP_L1, FDEM_GETL,
5354 	    (C, "fdgetl: rate=%d ssize=%d !!!\n",
5355 	    un->un_chars->fdc_transfer_rate, un->un_chars->fdc_sec_size));
5356 
5357 	/*
5358 	 * _something_ was read	 -  look for unixtype label
5359 	 */
5360 	if (label->dkl_magic != DKL_MAGIC) {
5361 
5362 		/*
5363 		 * The label isn't a unix label.  However, the diskette
5364 		 * is formatted because we were able to read the first
5365 		 * cylinder.
5366 		 */
5367 
5368 		FDERRPRINT(FDEP_L1, FDEM_GETL,
5369 		    (C, "fdgetl: not unix label\n"));
5370 
5371 		goto nolabel;
5372 	}
5373 
5374 	/*
5375 	 * Checksum the label
5376 	 */
5377 	count = sizeof (struct dk_label)/sizeof (short);
5378 	sp = (short *)label;
5379 	xsum = 0;
5380 	while (count--)
5381 		xsum ^= *sp++;	/* should add up to 0 */
5382 	if (xsum) {
5383 
5384 		/*
5385 		 * The checksum fails.  However, the diskette is formatted
5386 		 * because we were able to read the first cylinder
5387 		 */
5388 
5389 		FDERRPRINT(FDEP_L1, FDEM_GETL,
5390 		    (C, "fdgetl: bad cksum\n"));
5391 
5392 		goto nolabel;
5393 	}
5394 
5395 	/*
5396 	 * The diskette has a unix label with a correct checksum.
5397 	 * Copy the label into the unit structure
5398 	 */
5399 	un->un_label = *label;
5400 
5401 	goto out;
5402 
5403 nolabel:
5404 	/*
5405 	 * The diskette doesn't have a correct unix label, but it is formatted.
5406 	 * Use a default label according to the diskette's density
5407 	 * (mark default used)
5408 	 */
5409 	FDERRPRINT(FDEP_L1, FDEM_GETL,
5410 	    (C, "fdgetlabel: unit %d\n", unit));
5411 	un->un_flags |= FDUNIT_UNLABELED;
5412 	switch (un->un_chars->fdc_secptrack) {
5413 	case 9:
5414 		fdunpacklabel(&fdlbl_low_80, &un->un_label);
5415 		break;
5416 	case 8:
5417 		fdunpacklabel(&fdlbl_medium_80, &un->un_label);
5418 		break;
5419 	case 18:
5420 		fdunpacklabel(&fdlbl_high_80, &un->un_label);
5421 		break;
5422 	case 21:
5423 		fdunpacklabel(&fdlbl_high_21, &un->un_label);
5424 		break;
5425 	default:
5426 		fdunpacklabel(&fdlbl_high_80, &un->un_label);
5427 		break;
5428 	}
5429 
5430 out:
5431 	if (label != NULL)
5432 		kmem_free((caddr_t)label, sizeof (struct dk_label));
5433 	return (err);
5434 }
5435 
5436 /*
5437  * fdrw- used only for reading labels  and for DKIOCSVTOC ioctl
5438  *	 which reads the 1 sector.
5439  */
5440 static int
5441 fdrw(struct fdctlr *fdc, int unit, int rw, int cyl, int head,
5442     int sector, caddr_t bufp, uint_t len)
5443 {
5444 	struct fdcsb *csb;
5445 	struct	fd_char *ch;
5446 	int	cmdresult = 0;
5447 	caddr_t dma_addr;
5448 	size_t	real_length;
5449 	int	res;
5450 	ddi_device_acc_attr_t attr;
5451 	ddi_acc_handle_t	mem_handle = NULL;
5452 
5453 	FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fdrw\n"));
5454 
5455 	ASSERT(fdc->c_un->un_unit_no == unit);
5456 
5457 	CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc);
5458 
5459 	if (fdc->c_un->un_state == FD_STATE_STOPPED) {
5460 		mutex_exit(&fdc->c_lolock);
5461 		if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON))
5462 		    != DDI_SUCCESS) {
5463 			FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power change \
5464 			    failed. \n"));
5465 			mutex_enter(&fdc->c_lolock);
5466 			return (EIO);
5467 		}
5468 
5469 		mutex_enter(&fdc->c_lolock);
5470 	}
5471 
5472 	fdgetcsb(fdc);
5473 	csb = &fdc->c_csb;
5474 	ch = fdc->c_un->un_chars;
5475 	if (rw == FDREAD) {
5476 		if (fdc->c_fdtype & FDCTYPE_TCBUG) {
5477 			/*
5478 			 * kludge for lack of Multitrack functionality
5479 			 */
5480 			csb->csb_cmds[0] = SK + FDRAW_RDCMD;
5481 		} else
5482 			csb->csb_cmds[0] = MT + SK + FDRAW_RDCMD;
5483 	} else { /* write */
5484 		if (fdc->c_fdtype & FDCTYPE_TCBUG) {
5485 			/*
5486 			 * kludge for lack of Multitrack functionality
5487 			 */
5488 			csb->csb_cmds[0] = FDRAW_WRCMD;
5489 		} else
5490 			csb->csb_cmds[0] = MT + FDRAW_WRCMD;
5491 	}
5492 
5493 	if (rw == FDREAD)
5494 		fdc->c_csb.csb_read = CSB_READ;
5495 	else
5496 		fdc->c_csb.csb_read = CSB_WRITE;
5497 
5498 	/* always or in MFM bit */
5499 	csb->csb_cmds[0] |= MFM;
5500 	csb->csb_cmds[1] = (uchar_t)(unit | ((head & 0x1) << 2));
5501 	if (fdc->c_fdtype & FDCTYPE_SB)
5502 		csb->csb_cmds[1] |= IPS;
5503 	csb->csb_cmds[2] = (uchar_t)cyl;
5504 	csb->csb_cmds[3] = (uchar_t)head;
5505 	csb->csb_cmds[4] = (uchar_t)sector;
5506 	csb->csb_cmds[5] = ch->fdc_medium ? 3 : 2; /* sector size code */
5507 	/*
5508 	 * kludge for end-of-cylinder error.
5509 	 */
5510 	if (fdc->c_fdtype & FDCTYPE_TCBUG)
5511 		csb->csb_cmds[6] = sector + (len / ch->fdc_sec_size) - 1;
5512 	else
5513 		csb->csb_cmds[6] =
5514 		    (uchar_t)max(fdc->c_un->un_chars->fdc_secptrack, sector);
5515 	csb->csb_len = len;
5516 	csb->csb_cmds[7] = GPLN;
5517 	csb->csb_cmds[8] = SSSDTL;
5518 	csb->csb_ncmds = NCBRW;
5519 	csb->csb_len = len;
5520 	csb->csb_maxretry = 2;
5521 	csb->csb_retrys = 0;
5522 	bzero(csb->csb_rslt, NRBRW);
5523 	csb->csb_nrslts = NRBRW;
5524 	csb->csb_opflags = CSB_OFXFEROPS | CSB_OFTIMEIT;
5525 
5526 	/* If platform supports DMA, set up DMA resources */
5527 	if (fdc->c_fdtype & FDCTYPE_DMA) {
5528 
5529 		mutex_enter(&fdc->c_hilock);
5530 
5531 		attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
5532 		attr.devacc_attr_endian_flags  = DDI_STRUCTURE_BE_ACC;
5533 		attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
5534 
5535 		res = ddi_dma_mem_alloc(fdc->c_dmahandle, len,
5536 		    &attr, DDI_DMA_STREAMING,
5537 		    DDI_DMA_DONTWAIT, 0, &dma_addr, &real_length,
5538 		    &mem_handle);
5539 
5540 		if (res != DDI_SUCCESS) {
5541 			FDERRPRINT(FDEP_L1, FDEM_RW,
5542 			    (C, "fdrw: dma mem alloc failed\n"));
5543 
5544 			fdretcsb(fdc);
5545 			mutex_exit(&fdc->c_hilock);
5546 			return (EIO);
5547 		}
5548 
5549 		FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fdrw: allocated memory"));
5550 
5551 		if (fdstart_dma(fdc, dma_addr, len) != 0) {
5552 			fdretcsb(fdc);
5553 			ddi_dma_mem_free(&mem_handle);
5554 			mutex_exit(&fdc->c_hilock);
5555 			return (-1);
5556 
5557 		}
5558 
5559 		/*
5560 		 * If the command is a write, copy the data to be written to
5561 		 * dma_addr.
5562 		 */
5563 
5564 		if (fdc->c_csb.csb_read == CSB_WRITE) {
5565 			bcopy((char *)bufp, (char *)dma_addr, len);
5566 		}
5567 
5568 		csb->csb_addr = dma_addr;
5569 		mutex_exit(&fdc->c_hilock);
5570 	} else {
5571 		csb->csb_addr = bufp;
5572 	}
5573 
5574 
5575 	FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fdrw: call fdexec\n"));
5576 
5577 	if (fdexec(fdc, FDXC_SLEEP | FDXC_CHECKCHG) != 0) {
5578 		fdretcsb(fdc);
5579 
5580 		if (mem_handle)
5581 			ddi_dma_mem_free(&mem_handle);
5582 
5583 		return (EIO);
5584 
5585 	}
5586 
5587 	FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fdrw: fdexec returned\n"));
5588 
5589 	/*
5590 	 * if DMA was used and the command was a read
5591 	 * copy the results into bufp
5592 	 */
5593 	if (fdc->c_fdtype & FDCTYPE_DMA) {
5594 		if (fdc->c_csb.csb_read == CSB_READ) {
5595 			bcopy((char *)dma_addr, (char *)bufp, len);
5596 		}
5597 		ddi_dma_mem_free(&mem_handle);
5598 	}
5599 
5600 	if (csb->csb_cmdstat)
5601 		cmdresult = EIO;	/* XXX TBD NYD for now */
5602 
5603 	fdretcsb(fdc);
5604 	return (cmdresult);
5605 }
5606 
5607 /*
5608  * fdunpacklabel
5609  *	this unpacks a (packed) struct dk_label into a standard dk_label.
5610  */
5611 static void
5612 fdunpacklabel(struct packed_label *from, struct dk_label *to)
5613 {
5614 	FDERRPRINT(FDEP_L1, FDEM_PACK, (C, "fdpacklabel\n"));
5615 	bzero((caddr_t)to, sizeof (*to));
5616 	bcopy((caddr_t)&from->dkl_vname, (caddr_t)to->dkl_asciilabel,
5617 	    sizeof (to->dkl_asciilabel));
5618 	to->dkl_rpm = from->dkl_rpm;	/* rotations per minute */
5619 	to->dkl_pcyl = from->dkl_pcyl;	/* # physical cylinders */
5620 	to->dkl_apc = from->dkl_apc;	/* alternates per cylinder */
5621 	to->dkl_intrlv = from->dkl_intrlv;	/* interleave factor */
5622 	to->dkl_ncyl = from->dkl_ncyl;	/* # of data cylinders */
5623 	to->dkl_acyl = from->dkl_acyl;	/* # of alternate cylinders */
5624 	to->dkl_nhead = from->dkl_nhead; /* # of heads in this partition */
5625 	to->dkl_nsect = from->dkl_nsect; /* # of 512 byte sectors per track */
5626 	/* logical partitions */
5627 	bcopy((caddr_t)from->dkl_map, (caddr_t)to->dkl_map,
5628 	    sizeof (struct dk_map32) * NDKMAP);
5629 	to->dkl_vtoc = from->dkl_vtoc;
5630 }
5631 
5632 static struct fdctlr *
5633 fd_getctlr(dev_t dev)
5634 {
5635 
5636 	struct fdctlr *fdc = fdctlrs;
5637 	int ctlr = FDCTLR(dev);
5638 
5639 	while (fdc) {
5640 		if (ddi_get_instance(fdc->c_dip) == ctlr)
5641 			return (fdc);
5642 		fdc = fdc->c_next;
5643 	}
5644 	return (fdc);
5645 }
5646 
5647 static int
5648 fd_unit_is_open(struct fdunit *un)
5649 {
5650 	int i;
5651 	for (i = 0; i < NDKMAP; i++)
5652 		if (un->un_lyropen[i])
5653 			return (1);
5654 	for (i = 0; i < OTYPCNT - 1; i++)
5655 		if (un->un_regopen[i])
5656 			return (1);
5657 	return (0);
5658 }
5659 
5660 /*
5661  * Return the a vtoc structure in *vtoc.
5662  * The vtoc is built from information in
5663  * the diskette's label.
5664  */
5665 static void
5666 fd_build_user_vtoc(struct fdunit *un, struct vtoc *vtoc)
5667 {
5668 	int i;
5669 	int nblks;			/* DEV_BSIZE sectors per cylinder */
5670 	struct dk_map2 *lpart;
5671 	struct dk_map32	*lmap;
5672 	struct partition *vpart;
5673 
5674 	bzero(vtoc, sizeof (struct vtoc));
5675 
5676 	/* Initialize info. needed by mboot.  (unsupported) */
5677 	vtoc->v_bootinfo[0] = un->un_label.dkl_vtoc.v_bootinfo[0];
5678 	vtoc->v_bootinfo[1] = un->un_label.dkl_vtoc.v_bootinfo[1];
5679 	vtoc->v_bootinfo[2] = un->un_label.dkl_vtoc.v_bootinfo[2];
5680 
5681 	/* Fill in vtoc sanity and version information */
5682 	vtoc->v_sanity		= un->un_label.dkl_vtoc.v_sanity;
5683 	vtoc->v_version		= un->un_label.dkl_vtoc.v_version;
5684 
5685 	/* Copy the volume name */
5686 	bcopy(un->un_label.dkl_vtoc.v_volume,
5687 	    vtoc->v_volume, LEN_DKL_VVOL);
5688 
5689 	/*
5690 	 * The dk_map32 structure is based on DEV_BSIZE byte blocks.
5691 	 * However, medium density diskettes have 1024 byte blocks.
5692 	 * The number of sectors per partition listed in the dk_map32 structure
5693 	 * accounts for this by multiplying the number of 1024 byte
5694 	 * blocks by 2.  (See the packed_label initializations.)  The
5695 	 * 1024 byte block size can not be listed for medium density
5696 	 * diskettes because the kernel is hard coded for DEV_BSIZE
5697 	 * blocks.
5698 	 */
5699 	vtoc->v_sectorsz = DEV_BSIZE;
5700 	vtoc->v_nparts = un->un_label.dkl_vtoc.v_nparts;
5701 
5702 	/* Copy the reserved space */
5703 	bcopy(un->un_label.dkl_vtoc.v_reserved,
5704 	    vtoc->v_reserved, sizeof (un->un_label.dkl_vtoc.v_reserved));
5705 	/*
5706 	 * Convert partitioning information.
5707 	 *
5708 	 * Note the conversion from starting cylinder number
5709 	 * to starting sector number.
5710 	 */
5711 	lmap = un->un_label.dkl_map;
5712 	lpart = un->un_label.dkl_vtoc.v_part;
5713 	vpart = vtoc->v_part;
5714 
5715 	nblks = (un->un_chars->fdc_nhead * un->un_chars->fdc_secptrack *
5716 	    un->un_chars->fdc_sec_size) / DEV_BSIZE;
5717 
5718 	for (i = 0; i < V_NUMPAR; i++) {
5719 		vpart->p_tag	= lpart->p_tag;
5720 		vpart->p_flag	= lpart->p_flag;
5721 		vpart->p_start	= lmap->dkl_cylno * nblks;
5722 		vpart->p_size	= lmap->dkl_nblk;
5723 
5724 		lmap++;
5725 		lpart++;
5726 		vpart++;
5727 	}
5728 
5729 	/* Initialize timestamp and label */
5730 	bcopy(un->un_label.dkl_vtoc.v_timestamp,
5731 	    vtoc->timestamp, sizeof (vtoc->timestamp));
5732 
5733 	bcopy(un->un_label.dkl_asciilabel,
5734 	    vtoc->v_asciilabel, LEN_DKL_ASCII);
5735 }
5736 
5737 /*
5738  * Build a label out of a vtoc structure.
5739  */
5740 static int
5741 fd_build_label_vtoc(struct fdunit *un, struct vtoc *vtoc)
5742 {
5743 	struct dk_map32		*lmap;
5744 	struct dk_map2		*lpart;
5745 	struct partition	*vpart;
5746 	int			nblks;	/* no. blocks per cylinder */
5747 	int			ncyl;
5748 	int			i;
5749 	short	 sum, *sp;
5750 
5751 	/* Sanity-check the vtoc */
5752 	if ((vtoc->v_sanity != VTOC_SANE) ||
5753 	    (vtoc->v_nparts > NDKMAP) || (vtoc->v_nparts <= 0)) {
5754 		FDERRPRINT(FDEP_L1, FDEM_IOCT,
5755 		    (C, "fd_build_label:  sanity check on vtoc failed\n"));
5756 		return (EINVAL);
5757 	}
5758 
5759 	nblks = (un->un_chars->fdc_nhead * un->un_chars->fdc_secptrack *
5760 	    un->un_chars->fdc_sec_size) / DEV_BSIZE;
5761 
5762 	vpart = vtoc->v_part;
5763 
5764 	/*
5765 	 * Check the partition information in the vtoc.  The starting sectors
5766 	 * must lie along partition boundaries. (NDKMAP entries are checked
5767 	 * to ensure that the unused entries are set to 0 if vtoc->v_nparts
5768 	 * is less than NDKMAP)
5769 	 */
5770 
5771 	for (i = 0; i < NDKMAP; i++) {
5772 		if ((vpart->p_start % nblks) != 0) {
5773 			return (EINVAL);
5774 		}
5775 		ncyl = vpart->p_start % nblks;
5776 		ncyl += vpart->p_size % nblks;
5777 		if ((vpart->p_size % nblks) != 0)
5778 			ncyl++;
5779 		if (ncyl > un->un_chars->fdc_ncyl) {
5780 			return (EINVAL);
5781 		}
5782 		vpart++;
5783 	}
5784 
5785 	/*
5786 	 * reinitialize the existing label
5787 	 */
5788 	bzero(&un->un_label, sizeof (un->un_label));
5789 
5790 	/* Put appropriate vtoc structure fields into the disk label */
5791 	un->un_label.dkl_vtoc.v_bootinfo[0] = (uint32_t)vtoc->v_bootinfo[0];
5792 	un->un_label.dkl_vtoc.v_bootinfo[1] = (uint32_t)vtoc->v_bootinfo[1];
5793 	un->un_label.dkl_vtoc.v_bootinfo[2] = (uint32_t)vtoc->v_bootinfo[2];
5794 
5795 	un->un_label.dkl_vtoc.v_sanity = vtoc->v_sanity;
5796 	un->un_label.dkl_vtoc.v_version = vtoc->v_version;
5797 
5798 	bcopy(vtoc->v_volume, un->un_label.dkl_vtoc.v_volume, LEN_DKL_VVOL);
5799 
5800 	un->un_label.dkl_vtoc.v_nparts = vtoc->v_nparts;
5801 
5802 	bcopy(vtoc->v_reserved, un->un_label.dkl_vtoc.v_reserved,
5803 	    sizeof (un->un_label.dkl_vtoc.v_reserved));
5804 
5805 	/*
5806 	 * Initialize cylinder information in the label.
5807 	 * Note the conversion from starting sector number
5808 	 * to starting cylinder number.
5809 	 * Return error if division results in a remainder.
5810 	 */
5811 	lmap = un->un_label.dkl_map;
5812 	lpart = un->un_label.dkl_vtoc.v_part;
5813 	vpart = vtoc->v_part;
5814 
5815 	for (i = 0; i < (int)vtoc->v_nparts; i++) {
5816 		lpart->p_tag  = vtoc->v_part[i].p_tag;
5817 		lpart->p_flag = vtoc->v_part[i].p_flag;
5818 		lmap->dkl_cylno = vpart->p_start / nblks;
5819 		lmap->dkl_nblk = vpart->p_size;
5820 
5821 		lmap++;
5822 		lpart++;
5823 		vpart++;
5824 	}
5825 
5826 	/* Copy the timestamp and ascii label */
5827 	for (i = 0; i < NDKMAP; i++) {
5828 		un->un_label.dkl_vtoc.v_timestamp[i] = vtoc->timestamp[i];
5829 	}
5830 
5831 
5832 	bcopy(vtoc->v_asciilabel, un->un_label.dkl_asciilabel, LEN_DKL_ASCII);
5833 
5834 	FDERRPRINT(FDEP_L1, FDEM_IOCT,
5835 	    (C, "fd_build_label: asciilabel %s\n",
5836 	    un->un_label.dkl_asciilabel));
5837 
5838 	/* Initialize the magic number */
5839 	un->un_label.dkl_magic = DKL_MAGIC;
5840 
5841 	un->un_label.dkl_pcyl = un->un_chars->fdc_ncyl;
5842 
5843 	/*
5844 	 * The fdc_secptrack filed of the fd_char structure is the number
5845 	 * of sectors per track where the sectors are fdc_sec_size.  The
5846 	 * dkl_nsect field of the dk_label structure is the number of
5847 	 * 512 (DEVBSIZE) byte sectors per track.
5848 	 */
5849 	un->un_label.dkl_nsect = (un->un_chars->fdc_secptrack *
5850 	    un->un_chars->fdc_sec_size) / DEV_BSIZE;
5851 
5852 
5853 	un->un_label.dkl_ncyl = un->un_label.dkl_pcyl;
5854 	un->un_label.dkl_nhead = un->un_chars->fdc_nhead;
5855 	un->un_label.dkl_rpm = un->un_chars->fdc_medium ? 360 : 300;
5856 	un->un_label.dkl_intrlv = 1;
5857 
5858 	/* Create the checksum */
5859 	sum = 0;
5860 	un->un_label.dkl_cksum = 0;
5861 	sp = (short *)&un->un_label;
5862 	i = sizeof (struct dk_label)/sizeof (short);
5863 	while (i--) {
5864 		sum ^= *sp++;
5865 	}
5866 	un->un_label.dkl_cksum = sum;
5867 
5868 	return (0);
5869 }
5870 
5871 /*
5872  * Check for auxio register node
5873  */
5874 
5875 int
5876 fd_isauxiodip(dev_info_t *dip)
5877 {
5878 	if (strcmp(ddi_get_name(dip), "auxio") == 0 ||
5879 	    strcmp(ddi_get_name(dip), "auxiliary-io") == 0) {
5880 		return (1);
5881 	}
5882 	return (0);
5883 }
5884 
5885 /*
5886  * Search for auxio register node, then for address property
5887  */
5888 
5889 caddr_t
5890 fd_getauxiova(dev_info_t *dip)
5891 {
5892 	dev_info_t *auxdip;
5893 	caddr_t addr;
5894 
5895 	/*
5896 	 * Search sibling list, which happens to be safe inside attach
5897 	 */
5898 	auxdip = ddi_get_child(ddi_get_parent(dip));
5899 	while (auxdip) {
5900 		if (fd_isauxiodip(auxdip))
5901 			break;
5902 		auxdip = ddi_get_next_sibling(auxdip);
5903 	}
5904 
5905 	if (auxdip == NULL)
5906 		return (NULL);
5907 
5908 	addr = (caddr_t)(uintptr_t)(caddr32_t)ddi_getprop(DDI_DEV_T_ANY,
5909 	    auxdip, DDI_PROP_DONTPASS, "address", 0);
5910 
5911 	return (addr);
5912 }
5913 
5914 
5915 /*
5916  * set_rotational speed
5917  * 300 rpm for high and low density.
5918  * 360 rpm for medium density.
5919  * for now, we assume that 3rd density is supported only for Sun4M,
5920  * not for Clones. (else we would have to check for 82077, and do
5921  * specific things for the MEDIUM_DENSITY BIT for clones.
5922  * this code should not break CLONES.
5923  *
5924  * REMARK: there is a SOny requirement, to deselect the drive then
5925  * select it again after the medium density change, since the
5926  * leading edge of the select line latches the rotational Speed.
5927  * then after that, we have to wait 500 ms for the rotation to
5928  * stabilize.
5929  *
5930  */
5931 static void
5932 set_rotational_speed(struct fdctlr *fdc, int unit)
5933 {
5934 	int check;
5935 	int is_medium;
5936 
5937 	ASSERT(fdc->c_un->un_unit_no == unit);
5938 
5939 	/*
5940 	 * if we do not have a Sun4m, medium density is not supported.
5941 	 */
5942 	if (fdc->c_fdtype & FDCTYPE_MACHIO)
5943 		return;
5944 
5945 	/*
5946 	 * if FDUNIT_SET_SPEED is set, set the speed.
5947 	 * else,
5948 	 *	if there is a change, do it, if not leave it alone.
5949 	 *	there is a change if un->un_chars->fdc_medium does not match
5950 	 *	un->un_flags & FDUNIT_MEDIUM
5951 	 *	un->un_flags & FDUNIT_MEDIUM specifies the last setting.
5952 	 *	un->un_chars->fdc_medium specifies next setting.
5953 	 *	if there is a change, wait 500ms according to Sony spec.
5954 	 */
5955 
5956 	is_medium = fdc->c_un->un_chars->fdc_medium;
5957 
5958 	if (fdc->c_un->un_flags & FDUNIT_SET_SPEED) {
5959 		check = 1;
5960 	} else {
5961 		check = is_medium ^
5962 		    ((fdc->c_un->un_flags & FDUNIT_MEDIUM) ? 1 : 0);
5963 
5964 		/* Set the un_flags if necessary */
5965 
5966 		if (check)
5967 			fdc->c_un->un_flags ^= FDUNIT_MEDIUM;
5968 	}
5969 
5970 	fdc->c_un->un_flags &= ~FDUNIT_SET_SPEED;
5971 
5972 
5973 	if (check) {
5974 
5975 		fdselect(fdc, unit, 0);
5976 		drv_usecwait(5);
5977 
5978 		if ((fdc->c_fdtype & FDCTYPE_AUXIOMASK) == FDCTYPE_SLAVIO) {
5979 			Set_dor(fdc, MEDIUM_DENSITY, is_medium);
5980 		}
5981 
5982 		if ((fdc->c_fdtype & FDCTYPE_AUXIOMASK) == FDCTYPE_CHEERIO) {
5983 			if (is_medium) {
5984 				Set_auxio(fdc, AUX_MEDIUM_DENSITY);
5985 			} else {
5986 				Set_auxio(fdc, AUX_HIGH_DENSITY);
5987 			}
5988 
5989 		}
5990 
5991 		if (is_medium) {
5992 			drv_usecwait(5);
5993 		}
5994 
5995 		fdselect(fdc, unit, 1);	/* Sony requirement */
5996 		FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "rotation:medium\n"));
5997 		drv_usecwait(500000);
5998 	}
5999 }
6000 
6001 static void
6002 fd_media_watch(void *arg)
6003 {
6004 	dev_t		dev;
6005 	struct fdunit *un;
6006 	struct fdctlr *fdc;
6007 	int		unit;
6008 
6009 	dev = (dev_t)arg;
6010 	fdc = fd_getctlr(dev);
6011 	unit = fdc->c_un->un_unit_no;
6012 	un = fdc->c_un;
6013 
6014 	mutex_enter(&fdc->c_lolock);
6015 
6016 	if (un->un_media_timeout_id == 0) {
6017 		/*
6018 		 * Untimeout is about to be called.
6019 		 * Don't call fd_get_media_state again
6020 		 */
6021 		mutex_exit(&fdc->c_lolock);
6022 		return;
6023 	}
6024 
6025 
6026 	un->un_media_state = fd_get_media_state(fdc, unit);
6027 	cv_broadcast(&fdc->c_statecv);
6028 
6029 	mutex_exit(&fdc->c_lolock);
6030 
6031 	if (un->un_media_timeout) {
6032 		un->un_media_timeout_id = timeout(fd_media_watch,
6033 		    (void *)(ulong_t)dev, un->un_media_timeout);
6034 	}
6035 }
6036 
6037 enum dkio_state
6038 fd_get_media_state(struct fdctlr *fdc, int unit)
6039 {
6040 	enum dkio_state state;
6041 
6042 	ASSERT(fdc->c_un->un_unit_no == unit);
6043 
6044 	if (fdsense_chng(fdc, unit)) {
6045 		/* check disk only if DSKCHG "high" */
6046 		if (fdcheckdisk(fdc, unit)) {
6047 			state = DKIO_EJECTED;
6048 		} else {
6049 			state = DKIO_INSERTED;
6050 		}
6051 	} else {
6052 		state = DKIO_INSERTED;
6053 	}
6054 	return (state);
6055 }
6056 
6057 static int
6058 fd_check_media(dev_t dev, enum dkio_state state)
6059 {
6060 	struct fdunit *un;
6061 	struct fdctlr *fdc;
6062 	int		unit;
6063 
6064 	FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fd_check_media: start\n"));
6065 
6066 	fdc = fd_getctlr(dev);
6067 	unit = fdc->c_un->un_unit_no;
6068 	un = fdc->c_un;
6069 
6070 	mutex_enter(&fdc->c_lolock);
6071 
6072 	CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc);
6073 
6074 	if (fdc->c_un->un_state == FD_STATE_STOPPED) {
6075 		mutex_exit(&fdc->c_lolock);
6076 		if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON))
6077 		    != DDI_SUCCESS) {
6078 			FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power change \
6079 			    failed. \n"));
6080 
6081 			(void) pm_idle_component(fdc->c_dip, 0);
6082 			return (EIO);
6083 		}
6084 
6085 		mutex_enter(&fdc->c_lolock);
6086 	}
6087 
6088 	un->un_media_state = fd_get_media_state(fdc, unit);
6089 
6090 	/* turn on timeout */
6091 	un->un_media_timeout = drv_usectohz(fd_check_media_time);
6092 	un->un_media_timeout_id = timeout(fd_media_watch,
6093 	    (void *)(ulong_t)dev, un->un_media_timeout);
6094 
6095 	while (un->un_media_state == state) {
6096 		if (cv_wait_sig(&fdc->c_statecv, &fdc->c_lolock) == 0) {
6097 			un->un_media_timeout = 0;
6098 			mutex_exit(&fdc->c_lolock);
6099 			return (EINTR);
6100 		}
6101 	}
6102 
6103 	if (un->un_media_timeout_id) {
6104 		timeout_id_t timeid = un->un_media_timeout_id;
6105 		un->un_media_timeout_id = 0;
6106 
6107 		mutex_exit(&fdc->c_lolock);
6108 		(void) untimeout(timeid);
6109 		mutex_enter(&fdc->c_lolock);
6110 	}
6111 
6112 	if (un->un_media_state == DKIO_INSERTED) {
6113 		if (fdgetlabel(fdc, unit)) {
6114 			mutex_exit(&fdc->c_lolock);
6115 			return (EIO);
6116 		}
6117 	}
6118 	mutex_exit(&fdc->c_lolock);
6119 
6120 	FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fd_check_media: end\n"));
6121 	return (0);
6122 }
6123 
6124 /*
6125  * fd_get_media_info :
6126  * 	Collects medium information for
6127  *	DKIOCGMEDIAINFO ioctl.
6128  */
6129 
6130 static int
6131 fd_get_media_info(struct fdunit *un, caddr_t buf, int flag)
6132 {
6133 	struct dk_minfo media_info;
6134 	int err = 0;
6135 
6136 	media_info.dki_media_type = DK_FLOPPY;
6137 	media_info.dki_lbsize = un->un_chars->fdc_sec_size;
6138 	media_info.dki_capacity = un->un_chars->fdc_ncyl *
6139 	    un->un_chars->fdc_secptrack * un->un_chars->fdc_nhead;
6140 
6141 	if (ddi_copyout((caddr_t)&media_info, buf,
6142 	    sizeof (struct dk_minfo), flag))
6143 		err = EFAULT;
6144 	return (err);
6145 }
6146 
6147 /*
6148  * fd_power :
6149  *	Power entry point of fd driver.
6150  */
6151 
6152 static int
6153 fd_power(dev_info_t *dip, int component, int level)
6154 {
6155 
6156 	struct fdctlr *fdc;
6157 	int instance;
6158 	int rval;
6159 
6160 	if ((level < PM_LEVEL_OFF) || (level > PM_LEVEL_ON) ||
6161 	    (component != 0)) {
6162 		return (DDI_FAILURE);
6163 	}
6164 
6165 	instance = ddi_get_instance(dip);
6166 	fdc = fd_getctlr(instance << FDINSTSHIFT);
6167 	if (fdc->c_un == NULL)
6168 		return (DDI_FAILURE);
6169 
6170 	if (level == PM_LEVEL_OFF) {
6171 		rval = fd_pm_lower_power(fdc);
6172 	}
6173 	if (level == PM_LEVEL_ON) {
6174 		rval = fd_pm_raise_power(fdc);
6175 	}
6176 	return (rval);
6177 }
6178 
6179 /*
6180  * fd_pm_lower_power :
6181  *	This function is called only during pm suspend. At this point,
6182  *	the power management framework thinks the device is idle for
6183  *	long enough to go to a low power mode. If the device is busy,
6184  *	then this function returns DDI_FAILURE.
6185  */
6186 
6187 static int
6188 fd_pm_lower_power(struct fdctlr *fdc)
6189 {
6190 
6191 	mutex_enter(&fdc->c_lolock);
6192 
6193 	if ((fdc->c_un->un_state == FD_STATE_SUSPENDED) ||
6194 	    (fdc->c_un->un_state == FD_STATE_STOPPED)) {
6195 		mutex_exit(&fdc->c_lolock);
6196 		return (DDI_SUCCESS);
6197 	}
6198 
6199 
6200 	FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "fd_pm_lower_power called\n"));
6201 
6202 	/* if the device is busy then we fail the lower power request */
6203 	if (fdc->c_flags & FDCFLG_BUSY) {
6204 		FDERRPRINT(FDEP_L2, FDEM_PWR, (C, "fd_pm_lower_power : \
6205 controller is busy.\n"));
6206 		mutex_exit(&fdc->c_lolock);
6207 		return (DDI_FAILURE);
6208 	}
6209 
6210 	fdc->c_un->un_state = FD_STATE_STOPPED;
6211 
6212 	mutex_exit(&fdc->c_lolock);
6213 	return (DDI_SUCCESS);
6214 }
6215 
6216 /*
6217  * fd_pm_raise_power :
6218  *	This function performs the necessary steps for resuming a
6219  *	device, either from pm suspend or CPR. Here the controller
6220  *	is reset, initialized and the state is set to FD_STATE_NORMAL.
6221  */
6222 
6223 static int
6224 fd_pm_raise_power(struct fdctlr *fdc)
6225 {
6226 
6227 	struct fdunit *un = fdc->c_un;
6228 	int unit;
6229 
6230 	FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "fd_pm_raise_power called\n"));
6231 	mutex_enter(&fdc->c_lolock);
6232 	fdgetcsb(fdc);
6233 
6234 	/* Reset the dma engine */
6235 	if (fdc->c_fdtype & FDCTYPE_DMA) {
6236 		mutex_enter(&fdc->c_hilock);
6237 		reset_dma_controller(fdc);
6238 		set_dma_control_register(fdc, DCSR_INIT_BITS);
6239 		mutex_exit(&fdc->c_hilock);
6240 	}
6241 
6242 	/*
6243 	 * Force a rotational speed set in the next
6244 	 * call to set_rotational_speed().
6245 	 */
6246 
6247 	fdc->c_un->un_flags |= FDUNIT_SET_SPEED;
6248 
6249 	/* Reset and configure the controller */
6250 	(void) fdreset(fdc);
6251 
6252 	unit = fdc->c_un->un_unit_no;
6253 
6254 	/* Recalibrate the drive */
6255 	if (fdrecalseek(fdc, unit, -1, 0) != 0) {
6256 		FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "raise_power : recalibrate \
6257 failed\n"));
6258 		fdretcsb(fdc);
6259 		mutex_exit(&fdc->c_lolock);
6260 		return (DDI_FAILURE);
6261 	}
6262 
6263 	/* Select the drive through the AUXIO registers */
6264 	fdselect(fdc, unit, 0);
6265 	un->un_state = FD_STATE_NORMAL;
6266 	fdretcsb(fdc);
6267 	mutex_exit(&fdc->c_lolock);
6268 	return (DDI_SUCCESS);
6269 }
6270 
6271 /*
6272  * create_pm_components :
6273  *	creates the power management components for auto pm framework.
6274  */
6275 
6276 static void
6277 create_pm_components(dev_info_t *dip)
6278 {
6279 	char	*un_pm_comp[] = { "NAME=spindle-motor", "0=off", "1=on"};
6280 
6281 	if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
6282 	    "pm-components", un_pm_comp, 3) == DDI_PROP_SUCCESS) {
6283 
6284 		(void) pm_raise_power(dip, 0, PM_LEVEL_ON);
6285 	}
6286 }
6287 
6288 /*
6289  * set_data_count_register(struct fdctlr *fdc, uint32_t count)
6290  * 	Set the data count in appropriate dma register.
6291  */
6292 
6293 static void
6294 set_data_count_register(struct fdctlr *fdc, uint32_t count)
6295 {
6296 	if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
6297 		struct cheerio_dma_reg *dma_reg;
6298 		dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs;
6299 		ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dbcr, count);
6300 	} else if (fdc->c_fdtype & FDCTYPE_SB) {
6301 		struct sb_dma_reg *dma_reg;
6302 		count = count - 1; /* 8237 needs it */
6303 		dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs;
6304 		switch (fdc->sb_dma_channel) {
6305 		case 0 :
6306 			ddi_put16(fdc->c_handlep_dma,
6307 			    (ushort_t *)&dma_reg->sb_dma_regs[DMA_0WCNT],
6308 			    count & 0xFFFF);
6309 			break;
6310 		case 1 :
6311 			ddi_put16(fdc->c_handlep_dma,
6312 			    (ushort_t *)&dma_reg->sb_dma_regs[DMA_1WCNT],
6313 			    count & 0xFFFF);
6314 			break;
6315 		case 2 :
6316 			ddi_put16(fdc->c_handlep_dma,
6317 			    (ushort_t *)&dma_reg->sb_dma_regs[DMA_2WCNT],
6318 			    count & 0xFFFF);
6319 			break;
6320 		case 3 :
6321 			ddi_put16(fdc->c_handlep_dma,
6322 			    (ushort_t *)&dma_reg->sb_dma_regs[DMA_3WCNT],
6323 			    count & 0xFFFF);
6324 			break;
6325 		default :
6326 			FDERRPRINT(FDEP_L3, FDEM_SDMA,
6327 			    (C, "set_data_count: wrong channel %x\n",
6328 			    fdc->sb_dma_channel));
6329 			break;
6330 		}
6331 	}
6332 }
6333 
6334 /*
6335  * get_data_count_register(struct fdctlr *fdc)
6336  * 	Read the data count from appropriate dma register.
6337  */
6338 
6339 static uint32_t
6340 get_data_count_register(struct fdctlr *fdc)
6341 {
6342 	uint32_t retval = 0;
6343 	if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
6344 		struct cheerio_dma_reg *dma_reg;
6345 		dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs;
6346 		retval = ddi_get32(fdc->c_handlep_dma, &dma_reg->fdc_dbcr);
6347 	} else if (fdc->c_fdtype & FDCTYPE_SB) {
6348 		struct sb_dma_reg *dma_reg;
6349 		dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs;
6350 		switch (fdc->sb_dma_channel) {
6351 		case 0 :
6352 			retval = ddi_get16(fdc->c_handlep_dma,
6353 			    (ushort_t *)&dma_reg->sb_dma_regs[DMA_0WCNT]);
6354 			break;
6355 		case 1 :
6356 			retval = ddi_get16(fdc->c_handlep_dma,
6357 			    (ushort_t *)&dma_reg->sb_dma_regs[DMA_1WCNT]);
6358 			break;
6359 		case 2 :
6360 			retval = ddi_get16(fdc->c_handlep_dma,
6361 			    (ushort_t *)&dma_reg->sb_dma_regs[DMA_2WCNT]);
6362 			break;
6363 		case 3 :
6364 			retval = ddi_get16(fdc->c_handlep_dma,
6365 			    (ushort_t *)&dma_reg->sb_dma_regs[DMA_3WCNT]);
6366 			break;
6367 		default :
6368 			FDERRPRINT(FDEP_L3, FDEM_SDMA,
6369 			    (C, "get_data_count: wrong channel %x\n",
6370 			    fdc->sb_dma_channel));
6371 			break;
6372 		}
6373 		retval = (uint32_t)((uint16_t)(retval +1));
6374 	}
6375 
6376 	return (retval);
6377 
6378 }
6379 
6380 /*
6381  * reset_dma_controller(struct fdctlr *fdc)
6382  * 	Reset and initialize the dma controller.
6383  */
6384 
6385 static void
6386 reset_dma_controller(struct fdctlr *fdc)
6387 {
6388 	if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
6389 		struct cheerio_dma_reg *dma_reg;
6390 		dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs;
6391 		ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr, DCSR_RESET);
6392 		while (get_dma_control_register(fdc) & DCSR_CYC_PEND)
6393 			;
6394 		ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr, 0);
6395 	} else if (fdc->c_fdtype & FDCTYPE_SB) {
6396 		struct sb_dma_reg *dma_reg;
6397 		dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs;
6398 		ddi_put8(fdc->c_handlep_dma, &dma_reg->sb_dma_regs[DMAC1_MASK],
6399 		    (fdc->sb_dma_channel & 0x3));
6400 
6401 	}
6402 }
6403 
6404 /*
6405  * Get the DMA control register for CHEERIO.
6406  * For SouthBridge 8237 DMA controller, this register is not valid.
6407  * So, just return 0.
6408  */
6409 static uint32_t
6410 get_dma_control_register(struct fdctlr *fdc)
6411 {
6412 	uint32_t retval = 0;
6413 	if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
6414 		struct cheerio_dma_reg *dma_reg;
6415 		dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs;
6416 		retval = ddi_get32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr);
6417 	}
6418 
6419 	return (retval);
6420 }
6421 
6422 
6423 /*
6424  * set_data_address_register(struct fdctlr *fdc)
6425  * 	Set the data address in appropriate dma register.
6426  */
6427 static void
6428 set_data_address_register(struct fdctlr *fdc, uint32_t address)
6429 {
6430 	if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
6431 		struct cheerio_dma_reg *dma_reg;
6432 		dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs;
6433 		ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dacr, address);
6434 	} else if (fdc->c_fdtype & FDCTYPE_SB) {
6435 		struct sb_dma_reg *dma_reg;
6436 		dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs;
6437 		switch (fdc->sb_dma_channel) {
6438 			case 0 :
6439 				ddi_put8(fdc->c_handlep_dma,
6440 				    &dma_reg->sb_dma_regs[DMA_0PAGE],
6441 				    (address & 0xFF0000) >>16);
6442 				ddi_put8(fdc->c_handlep_dma,
6443 				    &dma_reg->sb_dma_regs[DMA_0HPG],
6444 				    (address & 0xFF000000) >>24);
6445 				ddi_put16(fdc->c_handlep_dma,
6446 				    (ushort_t *)&dma_reg->sb_dma_regs[DMA_0ADR],
6447 				    address & 0xFFFF);
6448 				break;
6449 			case 1 :
6450 				ddi_put8(fdc->c_handlep_dma,
6451 				    &dma_reg->sb_dma_regs[DMA_1PAGE],
6452 				    (address & 0xFF0000) >>16);
6453 				ddi_put8(fdc->c_handlep_dma,
6454 				    &dma_reg->sb_dma_regs[DMA_1HPG],
6455 				    (address & 0xFF000000) >>24);
6456 				ddi_put16(fdc->c_handlep_dma,
6457 				    (ushort_t *)&dma_reg->sb_dma_regs[DMA_1ADR],
6458 				    address & 0xFFFF);
6459 				break;
6460 			case 2 :
6461 				ddi_put8(fdc->c_handlep_dma,
6462 				    &dma_reg->sb_dma_regs[DMA_2PAGE],
6463 				    (address & 0xFF0000) >>16);
6464 				ddi_put8(fdc->c_handlep_dma,
6465 				    &dma_reg->sb_dma_regs[DMA_2HPG],
6466 				    (address & 0xFF000000) >>24);
6467 				ddi_put16(fdc->c_handlep_dma,
6468 				    (ushort_t *)&dma_reg->sb_dma_regs[DMA_2ADR],
6469 				    address & 0xFFFF);
6470 				break;
6471 			case 3 :
6472 				ddi_put8(fdc->c_handlep_dma,
6473 				    &dma_reg->sb_dma_regs[DMA_3PAGE],
6474 				    (address & 0xFF0000) >>16);
6475 				ddi_put8(fdc->c_handlep_dma,
6476 				    &dma_reg->sb_dma_regs[DMA_3HPG],
6477 				    (address & 0xFF000000) >>24);
6478 				ddi_put16(fdc->c_handlep_dma,
6479 				    (ushort_t *)&dma_reg->sb_dma_regs[DMA_3ADR],
6480 				    address & 0xFFFF);
6481 				break;
6482 			default :
6483 				FDERRPRINT(FDEP_L3, FDEM_SDMA,
6484 				    (C, "set_data_address: wrong channel %x\n",
6485 				    fdc->sb_dma_channel));
6486 			break;
6487 		}
6488 	}
6489 
6490 }
6491 
6492 
6493 /*
6494  * set_dma_mode(struct fdctlr *fdc, int val)
6495  * 	Set the appropriate dma direction and registers.
6496  */
6497 static void
6498 set_dma_mode(struct fdctlr *fdc, int val)
6499 {
6500 	if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
6501 		struct cheerio_dma_reg *dma_reg;
6502 		dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs;
6503 		if (val == CSB_READ)
6504 			ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr,
6505 			    DCSR_INIT_BITS|DCSR_WRITE);
6506 		else
6507 			ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr,
6508 			    DCSR_INIT_BITS);
6509 
6510 	} else if (fdc->c_fdtype & FDCTYPE_SB) {
6511 		uint8_t mode_reg_val, chn_mask;
6512 		struct sb_dma_reg *dma_reg;
6513 		dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs;
6514 
6515 		if (val == CSB_READ) {
6516 			mode_reg_val = fdc->sb_dma_channel | DMAMODE_READ
6517 			    | DMAMODE_SINGLE;
6518 		} else { /* Read operation */
6519 			mode_reg_val = fdc->sb_dma_channel | DMAMODE_WRITE
6520 			    | DMAMODE_SINGLE;
6521 		}
6522 		ddi_put8(fdc->c_handlep_dma, &dma_reg->sb_dma_regs[DMAC1_MODE],
6523 		    mode_reg_val);
6524 		chn_mask = 1 << (fdc->sb_dma_channel & 0x3);
6525 		ddi_put8(fdc->c_handlep_dma,
6526 		    &dma_reg->sb_dma_regs[DMAC1_ALLMASK], ~chn_mask);
6527 		fdc->sb_dma_lock = 1;
6528 	}
6529 }
6530 
6531 /*
6532  * This function is valid only for CHEERIO/RIO based
6533  * controllers. The control register for the dma channel
6534  * is initialized by this function.
6535  */
6536 
6537 static void
6538 set_dma_control_register(struct fdctlr *fdc, uint32_t val)
6539 {
6540 	if (fdc->c_fdtype & FDCTYPE_CHEERIO) {
6541 		struct cheerio_dma_reg *dma_reg;
6542 		dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs;
6543 		ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr, val);
6544 	}
6545 }
6546 
6547 static void
6548 release_sb_dma(struct fdctlr *fdc)
6549 {
6550 	struct sb_dma_reg *dma_reg;
6551 	dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs;
6552 	/* Unmask all the channels to release the DMA controller */
6553 	ddi_put8(fdc->c_handlep_dma,
6554 	    &dma_reg->sb_dma_regs[DMAC1_ALLMASK], NULL);
6555 	fdc->sb_dma_lock = 0;
6556 }
6557 
6558 static void
6559 quiesce_fd_interrupt(struct fdctlr *fdc)
6560 {
6561 	/*
6562 	 * The following code is put here to take care of HW problem.
6563 	 * The HW problem is as follows:
6564 	 *
6565 	 *	After poweron the Southbridge floppy controller asserts the
6566 	 * interrupt in tristate. This causes continuous interrupts to
6567 	 * be generated.
6568 	 * Until the Hardware is FIXED we will have to use the following code
6569 	 * to set the interrupt line to proper state after poweron.
6570 	 */
6571 	if (fdc->c_fdtype & FDCTYPE_SB) {
6572 		ddi_put8(fdc->c_handlep_cont, ((uint8_t *)fdc->c_dor),
6573 		    0x0);
6574 		drv_usecwait(200);
6575 		ddi_put8(fdc->c_handlep_cont, ((uint8_t *)fdc->c_dor),
6576 		    0xC);
6577 		drv_usecwait(200);
6578 		Set_Fifo(fdc, 0xE6);
6579 		drv_usecwait(200);
6580 	}
6581 }
6582