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