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