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