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