1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * Intel 82077 Floppy Disk Driver 29 */ 30 31 /* 32 * Notes 33 * 34 * 0. The driver supports two flavors of hardware design: 35 * "SUNW,fdtwo" - sun4m - 82077 with sun4m style Auxio 36 * "fdthree" - sun4u - 82077 with DMA 37 * In addition it supports an apparent bug in some versions of 38 * the 82077 controller. 39 * 40 * 1. The driver is mostly set up for multiple controllers, multiple 41 * drives. However- we *do* assume the use of the AUXIO register, and 42 * if we ever have > 1 fdc, we'll have to see what that means. This 43 * is all intrinsically machine specific, but there isn't much we 44 * can do about it. 45 * 46 * 2. The driver also is structured to deal with one drive active at 47 * a time. This is because the 82072 chip (no longer supported) was 48 * known to be buggy with respect to overlapped seeks. 49 * 50 * 3. The high level interrupt code is in assembler, and runs in a 51 * sparc trap window. It acts as a pseudo-dma engine as well as 52 * handles a couple of other interrupts. When it gets its job done, 53 * it schedules a second stage interrupt (soft interrupt) which 54 * is then fielded here in fd_lointr. When DMA is used, the fdintr_dma 55 * interrupt handler is used. 56 * 57 * 4. Nearly all locking is done on a lower level MUTEX_DRIVER 58 * mutex. The locking is quite conservative, and is generally 59 * established very close to any of the entries into the driver. 60 * There is nearly no locking done of the high level MUTEX_DRIVER 61 * mutex (which generally is a SPIN mutex because the floppy usually 62 * interrupts above LOCK_LEVEL). The assembler high level interrupt 63 * handler grabs the high level mutex, but the code in the driver 64 * here is especially structured to not need to do this. 65 * 66 * 5. Fdrawioctl commands that pass data are not optimized for 67 * speed. If they need to be faster, the driver structure will 68 * have to be redone such that fdrawioctl calls physio after 69 * cons'ing up a uio structure and that fdstart will be able 70 * to detect that a particular buffer is a 'special' buffer. 71 * 72 * 6. Removable media support is not complete. 73 * 74 */ 75 76 #include <sys/param.h> 77 #include <sys/buf.h> 78 #include <sys/ioctl.h> 79 #include <sys/uio.h> 80 #include <sys/open.h> 81 #include <sys/conf.h> 82 #include <sys/file.h> 83 #include <sys/cmn_err.h> 84 #include <sys/debug.h> 85 #include <sys/kmem.h> 86 #include <sys/stat.h> 87 #include <sys/autoconf.h> 88 89 #include <sys/dklabel.h> 90 91 #include <sys/vtoc.h> 92 #include <sys/dkio.h> 93 #include <sys/fdio.h> 94 95 #include <sys/ddi.h> 96 #include <sys/sunddi.h> 97 #include <sys/kstat.h> 98 99 /* 100 * included to check for ELC or SLC which report floppy controller that 101 */ 102 #include <sys/cpu.h> 103 104 #include "sys/fdvar.h" 105 #include "sys/fdreg.h" 106 #include "sys/dma_i8237A.h" 107 108 /* 109 * Defines 110 */ 111 #define KIOSP KSTAT_IO_PTR(un->un_iostat) 112 #define KIOIP KSTAT_INTR_PTR(fdc->c_intrstat) 113 #define MEDIUM_DENSITY 0x40 114 #define SEC_SIZE_CODE (fdctlr.c_csb->csb_unit]->un_chars->medium ? 3 : 2) 115 #define CMD_READ (MT + SK + FDRAW_RDCMD + MFM) 116 #define CMD_WRITE (MT + FDRAW_WRCMD + MFM) 117 #define C CE_CONT 118 #define FD_POLLABLE_PROP "pollable" /* prom property */ 119 #define FD_MANUAL_EJECT "manual" /* prom property */ 120 #define FD_UNIT "unit" /* prom property */ 121 122 /* 123 * Sony MP-F17W-50D Drive Parameters 124 * High Capacity 125 * Capacity unformatted 2Mb 126 * Capacity formatted 1.47Mb 127 * Encoding method MFM 128 * Recording density 17434 bpi 129 * Track density 135 tpi 130 * Cylinders 80 131 * Heads 2 132 * Tracks 160 133 * Rotational speed 300 rpm 134 * Transfer rate 250/500 kbps 135 * Latency (average) 100 ms 136 * Access time 137 * Average 95 ms 138 * Track to track 3 ms 139 * Head settling time 15 ms 140 * Motor start time 500 ms 141 * Head load time ? ms 142 */ 143 144 /* 145 * The max_fd_dma_len is used only when southbridge is present. 146 * It has been observed that when IFB tests are run the floppy dma could get 147 * starved and result in underrun errors. After experimenting it was found that 148 * doing dma in chunks of 2048 works OK. 149 * The reason for making this a global variable is that there could be 150 * situations under which the customer would like to get full performance 151 * from floppy. He may not be having IFB boards that cause underrun errors. 152 * Under those conditions we could set this value to a much higher value 153 * by editing /etc/system file. 154 */ 155 int max_fd_dma_len = 2048; 156 157 static void quiesce_fd_interrupt(struct fdctlr *); 158 159 /* 160 * Character/block entry points function prototypes 161 */ 162 static int fd_open(dev_t *, int, int, cred_t *); 163 static int fd_close(dev_t, int, int, cred_t *); 164 static int fd_strategy(struct buf *); 165 static int fd_read(dev_t, struct uio *, cred_t *); 166 static int fd_write(dev_t, struct uio *, cred_t *); 167 static int fd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 168 static int 169 fd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *, caddr_t, int *); 170 171 /* 172 * Device operations (dev_ops) entries function prototypes 173 */ 174 static int fd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 175 void **result); 176 static int fd_attach(dev_info_t *, ddi_attach_cmd_t); 177 static int fd_detach(dev_info_t *, ddi_detach_cmd_t); 178 static int fd_power(dev_info_t *dip, int component, int level); 179 180 /* 181 * Internal functions 182 */ 183 static int fd_attach_check_drive(struct fdctlr *fdc); 184 static int fd_attach_det_ctlr(dev_info_t *dip, struct fdctlr *fdc); 185 static int fd_attach_map_regs(dev_info_t *dip, struct fdctlr *fdc); 186 static int fd_attach_register_interrupts(dev_info_t *dip, struct fdctlr *fdc, 187 int *hard); 188 static int fd_build_label_vtoc(struct fdunit *, struct vtoc *); 189 static void fd_build_user_vtoc(struct fdunit *, struct vtoc *); 190 static int fdcheckdisk(struct fdctlr *fdc, int unit); 191 static int fd_check_media(dev_t dev, enum dkio_state state); 192 static void fd_cleanup(dev_info_t *dip, struct fdctlr *fdc, int hard, 193 int locks); 194 static void fdeject(struct fdctlr *, int unit); 195 static int fdexec(struct fdctlr *fdc, int flags); 196 static void fdexec_turn_on_motor(struct fdctlr *fdc, int flags, uint_t unit); 197 static int fdformat(struct fdctlr *fdc, int unit, int cyl, int hd); 198 static caddr_t fd_getauxiova(); 199 static struct fdctlr *fd_getctlr(dev_t); 200 static void fdgetcsb(struct fdctlr *); 201 static int fdgetlabel(struct fdctlr *fdc, int unit); 202 enum dkio_state fd_get_media_state(struct fdctlr *, int); 203 static uint_t fdintr_dma(); 204 static int fd_isauxiodip(dev_info_t *); 205 static uint_t fd_lointr(caddr_t arg); 206 static void fd_media_watch(void *); 207 static void fdmotoff(void *); 208 static int fd_part_is_open(struct fdunit *un, int part); 209 static int fdrawioctl(struct fdctlr *, int, intptr_t, int); 210 static int fdrecalseek(struct fdctlr *fdc, int unit, int arg, int execflg); 211 static int fdrecover(struct fdctlr *); 212 static void fdretcsb(struct fdctlr *); 213 static int fdreset(struct fdctlr *); 214 static int fdrw(struct fdctlr *fdc, int, int, int, int, int, caddr_t, uint_t); 215 static void fdselect(struct fdctlr *fdc, int unit, int onoff); 216 static int fdsensedrv(struct fdctlr *fdc, int unit); 217 static int fdsense_chng(struct fdctlr *, int unit); 218 static void fdstart(struct fdctlr *); 219 static int fdstart_dma(register struct fdctlr *fdc, caddr_t addr, uint_t len); 220 static int fd_unit_is_open(struct fdunit *); 221 static void fdunpacklabel(struct packed_label *, struct dk_label *); 222 static int fd_unbind_handle(struct fdctlr *); 223 static void fdwatch(void *); 224 static void set_rotational_speed(struct fdctlr *, int); 225 static int fd_get_media_info(struct fdunit *un, caddr_t buf, int flag); 226 static int fd_pm_lower_power(struct fdctlr *fdc); 227 static int fd_pm_raise_power(struct fdctlr *fdc); 228 static void create_pm_components(dev_info_t *dip); 229 static void set_data_count_register(struct fdctlr *fdc, uint32_t count); 230 static uint32_t get_data_count_register(struct fdctlr *fdc); 231 static void reset_dma_controller(struct fdctlr *fdc); 232 static void set_data_address_register(struct fdctlr *fdc, uint32_t address); 233 static uint32_t get_dma_control_register(struct fdctlr *fdc); 234 static void set_dma_mode(struct fdctlr *fdc, int val); 235 static void set_dma_control_register(struct fdctlr *fdc, uint32_t val); 236 static void release_sb_dma(struct fdctlr *fdc); 237 238 /* 239 * External functions 240 */ 241 extern uint_t fd_intr(caddr_t); /* defined in fd_asm.s */ 242 extern void set_auxioreg(); 243 extern void call_debug(); 244 245 246 247 /* 248 * The following macro checks whether the device in a SUSPENDED state. 249 * As per WDD guide lines the I/O requests to a suspended device should 250 * be blocked until the device is resumed. 251 * Here we cv_wait on c_suspend_cv, and there is a cv_broadcast() in 252 * DDI_RESUME to wake up this thread. 253 * 254 * NOTE: This code is not tested because the kernel threads are suspended 255 * before the device is suspended. So there can not be any I/O requests on 256 * a suspended device until the cpr implementation changes.. 257 */ 258 259 #define CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc) \ 260 {\ 261 while (fdc->c_un->un_state == FD_STATE_SUSPENDED) {\ 262 cv_wait(&fdc->c_suspend_cv, \ 263 &fdc->c_lolock);\ 264 }\ 265 } 266 267 /* 268 * bss (uninitialized data) 269 */ 270 struct fdctlr *fdctlrs; /* linked list of controllers */ 271 272 /* 273 * initialized data 274 */ 275 276 static int fd_check_media_time = 5000000; /* 5 second state check */ 277 static int fd_pollable = 0; 278 static uchar_t rwretry = 10; 279 static uchar_t skretry = 5; 280 /* This variable allows the dynamic change of the burst size */ 281 static int fd_burstsize = DCSR_BURST_0 | DCSR_BURST_1; 282 283 static struct driver_minor_data { 284 char *name; 285 int minor; 286 int type; 287 } fd_minor [] = { 288 { "a", 0, S_IFBLK}, 289 { "b", 1, S_IFBLK}, 290 { "c", 2, S_IFBLK}, 291 { "a,raw", 0, S_IFCHR}, 292 { "b,raw", 1, S_IFCHR}, 293 { "c,raw", 2, S_IFCHR}, 294 {0} 295 }; 296 297 /* 298 * If the interrupt handler is invoked and no controllers expect an 299 * interrupt, the kernel panics. The following message is printed out. 300 */ 301 char *panic_msg = "fd_intr: unexpected interrupt\n"; 302 303 /* 304 * Specify/Configure cmd parameters 305 */ 306 static uchar_t fdspec[2] = { 0xc2, 0x33 }; /* "specify" parameters */ 307 static uchar_t fdconf[3] = { 0x64, 0x58, 0x00 }; /* "configure" parameters */ 308 309 /* When DMA is used, set the ND bit to 0 */ 310 #define SPEC_DMA_MODE 0x32 311 312 /* 313 * default characteristics 314 */ 315 static struct fd_char fdtypes[] = { 316 { /* struct fd_char fdchar_1.7MB density */ 317 0, /* medium */ 318 500, /* transfer rate */ 319 80, /* number of cylinders */ 320 2, /* number of heads */ 321 512, /* sector size */ 322 21, /* sectors per track */ 323 -1, /* (NA) # steps per data track */ 324 }, 325 { /* struct fd_char fdchar_highdens */ 326 0, /* medium */ 327 500, /* transfer rate */ 328 80, /* number of cylinders */ 329 2, /* number of heads */ 330 512, /* sector size */ 331 18, /* sectors per track */ 332 -1, /* (NA) # steps per data track */ 333 }, 334 { /* struct fd_char fdchar_meddens */ 335 1, /* medium */ 336 500, /* transfer rate */ 337 77, /* number of cylinders */ 338 2, /* number of heads */ 339 1024, /* sector size */ 340 8, /* sectors per track */ 341 -1, /* (NA) # steps per data track */ 342 }, 343 { /* struct fd_char fdchar_lowdens */ 344 0, /* medium */ 345 250, /* transfer rate */ 346 80, /* number of cylinders */ 347 2, /* number of heads */ 348 512, /* sector size */ 349 9, /* sectors per track */ 350 -1, /* (NA) # steps per data track */ 351 } 352 }; 353 354 355 static int nfdtypes = sizeof (fdtypes) / sizeof (fdtypes[0]); 356 357 358 /* 359 * Default Label & partition maps 360 */ 361 362 static struct packed_label fdlbl_high_21 = { 363 { "3.5\" floppy cyl 80 alt 0 hd 2 sec 21" }, 364 300, /* rotations per minute */ 365 80, /* # physical cylinders */ 366 0, /* alternates per cylinder */ 367 1, /* interleave factor */ 368 80, /* # of data cylinders */ 369 0, /* # of alternate cylinders */ 370 2, /* # of heads in this partition */ 371 21, /* # of 512 byte sectors per track */ 372 { 373 { 0, 79 * 2 * 21 }, /* part 0 - all but last cyl */ 374 { 79, 1 * 2 * 21 }, /* part 1 - just the last cyl */ 375 { 0, 80 * 2 * 21 }, /* part 2 - "the whole thing" */ 376 }, 377 { 0, /* version */ 378 "", /* volume label */ 379 3, /* no. of partitions */ 380 { 0 }, /* partition hdrs, sec 2 */ 381 { 0 }, /* mboot info. unsupported */ 382 VTOC_SANE, /* verify vtoc sanity */ 383 { 0 }, /* reserved space */ 384 0, /* timestamp */ 385 }, 386 }; 387 388 static struct packed_label fdlbl_high_80 = { 389 { "3.5\" floppy cyl 80 alt 0 hd 2 sec 18" }, 390 300, /* rotations per minute */ 391 80, /* # physical cylinders */ 392 0, /* alternates per cylinder */ 393 1, /* interleave factor */ 394 80, /* # of data cylinders */ 395 0, /* # of alternate cylinders */ 396 2, /* # of heads in this partition */ 397 18, /* # of 512 byte sectors per track */ 398 { 399 { 0, 79 * 2 * 18 }, /* part 0 - all but last cyl */ 400 { 79, 1 * 2 * 18 }, /* part 1 - just the last cyl */ 401 { 0, 80 * 2 * 18 }, /* part 2 - "the whole thing" */ 402 }, 403 { 0, /* version */ 404 "", /* volume label */ 405 3, /* no. of partitions */ 406 { 0 }, /* partition hdrs, sec 2 */ 407 { 0 }, /* mboot info. unsupported */ 408 VTOC_SANE, /* verify vtoc sanity */ 409 { 0 }, /* reserved space */ 410 0, /* timestamp */ 411 }, 412 }; 413 414 /* 415 * A medium density diskette has 1024 byte sectors. The dk_label structure 416 * assumes a sector is DEVBSIZE (512) bytes. 417 */ 418 static struct packed_label fdlbl_medium_80 = { 419 { "3.5\" floppy cyl 77 alt 0 hd 2 sec 8" }, 420 360, /* rotations per minute */ 421 77, /* # physical cylinders */ 422 0, /* alternates per cylinder */ 423 1, /* interleave factor */ 424 77, /* # of data cylinders */ 425 0, /* # of alternate cylinders */ 426 2, /* # of heads in this partition */ 427 16, /* # of 512 byte sectors per track */ 428 { 429 { 0, 76 * 2 * 8 * 2 }, /* part 0 - all but last cyl */ 430 { 76, 1 * 2 * 8 * 2 }, /* part 1 - just the last cyl */ 431 { 0, 77 * 2 * 8 * 2 }, /* part 2 - "the whole thing" */ 432 }, 433 { 0, /* version */ 434 "", /* volume label */ 435 3, /* no. of partitions */ 436 { 0 }, /* partition hdrs, sec 2 */ 437 { 0 }, /* mboot info. unsupported */ 438 VTOC_SANE, /* verify vtoc sanity */ 439 { 0 }, /* reserved space */ 440 0, /* timestamp */ 441 }, 442 }; 443 444 static struct packed_label fdlbl_low_80 = { 445 { "3.5\" floppy cyl 80 alt 0 hd 2 sec 9" }, 446 300, /* rotations per minute */ 447 80, /* # physical cylinders */ 448 0, /* alternates per cylinder */ 449 1, /* interleave factor */ 450 80, /* # of data cylinders */ 451 0, /* # of alternate cylinders */ 452 2, /* # of heads in this partition */ 453 9, /* # of 512 byte sectors per track */ 454 { 455 { 0, 79 * 2 * 9 }, /* part 0 - all but last cyl */ 456 { 79, 1 * 2 * 9 }, /* part 1 - just the last cyl */ 457 { 0, 80 * 2 * 9 }, /* part 2 - "the whole thing" */ 458 }, 459 { 0, /* version */ 460 "", /* volume label */ 461 3, /* no. of partitions */ 462 { 0 }, /* partition hdrs, sec 2 */ 463 { 0 }, /* mboot info. unsupported */ 464 VTOC_SANE, /* verify vtoc sanity */ 465 { 0 }, /* reserved space */ 466 0, /* timestamp */ 467 }, 468 }; 469 470 static struct fdcmdinfo { 471 char *cmdname; /* command name */ 472 uchar_t ncmdbytes; /* number of bytes of command */ 473 uchar_t nrsltbytes; /* number of bytes in result */ 474 uchar_t cmdtype; /* characteristics */ 475 } fdcmds[] = { 476 "", 0, 0, 0, /* - */ 477 "", 0, 0, 0, /* - */ 478 "read_track", 9, 7, 1, /* 2 */ 479 "specify", 3, 0, 3, /* 3 */ 480 "sense_drv_status", 2, 1, 3, /* 4 */ 481 "write", 9, 7, 1, /* 5 */ 482 "read", 9, 7, 1, /* 6 */ 483 "recalibrate", 2, 0, 2, /* 7 */ 484 "sense_int_status", 1, 2, 3, /* 8 */ 485 "write_del", 9, 7, 1, /* 9 */ 486 "read_id", 2, 7, 2, /* A */ 487 "motor_on/off", 1, 0, 4, /* B */ 488 "read_del", 9, 7, 1, /* C */ 489 "format_track", 10, 7, 1, /* D */ 490 "dump_reg", 1, 10, 4, /* E */ 491 "seek", 3, 0, 2, /* F */ 492 "", 0, 0, 0, /* - */ 493 "", 0, 0, 0, /* - */ 494 "", 0, 0, 0, /* - */ 495 "configure", 4, 0, 4, /* 13 */ 496 /* relative seek */ 497 }; 498 499 static struct cb_ops fd_cb_ops = { 500 fd_open, /* open */ 501 fd_close, /* close */ 502 fd_strategy, /* strategy */ 503 nodev, /* print */ 504 nodev, /* dump */ 505 fd_read, /* read */ 506 fd_write, /* write */ 507 fd_ioctl, /* ioctl */ 508 nodev, /* devmap */ 509 nodev, /* mmap */ 510 nodev, /* segmap */ 511 nochpoll, /* poll */ 512 fd_prop_op, /* cb_prop_op */ 513 0, /* streamtab */ 514 D_NEW | D_MP /* Driver compatibility flag */ 515 }; 516 517 static struct dev_ops fd_ops = { 518 DEVO_REV, /* devo_rev, */ 519 0, /* refcnt */ 520 fd_info, /* info */ 521 nulldev, /* identify */ 522 nulldev, /* probe */ 523 fd_attach, /* attach */ 524 fd_detach, /* detach */ 525 nodev, /* reset */ 526 &fd_cb_ops, /* driver operations */ 527 (struct bus_ops *)0, /* bus operations */ 528 fd_power, /* power */ 529 ddi_quiesce_not_supported, /* devo_quiesce */ 530 }; 531 532 533 /* 534 * error handling 535 * 536 * for debugging, set rwretry and skretry = 1 537 * set fderrlevel to 1 538 * set fderrmask to 224 or 100644 539 * 540 * after debug set rwretry to 10, skretry to 5, and fderrlevel to 3 541 * set fderrmask to FDEM_ALL 542 * remove the define FD_DEBUG 543 * 544 */ 545 546 static unsigned int fderrmask = (unsigned int)FDEM_ALL; 547 static int fderrlevel = 3; 548 549 static int tosec = 16; /* long timeouts for sundiag for now */ 550 551 /* 552 * loadable module support 553 */ 554 555 #include <sys/modctl.h> 556 557 extern struct mod_ops mod_driverops; 558 static struct modldrv modldrv = { 559 &mod_driverops, /* Type of module. driver here */ 560 "Floppy Driver", /* Name of the module. */ 561 &fd_ops, /* Driver ops vector */ 562 }; 563 564 static struct modlinkage modlinkage = { 565 MODREV_1, 566 &modldrv, 567 NULL 568 }; 569 570 int 571 _init(void) 572 { 573 return (mod_install(&modlinkage)); 574 } 575 576 int 577 _info(struct modinfo *modinfop) 578 { 579 return (mod_info(&modlinkage, modinfop)); 580 } 581 582 int 583 _fini(void) 584 { 585 int e; 586 587 if ((e = mod_remove(&modlinkage)) != 0) 588 return (e); 589 590 /* ddi_soft_state_fini() */ 591 return (0); 592 } 593 594 /* ARGSUSED */ 595 static int 596 fd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 597 { 598 struct fdctlr *fdc; 599 struct driver_minor_data *dmdp; 600 int instance = ddi_get_instance(dip); 601 int hard_intr_set = 0; 602 603 FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: start\n")); 604 605 switch (cmd) { 606 case DDI_ATTACH: 607 break; 608 case DDI_RESUME: 609 610 if (!(fdc = fd_getctlr(instance << FDINSTSHIFT))) { 611 return (DDI_FAILURE); 612 } 613 quiesce_fd_interrupt(fdc); 614 if (fdc->c_fdtype & FDCTYPE_SB) 615 if (ddi_add_intr(dip, 0, &fdc->c_block, 0, 616 fdintr_dma, (caddr_t)0) != DDI_SUCCESS) { 617 return (DDI_FAILURE); 618 } 619 620 (void) pm_raise_power(dip, 0, PM_LEVEL_ON); 621 mutex_enter(&fdc->c_lolock); 622 /* 623 * Wake up any thread blocked due to I/O requests 624 * while the device was suspended. 625 */ 626 cv_broadcast(&fdc->c_suspend_cv); 627 mutex_exit(&fdc->c_lolock); 628 return (DDI_SUCCESS); 629 630 default: 631 return (DDI_FAILURE); 632 } 633 634 635 /* 636 * Check for the pollable property 637 * A pollable floppy drive currently only exists on the 638 * Sparcstation Voyager. This drive does not need to 639 * be turned on in order to sense whether or not a diskette 640 * is present. 641 */ 642 if (ddi_getprop(DDI_DEV_T_ANY, dip, 643 DDI_PROP_DONTPASS, FD_POLLABLE_PROP, 0)) 644 fd_pollable = 1; 645 646 fdc = kmem_zalloc(sizeof (*fdc), KM_SLEEP); 647 fdc->c_dip = dip; 648 649 650 fdc->c_next = fdctlrs; 651 fdctlrs = fdc; 652 653 /* Determine which type of controller is present and initialize it */ 654 if (fd_attach_det_ctlr(dip, fdc) == DDI_FAILURE) { 655 fd_cleanup(dip, fdc, hard_intr_set, 0); 656 return (DDI_FAILURE); 657 } 658 /* Finish mapping the device registers & setting up structures */ 659 if (fd_attach_map_regs(dip, fdc) == DDI_FAILURE) { 660 fd_cleanup(dip, fdc, hard_intr_set, 0); 661 return (DDI_FAILURE); 662 } 663 664 /* 665 * Initialize the DMA limit structures if it's being used. 666 */ 667 if (fdc->c_fdtype & FDCTYPE_DMA) { 668 fdc->c_fd_dma_lim.dma_attr_version = DMA_ATTR_V0; 669 fdc->c_fd_dma_lim.dma_attr_addr_lo = 0x00000000ull; 670 fdc->c_fd_dma_lim.dma_attr_addr_hi = 0xfffffffeull; 671 fdc->c_fd_dma_lim.dma_attr_count_max = 0xffffff; 672 if (fdc->c_fdtype & FDCTYPE_SB) { 673 fdc->c_fd_dma_lim.dma_attr_align = FD_SB_DMA_ALIGN; 674 } else { 675 fdc->c_fd_dma_lim.dma_attr_align = 1; 676 } 677 fdc->c_fd_dma_lim.dma_attr_burstsizes = 0x0; 678 fdc->c_fd_dma_lim.dma_attr_minxfer = 1; 679 fdc->c_fd_dma_lim.dma_attr_maxxfer = 0xffff; 680 fdc->c_fd_dma_lim.dma_attr_seg = 0xffff; 681 fdc->c_fd_dma_lim.dma_attr_sgllen = 1; 682 fdc->c_fd_dma_lim.dma_attr_granular = 512; 683 684 if (ddi_dma_alloc_handle(dip, &fdc->c_fd_dma_lim, 685 DDI_DMA_DONTWAIT, 0, &fdc->c_dmahandle) != DDI_SUCCESS) { 686 fd_cleanup(dip, fdc, hard_intr_set, 0); 687 return (DDI_FAILURE); 688 } 689 690 if (fdc->c_fdtype & FDCTYPE_SB) { 691 ddi_device_acc_attr_t dev_attr; 692 size_t rlen; 693 694 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 695 dev_attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 696 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 697 698 if (ddi_dma_mem_alloc(fdc->c_dmahandle, 699 (size_t)(32*1024), &dev_attr, DDI_DMA_CONSISTENT, 700 DDI_DMA_SLEEP, NULL, (caddr_t *)&fdc->dma_buf, 701 &rlen, &fdc->c_dma_buf_handle) != DDI_SUCCESS) { 702 fd_cleanup(dip, fdc, hard_intr_set, 0); 703 return (DDI_FAILURE); 704 } 705 706 } 707 } 708 709 710 /* Register the interrupts */ 711 if (fd_attach_register_interrupts(dip, fdc, 712 &hard_intr_set) == DDI_FAILURE) { 713 fd_cleanup(dip, fdc, hard_intr_set, 0); 714 FDERRPRINT(FDEP_L1, FDEM_ATTA, 715 (C, "fd_attach: registering interrupts failed\n")); 716 return (DDI_FAILURE); 717 } 718 719 720 /* 721 * set initial controller/drive/disk "characteristics/geometry" 722 * 723 * NOTE: The driver only supports one floppy drive. The hardware 724 * only supports one drive because there is only one auxio register 725 * for one drive. 726 */ 727 fdc->c_un = kmem_zalloc(sizeof (struct fdunit), KM_SLEEP); 728 fdc->c_un->un_chars = kmem_alloc(sizeof (struct fd_char), KM_SLEEP); 729 fdc->c_un->un_iostat = kstat_create("fd", 0, "fd0", "disk", 730 KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT); 731 if (fdc->c_un->un_iostat) { 732 fdc->c_un->un_iostat->ks_lock = &fdc->c_lolock; 733 kstat_install(fdc->c_un->un_iostat); 734 } 735 736 fdc->c_un->un_drive = kmem_zalloc(sizeof (struct fd_drive), KM_SLEEP); 737 738 /* check for the manual eject property */ 739 if (ddi_getprop(DDI_DEV_T_ANY, dip, 740 DDI_PROP_DONTPASS, FD_MANUAL_EJECT, 0)) { 741 fdc->c_un->un_drive->fdd_ejectable = 0; 742 } else { 743 /* an absence of the property indicates auto eject */ 744 fdc->c_un->un_drive->fdd_ejectable = -1; 745 } 746 747 FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: ejectable? %d\n", 748 fdc->c_un->un_drive->fdd_ejectable)); 749 750 /* 751 * Check for the drive id. If the drive id property doesn't exist 752 * then the drive id is set to 0 753 */ 754 fdc->c_un->un_unit_no = ddi_getprop(DDI_DEV_T_ANY, dip, 755 DDI_PROP_DONTPASS, FD_UNIT, 0); 756 757 758 if (fdc->c_fdtype & FDCTYPE_SB) { 759 fdc->sb_dma_channel = ddi_getprop(DDI_DEV_T_ANY, dip, 760 DDI_PROP_DONTPASS, "dma-channel", 0); 761 } 762 763 764 FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: unit %d\n", 765 fdc->c_un->un_unit_no)); 766 767 /* Initially set the characteristics to high density */ 768 fdc->c_un->un_curfdtype = 1; 769 *fdc->c_un->un_chars = fdtypes[fdc->c_un->un_curfdtype]; 770 fdunpacklabel(&fdlbl_high_80, &fdc->c_un->un_label); 771 772 /* Make sure drive is present */ 773 if (fd_attach_check_drive(fdc) == DDI_FAILURE) { 774 fd_cleanup(dip, fdc, hard_intr_set, 1); 775 return (DDI_FAILURE); 776 } 777 778 for (dmdp = fd_minor; dmdp->name != NULL; dmdp++) { 779 if (ddi_create_minor_node(dip, dmdp->name, dmdp->type, 780 (instance << FDINSTSHIFT) | dmdp->minor, 781 DDI_NT_FD, 0) == DDI_FAILURE) { 782 fd_cleanup(dip, fdc, hard_intr_set, 1); 783 return (DDI_FAILURE); 784 } 785 } 786 787 create_pm_components(dip); 788 789 /* 790 * Add a zero-length attribute to tell the world we support 791 * kernel ioctls (for layered drivers) 792 */ 793 (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, 794 DDI_KERNEL_IOCTL, NULL, 0); 795 796 ddi_report_dev(dip); 797 798 FDERRPRINT(FDEP_L1, FDEM_ATTA, 799 (C, "attached 0x%x\n", ddi_get_instance(dip))); 800 801 return (DDI_SUCCESS); 802 } 803 804 /* 805 * Finish mapping the registers and initializing structures 806 */ 807 static int 808 fd_attach_map_regs(dev_info_t *dip, struct fdctlr *fdc) 809 { 810 ddi_device_acc_attr_t attr; 811 812 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 813 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 814 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 815 816 /* Map the DMA registers of the platform supports DMA */ 817 if (fdc->c_fdtype & FDCTYPE_SB) { 818 if (ddi_regs_map_setup(dip, 1, (caddr_t *)&fdc->c_dma_regs, 819 0, sizeof (struct sb_dma_reg), &attr, 820 &fdc->c_handlep_dma)) { 821 return (DDI_FAILURE); 822 } 823 824 825 } else if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 826 if (ddi_regs_map_setup(dip, 1, (caddr_t *)&fdc->c_dma_regs, 827 0, sizeof (struct cheerio_dma_reg), &attr, 828 &fdc->c_handlep_dma)) { 829 return (DDI_FAILURE); 830 } 831 } 832 833 /* Reset the DMA engine and enable floppy interrupts */ 834 reset_dma_controller(fdc); 835 set_dma_control_register(fdc, DCSR_INIT_BITS); 836 837 /* Finish initializing structures associated with the device regs */ 838 switch (fdc->c_fdtype & FDCTYPE_CTRLMASK) { 839 case FDCTYPE_82077: 840 FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "type is 82077\n")); 841 /* 842 * Initialize addrs of key registers 843 */ 844 fdc->c_control = 845 (uchar_t *)&fdc->c_reg->fdc_82077_reg.fdc_control; 846 fdc->c_fifo = (uchar_t *)&fdc->c_reg->fdc_82077_reg.fdc_fifo; 847 fdc->c_dor = (uchar_t *)&fdc->c_reg->fdc_82077_reg.fdc_dor; 848 fdc->c_dir = (uchar_t *)&fdc->c_reg->fdc_82077_reg.fdc_dir; 849 850 851 FDERRPRINT(FDEP_L1, FDEM_ATTA, ((int)C, 852 (char *)"fdattach: msr/dsr at %p\n", 853 (void *)fdc->c_control)); 854 855 /* 856 * The 82077 doesn't use the first configuration parameter 857 * so let's adjust that while we know we're an 82077. 858 */ 859 fdconf[0] = 0; 860 861 quiesce_fd_interrupt(fdc); 862 break; 863 default: 864 break; 865 } 866 867 return (0); 868 } 869 870 /* 871 * Determine which type of floppy controller is present and 872 * initialize the registers accordingly 873 */ 874 static int 875 fd_attach_det_ctlr(dev_info_t *dip, struct fdctlr *fdc) 876 { 877 ddi_device_acc_attr_t attr; 878 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 879 /* DDI_NEVERSWAP_ACC since the controller has a byte interface. */ 880 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 881 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 882 883 FDERRPRINT(FDEP_L1, FDEM_ATTA, 884 (C, "fdattach_det_cltr: start \n")); 885 886 /* 887 * First, map in the controller's registers 888 * The controller has an 8-bit interface, so byte 889 * swapping isn't needed 890 */ 891 892 if (ddi_regs_map_setup(dip, 0, (caddr_t *)&fdc->c_reg, 893 0, sizeof (union fdcreg), 894 &attr, 895 &fdc->c_handlep_cont)) { 896 return (DDI_FAILURE); 897 } 898 899 FDERRPRINT(FDEP_L1, FDEM_ATTA, 900 (C, "fdattach_det_cltr: mapped floppy regs\n")); 901 902 903 /* 904 * Set platform specific characteristics based on the device-tree 905 * node name. 906 */ 907 908 909 if (strcmp(ddi_get_name(dip), "SUNW,fdtwo") == 0) { 910 fdc->c_fdtype |= FDCTYPE_SLAVIO; 911 fdc->c_fdtype |= FDCTYPE_82077; 912 fdc->c_auxiova = fd_getauxiova(dip); 913 fdc->c_auxiodata = (uchar_t)(AUX_MBO4M|AUX_TC4M); 914 fdc->c_auxiodata2 = (uchar_t)AUX_TC4M; 915 FDERRPRINT(FDEP_L1, FDEM_ATTA, 916 (C, "fdattach: slavio will be used!\n")); 917 918 919 /* 920 * Check the binding name to identify whether it is a South bridge based 921 * system or not. 922 */ 923 } else if (strcmp(ddi_get_name(dip), "pnpALI,1533,0") == 0) { 924 925 fdc->c_fdtype |= FDCTYPE_SB; 926 fdc->c_fdtype |= FDCTYPE_82077; 927 fdc->c_fdtype |= FDCTYPE_DMA; 928 929 FDERRPRINT(FDEP_L1, FDEM_ATTA, 930 (C, "fdattach: southbridge will be used!\n")); 931 932 /* 933 * The driver assumes high density characteristics until 934 * the diskette is looked at. 935 */ 936 937 fdc->c_fdtype |= FDCTYPE_DMA8237; 938 FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: DMA used\n")); 939 940 941 } else if (strcmp(ddi_get_name(dip), "fdthree") == 0) { 942 943 fdc->c_fdtype |= FDCTYPE_CHEERIO; 944 fdc->c_fdtype |= FDCTYPE_82077; 945 946 FDERRPRINT(FDEP_L1, FDEM_ATTA, 947 (C, "fdattach: cheerio will be used!\n")); 948 /* 949 * The cheerio auxio register should be memory mapped. The 950 * auxio register on other platforms is shared and mapped 951 * elsewhere in the kernel 952 */ 953 if (ddi_regs_map_setup(dip, 2, (caddr_t *)&fdc->c_auxio_reg, 954 0, sizeof (uint_t), &attr, &fdc->c_handlep_aux)) { 955 return (DDI_FAILURE); 956 } 957 958 /* 959 * The driver assumes high density characteristics until 960 * the diskette is looked at. 961 */ 962 Set_auxio(fdc, AUX_HIGH_DENSITY); 963 FDERRPRINT(FDEP_L1, FDEM_ATTA, 964 (C, "fdattach: auxio register 0x%x\n", 965 *fdc->c_auxio_reg)); 966 967 fdc->c_fdtype |= FDCTYPE_DMA; 968 FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_attach: DMA used\n")); 969 970 } 971 972 if (fdc->c_fdtype == 0) { 973 FDERRPRINT(FDEP_L1, FDEM_ATTA, 974 (C, "fdattach: no controller!\n")); 975 return (DDI_FAILURE); 976 } else { 977 return (0); 978 } 979 } 980 981 982 /* 983 * Register the floppy interrupts 984 */ 985 static int 986 fd_attach_register_interrupts(dev_info_t *dip, struct fdctlr *fdc, int *hard) 987 { 988 ddi_iblock_cookie_t iblock_cookie_soft; 989 int status; 990 991 /* 992 * First call ddi_get_iblock_cookie() to retrieve the 993 * the interrupt block cookie so that the mutexes may 994 * be initialized before adding the interrupt. If the 995 * mutexes are initialized after adding the interrupt, there 996 * could be a race condition. 997 */ 998 if (ddi_get_iblock_cookie(dip, 0, &fdc->c_block) != DDI_SUCCESS) { 999 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1000 (C, "fdattach: ddi_get_iblock_cookie failed\n")); 1001 return (DDI_FAILURE); 1002 1003 } 1004 1005 /* Initialize high level mutex */ 1006 mutex_init(&fdc->c_hilock, NULL, MUTEX_DRIVER, fdc->c_block); 1007 1008 /* 1009 * Try to register fast trap handler, if unable try standard 1010 * interrupt handler, else bad 1011 */ 1012 1013 if (fdc->c_fdtype & FDCTYPE_DMA) { 1014 if (ddi_add_intr(dip, 0, &fdc->c_block, 0, 1015 fdintr_dma, (caddr_t)0) == DDI_SUCCESS) { 1016 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1017 (C, "fdattach: standard intr\n")); 1018 1019 /* 1020 * When DMA is used, the low level lock 1021 * is used in the hard interrupt handler. 1022 */ 1023 mutex_init(&fdc->c_lolock, NULL, 1024 MUTEX_DRIVER, fdc->c_block); 1025 1026 *hard = 1; 1027 } else { 1028 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1029 (C, "fdattach: can't add dma intr\n")); 1030 1031 mutex_destroy(&fdc->c_hilock); 1032 1033 return (DDI_FAILURE); 1034 } 1035 } else { 1036 /* 1037 * Platforms that don't support DMA have both hard 1038 * and soft interrupts. 1039 */ 1040 if (ddi_add_intr(dip, 0, &fdc->c_block, 0, 1041 fd_intr, (caddr_t)0) == DDI_SUCCESS) { 1042 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1043 (C, "fdattach: standard intr\n")); 1044 *hard = 1; 1045 1046 /* fast traps are not enabled */ 1047 fdc->c_fasttrap = 0; 1048 1049 } else { 1050 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1051 (C, "fdattach: can't add intr\n")); 1052 1053 mutex_destroy(&fdc->c_hilock); 1054 1055 return (DDI_FAILURE); 1056 } 1057 1058 1059 /* 1060 * Initialize the soft interrupt handler. First call 1061 * ddi_get_soft_iblock_cookie() so that the mutex may 1062 * be initialized before the handler is added. 1063 */ 1064 status = ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_LOW, 1065 &iblock_cookie_soft); 1066 1067 1068 if (status != DDI_SUCCESS) { 1069 mutex_destroy(&fdc->c_hilock); 1070 return (DDI_FAILURE); 1071 } 1072 1073 /* 1074 * Initialize low level mutex which is used in the soft 1075 * interrupt handler 1076 */ 1077 mutex_init(&fdc->c_lolock, NULL, MUTEX_DRIVER, 1078 iblock_cookie_soft); 1079 1080 if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &fdc->c_softid, 1081 NULL, NULL, 1082 fd_lointr, 1083 (caddr_t)fdc) != DDI_SUCCESS) { 1084 1085 mutex_destroy(&fdc->c_hilock); 1086 mutex_destroy(&fdc->c_lolock); 1087 1088 return (DDI_FAILURE); 1089 } 1090 } 1091 1092 fdc->c_intrstat = kstat_create("fd", 0, "fdc0", "controller", 1093 KSTAT_TYPE_INTR, 1, KSTAT_FLAG_PERSISTENT); 1094 if (fdc->c_intrstat) { 1095 fdc->c_hiintct = &KIOIP->intrs[KSTAT_INTR_HARD]; 1096 kstat_install(fdc->c_intrstat); 1097 } 1098 1099 /* condition variable to wait on while an io transaction occurs */ 1100 cv_init(&fdc->c_iocv, NULL, CV_DRIVER, NULL); 1101 1102 /* condition variable for the csb */ 1103 cv_init(&fdc->c_csbcv, NULL, CV_DRIVER, NULL); 1104 1105 /* condition variable for motor on waiting period */ 1106 cv_init(&fdc->c_motoncv, NULL, CV_DRIVER, NULL); 1107 1108 /* semaphore to serialize opens and closes */ 1109 sema_init(&fdc->c_ocsem, 1, NULL, SEMA_DRIVER, NULL); 1110 1111 /* condition variable to wait on suspended floppy controller. */ 1112 cv_init(&fdc->c_suspend_cv, NULL, CV_DRIVER, NULL); 1113 1114 return (0); 1115 } 1116 1117 /* 1118 * Make sure the drive is present 1119 * - acquires the low level lock 1120 */ 1121 static int 1122 fd_attach_check_drive(struct fdctlr *fdc) 1123 { 1124 int tmp_fderrlevel; 1125 int unit = fdc->c_un->un_unit_no; 1126 1127 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1128 (C, "fd_attach_check_drive\n")); 1129 1130 1131 mutex_enter(&fdc->c_lolock); 1132 switch (fdc->c_fdtype & FDCTYPE_CTRLMASK) { 1133 1134 /* insure that the eject line is reset */ 1135 case FDCTYPE_82077: 1136 1137 /* 1138 * Everything but the motor enable, drive select, 1139 * and reset bits are turned off. These three 1140 * bits remain as they are. 1141 */ 1142 /* LINTED */ 1143 Set_dor(fdc, ~((MOTEN(unit))|DRVSEL|RESET), 0); 1144 1145 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1146 (C, "fdattach: Dor 0x%x\n", Dor(fdc))); 1147 1148 drv_usecwait(5); 1149 if (unit == 0) { 1150 /* LINTED */ 1151 Set_dor(fdc, RESET|DRVSEL, 1); 1152 } else { 1153 1154 /* LINTED */ 1155 Set_dor(fdc, DRVSEL, 0); 1156 /* LINTED */ 1157 Set_dor(fdc, RESET, 1); 1158 } 1159 1160 drv_usecwait(5); 1161 1162 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1163 (C, "fdattach: Dor 0x%x\n", Dor(fdc))); 1164 1165 if (!((fdc->c_fdtype & FDCTYPE_CHEERIO) || 1166 (fdc->c_fdtype & FDCTYPE_SB))) { 1167 set_auxioreg(AUX_TC4M, 0); 1168 } 1169 break; 1170 default: 1171 break; 1172 } 1173 1174 1175 fdgetcsb(fdc); 1176 if (fdreset(fdc) != 0) { 1177 mutex_exit(&fdc->c_lolock); 1178 return (DDI_FAILURE); 1179 } 1180 1181 1182 /* check for drive present */ 1183 1184 tmp_fderrlevel = fderrlevel; 1185 1186 1187 fderrlevel = FDEP_LMAX; 1188 1189 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1190 (C, "fdattach: call fdrecalseek\n")); 1191 1192 /* Make sure the drive is present */ 1193 if (fdrecalseek(fdc, unit, -1, 0) != 0) { 1194 timeout_id_t timeid = fdc->c_mtimeid; 1195 fderrlevel = tmp_fderrlevel; 1196 fdc->c_mtimeid = 0; 1197 mutex_exit(&fdc->c_lolock); 1198 1199 1200 /* Do not hold the mutex over the call to untimeout */ 1201 if (timeid) { 1202 (void) untimeout(timeid); 1203 } 1204 1205 FDERRPRINT(FDEP_L2, FDEM_ATTA, 1206 (C, "fd_attach: no drive?\n")); 1207 1208 return (DDI_FAILURE); 1209 } 1210 1211 fderrlevel = tmp_fderrlevel; 1212 1213 fdselect(fdc, unit, 0); /* deselect drive zero (used in fdreset) */ 1214 fdretcsb(fdc); 1215 mutex_exit(&fdc->c_lolock); 1216 1217 return (0); 1218 } 1219 1220 /* 1221 * Clean up routine used by fd_detach and fd_attach 1222 * 1223 * Note: if the soft id is non-zero, then ddi_add_softintr() completed 1224 * successfully. I can not make the same assumption about the iblock_cookie 1225 * for the high level interrupt handler. So, the hard parameter indicates 1226 * whether or not a high level interrupt handler has been added. 1227 * 1228 * If the locks parameter is nonzero, then all mutexes, semaphores and 1229 * condition variables will be destroyed. 1230 * 1231 * Does not assume the low level mutex is held. 1232 * 1233 */ 1234 static void 1235 fd_cleanup(dev_info_t *dip, struct fdctlr *fdc, int hard, int locks) 1236 { 1237 1238 1239 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1240 (C, "fd_cleanup instance: %d ctlr: 0x%p\n", 1241 ddi_get_instance(dip), (void *)fdc)); 1242 1243 1244 if (fdc == NULL) { 1245 return; 1246 } 1247 1248 /* 1249 * Remove interrupt handlers first before anything else 1250 * is deallocated. 1251 */ 1252 1253 /* Remove hard interrupt if one is registered */ 1254 if (hard) { 1255 ddi_remove_intr(dip, (uint_t)0, fdc->c_block); 1256 } 1257 1258 /* Remove soft interrupt if one is registered */ 1259 if (fdc->c_softid != NULL) 1260 ddi_remove_softintr(fdc->c_softid); 1261 1262 1263 /* Remove timers */ 1264 if (fdc->c_fdtype & FDCTYPE_82077) { 1265 if (fdc->c_mtimeid) 1266 (void) untimeout(fdc->c_mtimeid); 1267 /* 1268 * Need to turn off motor (includes select/LED for South Bridge 1269 * chipset) just in case it was on when timer was removed 1270 */ 1271 fdmotoff(fdc); 1272 } 1273 if (fdc->c_timeid) 1274 (void) untimeout(fdc->c_timeid); 1275 1276 1277 /* Remove memory handles */ 1278 if (fdc->c_handlep_cont) 1279 ddi_regs_map_free(&fdc->c_handlep_cont); 1280 1281 if (fdc->c_handlep_aux) 1282 ddi_regs_map_free(&fdc->c_handlep_aux); 1283 1284 if (fdc->c_handlep_dma) 1285 ddi_regs_map_free(&fdc->c_handlep_dma); 1286 1287 if (fdc->c_dma_buf_handle != NULL) 1288 ddi_dma_mem_free(&fdc->c_dma_buf_handle); 1289 1290 if (fdc->c_dmahandle != NULL) 1291 ddi_dma_free_handle(&fdc->c_dmahandle); 1292 1293 1294 /* Remove all minor nodes */ 1295 ddi_remove_minor_node(dip, NULL); 1296 1297 1298 1299 /* Remove unit structure if one exists */ 1300 if (fdc->c_un != (struct fdunit *)NULL) { 1301 1302 ASSERT(!mutex_owned(&fdc->c_lolock)); 1303 1304 if (fdc->c_un->un_iostat) 1305 kstat_delete(fdc->c_un->un_iostat); 1306 fdc->c_un->un_iostat = NULL; 1307 1308 if (fdc->c_un->un_chars) 1309 kmem_free(fdc->c_un->un_chars, sizeof (struct fd_char)); 1310 1311 if (fdc->c_un->un_drive) 1312 kmem_free(fdc->c_un->un_drive, 1313 sizeof (struct fd_drive)); 1314 1315 kmem_free((caddr_t)fdc->c_un, sizeof (struct fdunit)); 1316 } 1317 1318 if (fdc->c_intrstat) { 1319 FDERRPRINT(FDEP_L1, FDEM_ATTA, 1320 (C, "fd_cleanup: delete intrstat\n")); 1321 1322 kstat_delete(fdc->c_intrstat); 1323 } 1324 1325 fdc->c_intrstat = NULL; 1326 1327 if (locks) { 1328 cv_destroy(&fdc->c_iocv); 1329 cv_destroy(&fdc->c_csbcv); 1330 cv_destroy(&fdc->c_motoncv); 1331 cv_destroy(&fdc->c_suspend_cv); 1332 sema_destroy(&fdc->c_ocsem); 1333 mutex_destroy(&fdc->c_hilock); 1334 mutex_destroy(&fdc->c_lolock); 1335 } 1336 1337 1338 fdctlrs = fdc->c_next; 1339 kmem_free(fdc, sizeof (*fdc)); 1340 1341 1342 } 1343 1344 1345 static int 1346 fd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1347 { 1348 int instance = ddi_get_instance(dip); 1349 struct fdctlr *fdc = fd_getctlr(instance << FDINSTSHIFT); 1350 timeout_id_t c_mtimeid; 1351 1352 FDERRPRINT(FDEP_L1, FDEM_ATTA, (C, "fd_detach\n")); 1353 1354 switch (cmd) { 1355 1356 case DDI_DETACH: 1357 /* 1358 * The hard parameter is set to 1. If detach is called, then 1359 * attach must have passed meaning that the high level 1360 * interrupt handler was successfully added. 1361 * Similarly, the locks parameter is also set to 1. 1362 */ 1363 fd_cleanup(dip, fdc, 1, 1); 1364 1365 ddi_prop_remove_all(dip); 1366 1367 return (DDI_SUCCESS); 1368 1369 case DDI_SUSPEND: 1370 if (!fdc) 1371 return (DDI_FAILURE); 1372 1373 1374 mutex_enter(&fdc->c_lolock); 1375 fdgetcsb(fdc); /* Wait for I/O to finish */ 1376 c_mtimeid = fdc->c_mtimeid; 1377 fdretcsb(fdc); 1378 mutex_exit(&fdc->c_lolock); 1379 1380 (void) untimeout(c_mtimeid); 1381 /* 1382 * After suspend, the system could be powered off. 1383 * When it is later powered on the southbridge floppy 1384 * controller will tristate the interrupt line causing 1385 * continuous dma interrupts. 1386 * To avoid getting continuous fd interrupts we will remove the 1387 * dma interrupt handler installed. We will re-install the 1388 * handler when we RESUME. 1389 */ 1390 if (fdc->c_fdtype & FDCTYPE_SB) 1391 ddi_remove_intr(dip, 0, fdc->c_block); 1392 1393 fdc->c_un->un_state = FD_STATE_SUSPENDED; 1394 1395 return (DDI_SUCCESS); 1396 1397 default: 1398 return (DDI_FAILURE); 1399 } 1400 } 1401 1402 /* ARGSUSED */ 1403 static int 1404 fd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 1405 { 1406 register struct fdctlr *fdc; 1407 register int error; 1408 1409 switch (infocmd) { 1410 1411 case DDI_INFO_DEVT2DEVINFO: 1412 if ((fdc = fd_getctlr((dev_t)arg)) == NULL) { 1413 error = DDI_FAILURE; 1414 } else { 1415 *result = fdc->c_dip; 1416 error = DDI_SUCCESS; 1417 } 1418 break; 1419 1420 case DDI_INFO_DEVT2INSTANCE: 1421 *result = 0; 1422 error = DDI_SUCCESS; 1423 break; 1424 1425 default: 1426 error = DDI_FAILURE; 1427 } 1428 return (error); 1429 } 1430 1431 /* 1432 * property operation routine. return the number of blocks for the partition 1433 * in question or forward the request to the property facilities. 1434 */ 1435 static int 1436 fd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 1437 char *name, caddr_t valuep, int *lengthp) 1438 { 1439 struct fdunit *un; 1440 struct fdctlr *fdc; 1441 uint64_t nblocks64; 1442 1443 /* 1444 * Our dynamic properties are all device specific and size oriented. 1445 * Requests issued under conditions where size is valid are passed 1446 * to ddi_prop_op_nblocks with the size information, otherwise the 1447 * request is passed to ddi_prop_op. 1448 */ 1449 if (dev == DDI_DEV_T_ANY) { 1450 pass: return (ddi_prop_op(dev, dip, prop_op, mod_flags, 1451 name, valuep, lengthp)); 1452 } else { 1453 fdc = fd_getctlr(dev); 1454 if (fdc == NULL) 1455 goto pass; 1456 1457 /* we have size if diskette opened and label read */ 1458 un = fdc->c_un; 1459 if ((un == NULL) || !fd_unit_is_open(fdc->c_un)) 1460 goto pass; 1461 1462 /* get nblocks value */ 1463 nblocks64 = (ulong_t) 1464 un->un_label.dkl_map[FDPARTITION(dev)].dkl_nblk; 1465 1466 return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags, 1467 name, valuep, lengthp, nblocks64)); 1468 } 1469 } 1470 1471 /* ARGSUSED3 */ 1472 static int 1473 fd_open(dev_t *devp, int flag, int otyp, cred_t *cred_p) 1474 { 1475 dev_t dev; 1476 int part; 1477 struct fdctlr *fdc; 1478 struct fdunit *un; 1479 struct dk_map32 *dkm; 1480 uchar_t pbit; 1481 int err, part_is_open; 1482 int unit; 1483 1484 dev = *devp; 1485 fdc = fd_getctlr(dev); 1486 if ((fdc == NULL) || ((un = fdc->c_un) == NULL)) { 1487 return (ENXIO); 1488 } 1489 1490 unit = fdc->c_un->un_unit_no; 1491 1492 /* 1493 * Serialize opens/closes 1494 */ 1495 1496 sema_p(&fdc->c_ocsem); 1497 1498 /* check partition */ 1499 part = FDPARTITION(dev); 1500 pbit = 1 << part; 1501 dkm = &un->un_label.dkl_map[part]; 1502 if (dkm->dkl_nblk == 0) { 1503 sema_v(&fdc->c_ocsem); 1504 return (ENXIO); 1505 } 1506 1507 FDERRPRINT(FDEP_L1, FDEM_OPEN, 1508 (C, "fdopen: ctlr %d unit %d part %d\n", 1509 ddi_get_instance(fdc->c_dip), unit, part)); 1510 1511 FDERRPRINT(FDEP_L1, FDEM_OPEN, 1512 (C, "fdopen: flag 0x%x", flag)); 1513 1514 1515 /* 1516 * Insure that drive is present with a recalibrate on first open. 1517 */ 1518 (void) pm_busy_component(fdc->c_dip, 0); 1519 1520 mutex_enter(&fdc->c_lolock); 1521 1522 CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc); 1523 1524 if (fdc->c_un->un_state == FD_STATE_STOPPED) { 1525 mutex_exit(&fdc->c_lolock); 1526 if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON)) 1527 != DDI_SUCCESS) { 1528 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power change \ 1529 failed. \n")); 1530 1531 sema_v(&fdc->c_ocsem); 1532 (void) pm_idle_component(fdc->c_dip, 0); 1533 return (EIO); 1534 } 1535 mutex_enter(&fdc->c_lolock); 1536 } 1537 if (fd_unit_is_open(un) == 0) { 1538 fdgetcsb(fdc); 1539 /* 1540 * no check changed! 1541 */ 1542 err = fdrecalseek(fdc, unit, -1, 0); 1543 fdretcsb(fdc); 1544 if (err) { 1545 FDERRPRINT(FDEP_L3, FDEM_OPEN, 1546 (C, "fd%d: drive not ready\n", 0)); 1547 /* deselect drv on last close */ 1548 fdselect(fdc, unit, 0); 1549 mutex_exit(&fdc->c_lolock); 1550 sema_v(&fdc->c_ocsem); 1551 (void) pm_idle_component(fdc->c_dip, 0); 1552 return (EIO); 1553 } 1554 } 1555 1556 /* 1557 * Check for previous exclusive open, or trying to exclusive open 1558 */ 1559 if (otyp == OTYP_LYR) { 1560 part_is_open = (un->un_lyropen[part] != 0); 1561 } else { 1562 part_is_open = fd_part_is_open(un, part); 1563 } 1564 if ((un->un_exclmask & pbit) || ((flag & FEXCL) && part_is_open)) { 1565 mutex_exit(&fdc->c_lolock); 1566 sema_v(&fdc->c_ocsem); 1567 FDERRPRINT(FDEP_L2, FDEM_OPEN, (C, "fd:just return\n")); 1568 (void) pm_idle_component(fdc->c_dip, 0); 1569 return (EBUSY); 1570 } 1571 1572 /* don't attempt access, just return successfully */ 1573 if (flag & (FNDELAY | FNONBLOCK)) { 1574 FDERRPRINT(FDEP_L2, FDEM_OPEN, 1575 (C, "fd: return busy..\n")); 1576 goto out; 1577 } 1578 1579 fdc->c_csb.csb_unit = (uchar_t)unit; 1580 if (fdgetlabel(fdc, unit)) { 1581 /* didn't find label (couldn't read anything) */ 1582 FDERRPRINT(FDEP_L3, FDEM_OPEN, 1583 (C, 1584 "fd%d: unformatted diskette or no diskette in the drive\n", 1585 0)); 1586 if (fd_unit_is_open(un) == 0) { 1587 /* deselect drv on last close */ 1588 fdselect(fdc, unit, 0); 1589 } 1590 1591 mutex_exit(&fdc->c_lolock); 1592 sema_v(&fdc->c_ocsem); 1593 (void) pm_idle_component(fdc->c_dip, 0); 1594 return (EIO); 1595 } 1596 1597 /* 1598 * if opening for writing, check write protect on diskette 1599 */ 1600 if (flag & FWRITE) { 1601 fdgetcsb(fdc); 1602 err = fdsensedrv(fdc, unit) & WP_SR3; 1603 fdretcsb(fdc); 1604 if (err) { 1605 if (fd_unit_is_open(un) == 0) 1606 fdselect(fdc, unit, 0); 1607 mutex_exit(&fdc->c_lolock); 1608 sema_v(&fdc->c_ocsem); 1609 (void) pm_idle_component(fdc->c_dip, 0); 1610 return (EROFS); 1611 } 1612 } 1613 1614 out: 1615 /* 1616 * mark open as having succeeded 1617 */ 1618 if (flag & FEXCL) { 1619 un->un_exclmask |= pbit; 1620 } 1621 if (otyp == OTYP_LYR) { 1622 un->un_lyropen[part]++; 1623 } else { 1624 un->un_regopen[otyp] |= pbit; 1625 } 1626 mutex_exit(&fdc->c_lolock); 1627 sema_v(&fdc->c_ocsem); 1628 (void) pm_idle_component(fdc->c_dip, 0); 1629 return (0); 1630 } 1631 /* 1632 * fd_part_is_open 1633 * return 1 if the partition is open 1634 * return 0 otherwise 1635 */ 1636 static int 1637 fd_part_is_open(struct fdunit *un, int part) 1638 { 1639 int i; 1640 for (i = 0; i < OTYPCNT - 1; i++) 1641 if (un->un_regopen[i] & (1 << part)) 1642 return (1); 1643 return (0); 1644 } 1645 1646 1647 /* ARGSUSED */ 1648 static int 1649 fd_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 1650 { 1651 int unit, part_is_closed, part; 1652 register struct fdctlr *fdc; 1653 register struct fdunit *un; 1654 1655 fdc = fd_getctlr(dev); 1656 if (!fdc || !(un = fdc->c_un)) 1657 return (ENXIO); 1658 1659 1660 unit = fdc->c_un->un_unit_no; 1661 FDERRPRINT(FDEP_L1, FDEM_CLOS, (C, "fd_close\n")); 1662 part = FDPARTITION(dev); 1663 1664 sema_p(&fdc->c_ocsem); 1665 mutex_enter(&fdc->c_lolock); 1666 1667 if (otyp == OTYP_LYR) { 1668 un->un_lyropen[part]--; 1669 part_is_closed = (un->un_lyropen[part] == 0); 1670 } else { 1671 un->un_regopen[otyp] &= ~(1<<part); 1672 part_is_closed = 1; 1673 } 1674 if (part_is_closed) 1675 un->un_exclmask &= ~(1<<part); 1676 1677 if (fd_unit_is_open(un) == 0) { 1678 /* deselect drive on last close */ 1679 fdselect(fdc, unit, 0); 1680 un->un_flags &= ~FDUNIT_CHANGED; 1681 } 1682 mutex_exit(&fdc->c_lolock); 1683 sema_v(&fdc->c_ocsem); 1684 1685 return (0); 1686 } 1687 1688 /* 1689 * fd_strategy 1690 * checks operation, hangs buf struct off fdctlr, calls fdstart 1691 * if not already busy. Note that if we call start, then the operation 1692 * will already be done on return (start sleeps). 1693 */ 1694 static int 1695 fd_strategy(register struct buf *bp) 1696 { 1697 struct fdctlr *fdc; 1698 struct fdunit *un; 1699 uint_t phys_blkno; 1700 struct dk_map32 *dkm; 1701 1702 FDERRPRINT(FDEP_L1, FDEM_STRA, 1703 (C, "fd_strategy: bp = 0x%p, dev = 0x%lx\n", 1704 (void *)bp, bp->b_edev)); 1705 FDERRPRINT(FDEP_L1, FDEM_STRA, 1706 (C, "b_blkno=%x b_flags=%x b_count=%x\n", 1707 (int)bp->b_blkno, bp->b_flags, (int)bp->b_bcount)); 1708 fdc = fd_getctlr(bp->b_edev); 1709 un = fdc->c_un; 1710 dkm = &un->un_label.dkl_map[FDPARTITION(bp->b_edev)]; 1711 1712 /* 1713 * If it's medium density and the block no. isn't a multiple 1714 * of 1K, then return an error. 1715 */ 1716 if (un->un_chars->fdc_medium) { 1717 phys_blkno = (uint_t)bp->b_blkno >> 1; 1718 if (bp->b_blkno & 1) { 1719 FDERRPRINT(FDEP_L3, FDEM_STRA, 1720 (C, "b_blkno=0x%lx is not 1k aligned\n", 1721 (long)bp->b_blkno)); 1722 bp->b_error = EINVAL; 1723 bp->b_resid = bp->b_bcount; 1724 bp->b_flags |= B_ERROR; 1725 biodone(bp); 1726 return (0); 1727 } 1728 } else { 1729 phys_blkno = (uint_t)bp->b_blkno; 1730 } 1731 1732 1733 /* If the block number is past the end, return an error */ 1734 if ((phys_blkno > dkm->dkl_nblk)) { 1735 FDERRPRINT(FDEP_L3, FDEM_STRA, 1736 (C, "fd%d: block %ld is past the end! (nblk=%d)\n", 1737 0, (long)bp->b_blkno, dkm->dkl_nblk)); 1738 bp->b_error = ENOSPC; 1739 bp->b_resid = bp->b_bcount; 1740 bp->b_flags |= B_ERROR; 1741 biodone(bp); 1742 return (0); 1743 } 1744 1745 /* if at end of file, skip out now */ 1746 if (phys_blkno == dkm->dkl_nblk) { 1747 FDERRPRINT(FDEP_L1, FDEM_STRA, 1748 (C, "b_blkno is at the end!\n")); 1749 1750 if ((bp->b_flags & B_READ) == 0) { 1751 /* a write needs to get an error! */ 1752 bp->b_error = ENOSPC; 1753 bp->b_flags |= B_ERROR; 1754 1755 FDERRPRINT(FDEP_L1, FDEM_STRA, 1756 (C, "block is at end and this is a write\n")); 1757 1758 } 1759 1760 bp->b_resid = bp->b_bcount; 1761 biodone(bp); 1762 return (0); 1763 } 1764 1765 /* if operation not a multiple of sector size, is error! */ 1766 if (bp->b_bcount % un->un_chars->fdc_sec_size) { 1767 FDERRPRINT(FDEP_L3, FDEM_STRA, 1768 (C, "fd%d: requested transfer size(0x%lx) is not" 1769 " multiple of sector size(0x%x)\n", 0, 1770 bp->b_bcount, un->un_chars->fdc_sec_size)); 1771 FDERRPRINT(FDEP_L3, FDEM_STRA, 1772 (C, " b_blkno=0x%lx b_flags=0x%x\n", 1773 (long)bp->b_blkno, bp->b_flags)); 1774 bp->b_error = EINVAL; 1775 bp->b_resid = bp->b_bcount; 1776 bp->b_flags |= B_ERROR; 1777 biodone(bp); 1778 return (0); 1779 1780 } 1781 1782 /* 1783 * Put the buf request in the controller's queue, FIFO. 1784 */ 1785 bp->av_forw = 0; 1786 sema_p(&fdc->c_ocsem); 1787 1788 (void) pm_busy_component(fdc->c_dip, 0); 1789 1790 mutex_enter(&fdc->c_lolock); 1791 1792 CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc); 1793 1794 if (fdc->c_un->un_state == FD_STATE_STOPPED) { 1795 mutex_exit(&fdc->c_lolock); 1796 if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON)) 1797 != DDI_SUCCESS) { 1798 sema_v(&fdc->c_ocsem); 1799 (void) pm_idle_component(fdc->c_dip, 0); 1800 bp->b_error = EIO; 1801 bp->b_resid = bp->b_bcount; 1802 bp->b_flags |= B_ERROR; 1803 biodone(bp); 1804 return (0); 1805 } else { 1806 mutex_enter(&fdc->c_lolock); 1807 } 1808 } 1809 if (un->un_iostat) { 1810 kstat_waitq_enter(KIOSP); 1811 } 1812 if (fdc->c_actf) 1813 fdc->c_actl->av_forw = bp; 1814 else 1815 fdc->c_actf = bp; 1816 fdc->c_actl = bp; 1817 1818 1819 /* call fdstart to start the transfer */ 1820 fdstart(fdc); 1821 1822 mutex_exit(&fdc->c_lolock); 1823 sema_v(&fdc->c_ocsem); 1824 (void) pm_idle_component(fdc->c_dip, 0); 1825 return (0); 1826 } 1827 1828 /* ARGSUSED2 */ 1829 static int 1830 fd_read(dev_t dev, struct uio *uio, cred_t *cred_p) 1831 { 1832 FDERRPRINT(FDEP_L1, FDEM_RDWR, (C, "fd_read\n")); 1833 return (physio(fd_strategy, NULL, dev, B_READ, minphys, uio)); 1834 } 1835 1836 /* ARGSUSED2 */ 1837 static int 1838 fd_write(dev_t dev, struct uio *uio, cred_t *cred_p) 1839 { 1840 FDERRPRINT(FDEP_L1, FDEM_RDWR, (C, "fd_write\n")); 1841 return (physio(fd_strategy, NULL, dev, B_WRITE, minphys, uio)); 1842 } 1843 1844 static void 1845 fdmotoff(void *arg) 1846 { 1847 struct fdctlr *fdc = arg; 1848 int unit = fdc->c_un->un_unit_no; 1849 1850 mutex_enter(&fdc->c_lolock); 1851 1852 /* Just return if we're about to call untimeout */ 1853 if (fdc->c_mtimeid == 0) { 1854 mutex_exit(&fdc->c_lolock); 1855 return; 1856 } 1857 1858 FDERRPRINT(FDEP_L1, FDEM_MOFF, (C, "fdmotoff\n")); 1859 1860 fdc->c_mtimeid = 0; 1861 1862 if (!(Msr(fdc) & CB) && (Dor(fdc) & (MOTEN(unit)))) { 1863 /* LINTED */ 1864 Set_dor(fdc, MOTEN(unit), 0); 1865 } 1866 1867 mutex_exit(&fdc->c_lolock); 1868 } 1869 1870 /* ARGSUSED */ 1871 static int 1872 fd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, 1873 cred_t *cred_p, int *rval_p) 1874 { 1875 union { 1876 struct dk_cinfo dki; 1877 struct dk_geom dkg; 1878 struct dk_allmap32 dka; 1879 struct fd_char fdchar; 1880 struct fd_drive drvchar; 1881 int temp; 1882 } cpy; 1883 1884 struct vtoc vtoc; 1885 struct fdunit *un; 1886 struct fdctlr *fdc; 1887 int unit, dkunit; 1888 int err = 0; 1889 uint_t sec_size; 1890 enum dkio_state state; 1891 int transfer_rate; 1892 1893 FDERRPRINT(FDEP_L1, FDEM_IOCT, 1894 (C, "fd_ioctl: cmd 0x%x, arg 0x%lx\n", cmd, (long)arg)); 1895 1896 /* The minor number should always be 0 */ 1897 if (FDUNIT(dev) != 0) 1898 return (ENXIO); 1899 1900 fdc = fd_getctlr(dev); 1901 unit = fdc->c_un->un_unit_no; 1902 un = fdc->c_un; 1903 sec_size = un->un_chars->fdc_sec_size; 1904 bzero(&cpy, sizeof (cpy)); 1905 1906 switch (cmd) { 1907 case DKIOCINFO: 1908 cpy.dki.dki_addr = 0; 1909 1910 /* 1911 * The meaning of the dki_slave and dki_unit fields 1912 * is unclear. The sparc floppy driver follows the same 1913 * convention as sd.c in that the instance number is 1914 * returned in the dki_cnum field. The dki_slave field is 1915 * ignored. 1916 * 1917 * The dki_cnum contains the controller instance 1918 * and its value can be any positive number. Even 1919 * though currently Sparc platforms only support 1920 * one controller, the controller instance number 1921 * can be any number since it is assigned by the 1922 * system depending on the device properties. 1923 */ 1924 1925 cpy.dki.dki_cnum = FDCTLR(dev); 1926 1927 /* 1928 * Sparc platforms support only one floppy drive. 1929 * The device node for the controller is the same as 1930 * the device node for the drive. The x86 driver is 1931 * different in that it has a node for the controller 1932 * and a child node for each drive. Since Sparc supports 1933 * only one drive, the unit number will always be zero. 1934 */ 1935 1936 cpy.dki.dki_unit = FDUNIT(dev); 1937 1938 /* 1939 * The meaning of the dki_slave field is unclear. 1940 * So, I will leave it set to 0. 1941 */ 1942 1943 cpy.dki.dki_slave = 0; 1944 1945 cpy.dki.dki_ctype = (ushort_t)-1; 1946 if (fdc->c_fdtype & FDCTYPE_82077) 1947 cpy.dki.dki_ctype = DKC_INTEL82077; 1948 cpy.dki.dki_flags = DKI_FMTTRK; 1949 cpy.dki.dki_partition = FDPARTITION(dev); 1950 cpy.dki.dki_maxtransfer = maxphys / DEV_BSIZE; 1951 if (ddi_copyout((caddr_t)&cpy.dki, (caddr_t)arg, 1952 sizeof (cpy.dki), flag)) 1953 err = EFAULT; 1954 break; 1955 case DKIOCGGEOM: 1956 cpy.dkg.dkg_ncyl = un->un_chars->fdc_ncyl; 1957 cpy.dkg.dkg_nhead = un->un_chars->fdc_nhead; 1958 cpy.dkg.dkg_nsect = un->un_chars->fdc_secptrack; 1959 cpy.dkg.dkg_intrlv = un->un_label.dkl_intrlv; 1960 cpy.dkg.dkg_rpm = un->un_label.dkl_rpm; 1961 cpy.dkg.dkg_pcyl = un->un_chars->fdc_ncyl; 1962 cpy.dkg.dkg_read_reinstruct = 1963 (int)(cpy.dkg.dkg_nsect * cpy.dkg.dkg_rpm * 4) / 60000; 1964 cpy.dkg.dkg_write_reinstruct = cpy.dkg.dkg_read_reinstruct; 1965 if (ddi_copyout((caddr_t)&cpy.dkg, (caddr_t)arg, 1966 sizeof (cpy.dkg), flag)) 1967 err = EFAULT; 1968 break; 1969 case DKIOCSGEOM: 1970 FDERRPRINT(FDEP_L3, FDEM_IOCT, 1971 (C, "fd_ioctl: DKIOCSGEOM not supported\n")); 1972 err = ENOTTY; 1973 break; 1974 1975 /* 1976 * return the map of all logical partitions 1977 */ 1978 case DKIOCGAPART: 1979 /* 1980 * We don't have anything to do if the application is ILP32 1981 * because the label map has a 32-bit format. Otherwise 1982 * convert. 1983 */ 1984 if ((flag & DATAMODEL_MASK) == DATAMODEL_ILP32) { 1985 if (ddi_copyout(&un->un_label.dkl_map, 1986 (void *)arg, sizeof (struct dk_allmap32), flag)) 1987 err = EFAULT; 1988 } 1989 #ifdef _MULTI_DATAMODEL 1990 else { 1991 struct dk_allmap dk_allmap; 1992 1993 ASSERT((flag & DATAMODEL_MASK) == DATAMODEL_LP64); 1994 for (dkunit = 0; dkunit < NDKMAP; dkunit++) { 1995 dk_allmap.dka_map[dkunit].dkl_cylno = 1996 un->un_label.dkl_map[dkunit].dkl_cylno; 1997 dk_allmap.dka_map[dkunit].dkl_nblk = 1998 un->un_label.dkl_map[dkunit].dkl_nblk; 1999 } 2000 if (ddi_copyout(&dk_allmap, (void *)arg, 2001 sizeof (struct dk_allmap), flag)) 2002 err = EFAULT; 2003 } 2004 #endif /* _MULTI_DATAMODEL */ 2005 break; 2006 2007 /* 2008 * Set the map of all logical partitions 2009 */ 2010 case DKIOCSAPART: 2011 if ((flag & DATAMODEL_MASK) == DATAMODEL_ILP32) { 2012 if (ddi_copyin((const void *)arg, &cpy.dka, 2013 sizeof (cpy.dka), flag)) 2014 return (EFAULT); 2015 else { 2016 mutex_enter(&fdc->c_lolock); 2017 for (dkunit = 0; dkunit < NDKMAP; dkunit++) { 2018 un->un_label.dkl_map[dkunit] = 2019 cpy.dka.dka_map[dkunit]; 2020 } 2021 mutex_exit(&fdc->c_lolock); 2022 } 2023 } 2024 #ifdef _MULTI_DATAMODEL 2025 else { 2026 struct dk_allmap dk_allmap; 2027 2028 ASSERT((flag & DATAMODEL_MASK) == DATAMODEL_LP64); 2029 if (ddi_copyin((const void *)arg, &dk_allmap, 2030 sizeof (dk_allmap), flag)) 2031 return (EFAULT); 2032 else { 2033 mutex_enter(&fdc->c_lolock); 2034 for (dkunit = 0; dkunit < NDKMAP; dkunit++) { 2035 un->un_label.dkl_map[dkunit].dkl_cylno = 2036 dk_allmap.dka_map[dkunit].dkl_cylno; 2037 un->un_label.dkl_map[dkunit].dkl_nblk = 2038 dk_allmap.dka_map[dkunit].dkl_nblk; 2039 } 2040 mutex_exit(&fdc->c_lolock); 2041 } 2042 } 2043 #endif /* _MULTI_DATAMODEL */ 2044 break; 2045 2046 case DKIOCGVTOC: 2047 mutex_enter(&fdc->c_lolock); 2048 2049 /* 2050 * Exit if the diskette has no label. 2051 * Also, get the label to make sure the 2052 * correct one is being used since the diskette 2053 * may have changed 2054 */ 2055 if (fdgetlabel(fdc, unit)) { 2056 mutex_exit(&fdc->c_lolock); 2057 err = EINVAL; 2058 break; 2059 } 2060 2061 /* Build a vtoc from the diskette's label */ 2062 fd_build_user_vtoc(un, &vtoc); 2063 mutex_exit(&fdc->c_lolock); 2064 2065 #ifdef _MULTI_DATAMODEL 2066 switch (ddi_model_convert_from(flag & FMODELS)) { 2067 case DDI_MODEL_ILP32: { 2068 struct vtoc32 vtoc32; 2069 2070 vtoctovtoc32(vtoc, vtoc32); 2071 if (ddi_copyout(&vtoc32, (void *)arg, 2072 sizeof (struct vtoc32), flag)) 2073 return (EFAULT); 2074 break; 2075 } 2076 2077 case DDI_MODEL_NONE: 2078 if (ddi_copyout(&vtoc, (void *)arg, 2079 sizeof (vtoc), flag)) 2080 return (EFAULT); 2081 break; 2082 } 2083 #else /* ! _MULTI_DATAMODEL */ 2084 if (ddi_copyout(&vtoc, (void *)arg, sizeof (vtoc), flag)) 2085 return (EFAULT); 2086 #endif /* _MULTI_DATAMODEL */ 2087 break; 2088 2089 case DKIOCSVTOC: 2090 2091 #ifdef _MULTI_DATAMODEL 2092 switch (ddi_model_convert_from(flag & FMODELS)) { 2093 case DDI_MODEL_ILP32: { 2094 struct vtoc32 vtoc32; 2095 2096 if (ddi_copyin((const void *)arg, &vtoc32, 2097 sizeof (struct vtoc32), flag)) { 2098 return (EFAULT); 2099 } 2100 vtoc32tovtoc(vtoc32, vtoc); 2101 break; 2102 } 2103 2104 case DDI_MODEL_NONE: 2105 if (ddi_copyin((const void *)arg, &vtoc, 2106 sizeof (vtoc), flag)) { 2107 return (EFAULT); 2108 } 2109 break; 2110 } 2111 #else /* ! _MULTI_DATAMODEL */ 2112 if (ddi_copyin((const void *)arg, &vtoc, sizeof (vtoc), flag)) 2113 return (EFAULT); 2114 #endif /* _MULTI_DATAMODEL */ 2115 2116 mutex_enter(&fdc->c_lolock); 2117 2118 /* 2119 * The characteristics structure must be filled in because 2120 * it helps build the vtoc. 2121 */ 2122 if ((un->un_chars->fdc_ncyl == 0) || 2123 (un->un_chars->fdc_nhead == 0) || 2124 (un->un_chars->fdc_secptrack == 0)) { 2125 mutex_exit(&fdc->c_lolock); 2126 err = EINVAL; 2127 break; 2128 } 2129 2130 if ((err = fd_build_label_vtoc(un, &vtoc)) != 0) { 2131 mutex_exit(&fdc->c_lolock); 2132 break; 2133 } 2134 2135 (void) pm_busy_component(fdc->c_dip, 0); 2136 2137 err = fdrw(fdc, unit, FDWRITE, 0, 0, 1, 2138 (caddr_t)&un->un_label, sizeof (struct dk_label)); 2139 mutex_exit(&fdc->c_lolock); 2140 (void) pm_idle_component(fdc->c_dip, 0); 2141 break; 2142 2143 case DKIOCSTATE: 2144 if (ddi_copyin((caddr_t)arg, (caddr_t)&state, 2145 sizeof (int), flag)) { 2146 err = EFAULT; 2147 break; 2148 } 2149 (void) pm_busy_component(fdc->c_dip, 0); 2150 2151 err = fd_check_media(dev, state); 2152 (void) pm_idle_component(fdc->c_dip, 0); 2153 2154 if (ddi_copyout((caddr_t)&un->un_media_state, 2155 (caddr_t)arg, sizeof (int), flag)) 2156 err = EFAULT; 2157 break; 2158 2159 case FDIOGCHAR: 2160 if (ddi_copyout((caddr_t)un->un_chars, (caddr_t)arg, 2161 sizeof (struct fd_char), flag)) 2162 err = EFAULT; 2163 break; 2164 2165 case FDIOSCHAR: 2166 if (ddi_copyin((caddr_t)arg, (caddr_t)&cpy.fdchar, 2167 sizeof (struct fd_char), flag)) { 2168 err = EFAULT; 2169 break; 2170 } 2171 2172 /* 2173 * Check the fields in the fdchar structure that are either 2174 * driver or controller dependent. 2175 */ 2176 2177 transfer_rate = cpy.fdchar.fdc_transfer_rate; 2178 if ((transfer_rate != 500) && (transfer_rate != 300) && 2179 (transfer_rate != 250) && (transfer_rate != 1000)) { 2180 FDERRPRINT(FDEP_L3, FDEM_IOCT, 2181 (C, "fd_ioctl: FDIOSCHAR odd transfer rate %d\n", 2182 cpy.fdchar.fdc_transfer_rate)); 2183 err = EINVAL; 2184 break; 2185 } 2186 2187 if ((cpy.fdchar.fdc_nhead < 1) || 2188 (cpy.fdchar.fdc_nhead > 2)) { 2189 FDERRPRINT(FDEP_L3, FDEM_IOCT, 2190 (C, "fd_ioctl: FDIOSCHAR bad no. of heads %d\n", 2191 cpy.fdchar.fdc_nhead)); 2192 err = EINVAL; 2193 break; 2194 } 2195 2196 /* 2197 * The number of cylinders must be between 0 and 255 2198 */ 2199 if ((cpy.fdchar.fdc_ncyl < 0) || (cpy.fdchar.fdc_ncyl > 255)) { 2200 FDERRPRINT(FDEP_L3, FDEM_IOCT, 2201 (C, "fd_ioctl: FDIOSCHAR bad cyl no %d\n", 2202 cpy.fdchar.fdc_ncyl)); 2203 err = EINVAL; 2204 break; 2205 } 2206 2207 /* Copy the fdchar structure */ 2208 2209 mutex_enter(&fdc->c_lolock); 2210 *(un->un_chars) = cpy.fdchar; 2211 2212 un->un_curfdtype = -1; 2213 2214 mutex_exit(&fdc->c_lolock); 2215 2216 break; 2217 case FDEJECT: /* eject disk */ 2218 case DKIOCEJECT: 2219 2220 /* 2221 * Fail the ioctl if auto-eject isn't supported 2222 */ 2223 if (fdc->c_un->un_drive->fdd_ejectable == 0) { 2224 2225 err = ENOSYS; 2226 2227 } else { 2228 (void) pm_busy_component(fdc->c_dip, 0); 2229 2230 mutex_enter(&fdc->c_lolock); 2231 2232 CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc); 2233 2234 if (fdc->c_un->un_state == FD_STATE_STOPPED) { 2235 mutex_exit(&fdc->c_lolock); 2236 if ((pm_raise_power(fdc->c_dip, 0, 2237 PM_LEVEL_ON)) != DDI_SUCCESS) { 2238 (void) pm_idle_component(fdc->c_dip, 0); 2239 err = EIO; 2240 } 2241 mutex_enter(&fdc->c_lolock); 2242 } 2243 } 2244 if (err == 0) { 2245 fdselect(fdc, unit, 1); 2246 fdeject(fdc, unit); 2247 mutex_exit(&fdc->c_lolock); 2248 } 2249 2250 (void) pm_idle_component(fdc->c_dip, 0); 2251 2252 /* 2253 * Make sure the drive is turned off 2254 */ 2255 if (fdc->c_fdtype & FDCTYPE_82077) { 2256 if (fdc->c_mtimeid == 0) { 2257 fdc->c_mtimeid = timeout(fdmotoff, fdc, 2258 Motoff_delay); 2259 } 2260 } 2261 2262 break; 2263 case FDGETCHANGE: /* disk changed */ 2264 2265 if (ddi_copyin((caddr_t)arg, (caddr_t)&cpy.temp, 2266 sizeof (int), flag)) { 2267 err = EFAULT; 2268 break; 2269 } 2270 2271 /* zero out the user's parameter */ 2272 cpy.temp = 0; 2273 2274 (void) pm_busy_component(fdc->c_dip, 0); 2275 2276 mutex_enter(&fdc->c_lolock); 2277 2278 CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc); 2279 2280 if (fdc->c_un->un_state == FD_STATE_STOPPED) { 2281 mutex_exit(&fdc->c_lolock); 2282 if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON)) 2283 != DDI_SUCCESS) { 2284 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power \ 2285 change failed. \n")); 2286 (void) pm_idle_component(fdc->c_dip, 0); 2287 return (EIO); 2288 } 2289 2290 mutex_enter(&fdc->c_lolock); 2291 } 2292 if (un->un_flags & FDUNIT_CHANGED) 2293 cpy.temp |= FDGC_HISTORY; 2294 else 2295 cpy.temp &= ~FDGC_HISTORY; 2296 un->un_flags &= ~FDUNIT_CHANGED; 2297 2298 if (fd_pollable) { 2299 /* 2300 * If it's a "pollable" floppy, then we don't 2301 * have to do all the fdcheckdisk nastyness to 2302 * figure out if the thing is still there. 2303 */ 2304 if (fdsense_chng(fdc, unit)) { 2305 cpy.temp |= FDGC_CURRENT; 2306 } else { 2307 cpy.temp &= ~FDGC_CURRENT; 2308 } 2309 } else { 2310 2311 if (fdsense_chng(fdc, unit)) { 2312 /* 2313 * check disk change signal is asserted. 2314 * Now find out if the floppy is 2315 * inserted 2316 */ 2317 if (fdcheckdisk(fdc, unit)) { 2318 cpy.temp |= FDGC_CURRENT; 2319 } else { 2320 /* 2321 * Yes, the floppy was 2322 * reinserted. Implies 2323 * floppy change. 2324 */ 2325 cpy.temp &= ~FDGC_CURRENT; 2326 cpy.temp |= FDGC_HISTORY; 2327 } 2328 } else { 2329 cpy.temp &= ~FDGC_CURRENT; 2330 } 2331 } 2332 2333 /* 2334 * For a pollable floppy, the floppy_change signal 2335 * reflects whether the floppy is in there or not. 2336 * We can not detect a floppy change if we don't poll 2337 * this signal when the floppy is being changed. 2338 * Because as soon as the floppy is put back, the 2339 * signal is reset. 2340 * BUT the pollable floppies are available only on 2341 * Sparcstation Voyager Voyagers (Gypsy) only and 2342 * those are motorized floppies. For motorized floppies, 2343 * the floppy can only (assuming the user doesn't use a 2344 * pin to take out the floppy) be taken out by 2345 * issuing 'eject' command which sets the 2346 * un->un_ejected flag. So, if the following 2347 * condition is true, we can assume there 2348 * was a floppy change. 2349 */ 2350 if (un->un_ejected && !(cpy.temp & FDGC_CURRENT)) { 2351 cpy.temp |= FDGC_HISTORY; 2352 } 2353 un->un_ejected = 0; 2354 2355 2356 /* return the write-protection status */ 2357 fdgetcsb(fdc); 2358 if (fdsensedrv(fdc, unit) & WP_SR3) { 2359 cpy.temp |= FDGC_CURWPROT; 2360 } 2361 fdretcsb(fdc); 2362 mutex_exit(&fdc->c_lolock); 2363 2364 if (ddi_copyout((caddr_t)&cpy.temp, (caddr_t)arg, 2365 sizeof (int), flag)) 2366 err = EFAULT; 2367 (void) pm_idle_component(fdc->c_dip, 0); 2368 break; 2369 2370 case FDGETDRIVECHAR: 2371 2372 if (ddi_copyin((caddr_t)arg, (caddr_t)&cpy.drvchar, 2373 sizeof (struct fd_drive), flag)) { 2374 err = EFAULT; 2375 break; 2376 } 2377 2378 /* 2379 * Return the ejectable value based on the FD_MANUAL_EJECT 2380 * property 2381 */ 2382 cpy.drvchar.fdd_ejectable = fdc->c_un->un_drive->fdd_ejectable; 2383 cpy.drvchar.fdd_maxsearch = nfdtypes; /* 3 - hi m lo density */ 2384 if (fd_pollable) /* pollable device */ 2385 cpy.drvchar.fdd_flags |= FDD_POLLABLE; 2386 2387 /* the rest of the fd_drive struct is meaningless to us */ 2388 2389 if (ddi_copyout((caddr_t)&cpy.drvchar, (caddr_t)arg, 2390 sizeof (struct fd_drive), flag)) 2391 err = EFAULT; 2392 break; 2393 2394 case FDSETDRIVECHAR: 2395 FDERRPRINT(FDEP_L3, FDEM_IOCT, 2396 (C, "fd_ioctl: FDSETDRIVECHAR not supportedn\n")); 2397 err = ENOTTY; 2398 break; 2399 2400 case DKIOCREMOVABLE: { 2401 int i = 1; 2402 2403 /* no brainer: floppies are always removable */ 2404 if (ddi_copyout((caddr_t)&i, (caddr_t)arg, sizeof (int), 2405 flag)) { 2406 err = EFAULT; 2407 } 2408 break; 2409 } 2410 case DKIOCGMEDIAINFO: 2411 err = fd_get_media_info(un, (caddr_t)arg, flag); 2412 break; 2413 2414 2415 case FDIOCMD: 2416 { 2417 struct fd_cmd fc; 2418 int cyl, hd, spc, spt; 2419 int nblks; /* total no. of blocks */ 2420 2421 #ifdef _MULTI_DATAMODEL 2422 switch (ddi_model_convert_from(flag & FMODELS)) { 2423 case DDI_MODEL_ILP32: { 2424 struct fd_cmd32 fc32; 2425 2426 if (ddi_copyin((const void *)arg, &fc32, 2427 sizeof (fc32), flag)) { 2428 return (EFAULT); 2429 } 2430 fc.fdc_cmd = fc32.fdc_cmd; 2431 fc.fdc_flags = fc32.fdc_flags; 2432 fc.fdc_blkno = (daddr_t)fc32.fdc_blkno; 2433 fc.fdc_secnt = fc32.fdc_secnt; 2434 fc.fdc_bufaddr = (caddr_t)(uintptr_t)fc32.fdc_bufaddr; 2435 fc.fdc_buflen = fc32.fdc_buflen; 2436 fc.fdc_cmd = fc32.fdc_cmd; 2437 2438 break; 2439 } 2440 2441 case DDI_MODEL_NONE: 2442 if (ddi_copyin((const void *)arg, &fc, 2443 sizeof (fc), flag)) { 2444 return (EFAULT); 2445 } 2446 break; 2447 } 2448 #else /* ! _MULTI_DATAMODEL */ 2449 if (ddi_copyin((const void *)arg, &fc, sizeof (fc), flag)) { 2450 return (EFAULT); 2451 } 2452 #endif /* _MULTI_DATAMODEL */ 2453 2454 if (fc.fdc_cmd == FDCMD_READ || fc.fdc_cmd == FDCMD_WRITE) { 2455 auto struct iovec aiov; 2456 auto struct uio auio; 2457 struct uio *uio = &auio; 2458 2459 spc = (fc.fdc_cmd == FDCMD_READ)? B_READ: B_WRITE; 2460 2461 bzero(&auio, sizeof (struct uio)); 2462 bzero(&aiov, sizeof (struct iovec)); 2463 aiov.iov_base = fc.fdc_bufaddr; 2464 aiov.iov_len = (uint_t)fc.fdc_secnt * sec_size; 2465 uio->uio_iov = &aiov; 2466 2467 uio->uio_iovcnt = 1; 2468 uio->uio_resid = aiov.iov_len; 2469 uio->uio_segflg = UIO_USERSPACE; 2470 FDERRPRINT(FDEP_L2, FDEM_IOCT, 2471 (C, "fd_ioctl: call physio\n")); 2472 err = physio(fd_strategy, NULL, dev, 2473 spc, minphys, uio); 2474 break; 2475 } else if (fc.fdc_cmd != FDCMD_FORMAT_TRACK) { 2476 2477 /* 2478 * The manpage states that only the FDCMD_WRITE, 2479 * FDCMD_READ, and the FDCMD_FORMAT_TR are available. 2480 */ 2481 FDERRPRINT(FDEP_L1, FDEM_IOCT, 2482 (C, "fd_ioctl: FDIOCMD invalid command\n")); 2483 err = EINVAL; 2484 break; 2485 } 2486 2487 /* The command is FDCMD_FORMAT_TRACK */ 2488 2489 spt = un->un_chars->fdc_secptrack; /* sec/trk */ 2490 spc = un->un_chars->fdc_nhead * spt; /* sec/cyl */ 2491 cyl = fc.fdc_blkno / spc; 2492 hd = (fc.fdc_blkno % spc) / spt; 2493 2494 /* 2495 * Make sure the specified block number is in the correct 2496 * range. (block numbers start at 0) 2497 */ 2498 nblks = spc * un->un_chars->fdc_ncyl; 2499 2500 if (fc.fdc_blkno < 0 || fc.fdc_blkno > (nblks - 1)) { 2501 err = EINVAL; 2502 break; 2503 } 2504 2505 (void) pm_busy_component(fdc->c_dip, 0); 2506 2507 mutex_enter(&fdc->c_lolock); 2508 CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc); 2509 if (fdc->c_un->un_state == FD_STATE_STOPPED) { 2510 mutex_exit(&fdc->c_lolock); 2511 if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON)) 2512 != DDI_SUCCESS) { 2513 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power \ 2514 change failed. \n")); 2515 (void) pm_idle_component(fdc->c_dip, 0); 2516 return (EIO); 2517 } 2518 2519 mutex_enter(&fdc->c_lolock); 2520 } 2521 2522 if (fdformat(fdc, unit, cyl, hd)) 2523 err = EIO; 2524 2525 mutex_exit(&fdc->c_lolock); 2526 (void) pm_idle_component(fdc->c_dip, 0); 2527 2528 break; 2529 } 2530 2531 case FDRAW: 2532 2533 (void) pm_busy_component(fdc->c_dip, 0); 2534 err = fdrawioctl(fdc, unit, arg, flag); 2535 2536 (void) pm_idle_component(fdc->c_dip, 0); 2537 2538 break; 2539 #ifdef FD_DEBUG 2540 case IOCTL_DEBUG: 2541 fderrlevel--; 2542 if (fderrlevel < 0) 2543 fderrlevel = 3; 2544 cmn_err(C, "fdioctl: CHANGING debug to %d", fderrlevel); 2545 return (0); 2546 #endif /* FD_DEBUG */ 2547 default: 2548 FDERRPRINT(FDEP_L2, FDEM_IOCT, 2549 (C, "fd_ioctl: invalid ioctl 0x%x\n", cmd)); 2550 err = ENOTTY; 2551 break; 2552 } 2553 2554 return (err); 2555 } 2556 2557 /* 2558 * fdrawioctl 2559 * 2560 * - acquires the low level lock 2561 */ 2562 2563 static int 2564 fdrawioctl(struct fdctlr *fdc, int unit, intptr_t arg, int mode) 2565 { 2566 struct fd_raw fdr; 2567 #ifdef _MULTI_DATAMODEL 2568 struct fd_raw32 fdr32; 2569 #endif 2570 struct fdcsb *csb; 2571 int i, err, flag; 2572 caddr_t fa; 2573 uint_t fc; 2574 size_t real_length; 2575 int res; 2576 ddi_device_acc_attr_t attr; 2577 ddi_acc_handle_t mem_handle; 2578 2579 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 2580 attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC; 2581 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 2582 2583 ASSERT(fdc->c_un->un_unit_no == unit); 2584 2585 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2586 (C, "fdrawioctl: cmd[0]=0x%x\n", fdr.fdr_cmd[0])); 2587 2588 flag = B_READ; 2589 err = 0; 2590 fa = NULL; 2591 fc = (uint_t)0; 2592 2593 /* Copy in the arguments */ 2594 switch (ddi_model_convert_from(mode)) { 2595 #ifdef _MULTI_DATAMODEL 2596 case DDI_MODEL_ILP32: 2597 if (ddi_copyin((caddr_t)arg, (caddr_t)&fdr32, 2598 sizeof (fdr32), mode)) { 2599 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2600 (C, "fdrawioctl: copyin error, args32\n")); 2601 return (EFAULT); 2602 } 2603 bcopy(fdr32.fdr_cmd, fdr.fdr_cmd, sizeof (fdr.fdr_cmd)); 2604 fdr.fdr_cnum = fdr32.fdr_cnum; 2605 bcopy(fdr32.fdr_result, fdr.fdr_result, 2606 sizeof (fdr.fdr_result)); 2607 fdr.fdr_nbytes = fdr32.fdr_nbytes; 2608 fdr.fdr_addr = (caddr_t)(uintptr_t)fdr32.fdr_addr; 2609 break; 2610 #endif 2611 default: 2612 case DDI_MODEL_NONE: 2613 if (ddi_copyin((caddr_t)arg, (caddr_t)&fdr, 2614 sizeof (fdr), mode)) { 2615 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2616 (C, "fdrawioctl: copyin error, args\n")); 2617 return (EFAULT); 2618 } 2619 break; 2620 } 2621 2622 mutex_enter(&fdc->c_lolock); 2623 2624 CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc); 2625 2626 if (fdc->c_un->un_state == FD_STATE_STOPPED) { 2627 mutex_exit(&fdc->c_lolock); 2628 if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON)) 2629 != DDI_SUCCESS) { 2630 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power change \ 2631 failed. \n")); 2632 2633 (void) pm_idle_component(fdc->c_dip, 0); 2634 return (EIO); 2635 } 2636 mutex_enter(&fdc->c_lolock); 2637 } 2638 2639 fdgetcsb(fdc); 2640 csb = &fdc->c_csb; 2641 csb->csb_unit = (uchar_t)unit; 2642 2643 /* copy cmd bytes into csb */ 2644 for (i = 0; i <= fdr.fdr_cnum; i++) 2645 csb->csb_cmds[i] = fdr.fdr_cmd[i]; 2646 csb->csb_ncmds = (uchar_t)fdr.fdr_cnum; 2647 2648 csb->csb_maxretry = 0; /* let the application deal with errors */ 2649 csb->csb_retrys = 0; 2650 2651 switch (fdr.fdr_cmd[0] & 0x0f) { 2652 2653 case FDRAW_SPECIFY: 2654 /* 2655 * Ensure that the right DMA mode is selected. There is 2656 * currently no way for the user to tell if DMA is 2657 * happening so set the value for the user. 2658 */ 2659 2660 if (fdc->c_fdtype & FDCTYPE_DMA) 2661 csb->csb_cmds[2] = csb->csb_cmds[2] & 0xFE; 2662 else 2663 csb->csb_cmds[2] = csb->csb_cmds[2] | 0x1; 2664 2665 csb->csb_opflags = CSB_OFNORESULTS; 2666 csb->csb_nrslts = 0; 2667 break; 2668 2669 case FDRAW_SENSE_DRV: 2670 /* Insert the appropriate drive number */ 2671 csb->csb_cmds[1] = csb->csb_cmds[1] | (unit & DRV_MASK); 2672 csb->csb_opflags = CSB_OFIMMEDIATE; 2673 csb->csb_nrslts = 1; 2674 break; 2675 2676 case FDRAW_REZERO: 2677 case FDRAW_SEEK: 2678 /* Insert the appropriate drive number */ 2679 csb->csb_cmds[1] = csb->csb_cmds[1] | (unit & DRV_MASK); 2680 csb->csb_opflags = CSB_OFSEEKOPS + CSB_OFTIMEIT; 2681 csb->csb_nrslts = 2; 2682 break; 2683 2684 case FDRAW_FORMAT: 2685 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2686 (C, "fdrawioctl: cmd is fdfraw format\n")); 2687 2688 /* Insert the appropriate drive number */ 2689 csb->csb_cmds[1] = csb->csb_cmds[1] | (unit & DRV_MASK); 2690 csb->csb_opflags = CSB_OFXFEROPS + CSB_OFTIMEIT; 2691 csb->csb_nrslts = NRBRW; 2692 flag = B_WRITE; 2693 2694 /* 2695 * Allocate memory for the command. 2696 * If PIO is being used, then add an extra 16 bytes 2697 */ 2698 if (fdc->c_fdtype & FDCTYPE_DMA) { 2699 2700 fc = (uint_t)(fdr.fdr_nbytes); 2701 mutex_enter(&fdc->c_hilock); 2702 2703 res = ddi_dma_mem_alloc(fdc->c_dmahandle, fc, 2704 &attr, DDI_DMA_STREAMING, 2705 DDI_DMA_DONTWAIT, 0, &fa, &real_length, 2706 &mem_handle); 2707 2708 if (res != DDI_SUCCESS) { 2709 fdretcsb(fdc); 2710 mutex_exit(&fdc->c_lolock); 2711 mutex_exit(&fdc->c_hilock); 2712 return (EIO); 2713 } 2714 2715 fdc->c_csb.csb_read = CSB_WRITE; 2716 if (fdstart_dma(fdc, fa, fc) != 0) { 2717 ddi_dma_mem_free(&mem_handle); 2718 fdretcsb(fdc); 2719 mutex_exit(&fdc->c_lolock); 2720 mutex_exit(&fdc->c_hilock); 2721 return (EIO); 2722 } 2723 mutex_exit(&fdc->c_hilock); 2724 2725 } else { 2726 fc = (uint_t)(fdr.fdr_nbytes + 16); 2727 fa = kmem_zalloc(fc, KM_SLEEP); 2728 } 2729 2730 /* copy in the user's command bytes */ 2731 if (ddi_copyin(fdr.fdr_addr, fa, 2732 (uint_t)fdr.fdr_nbytes, mode)) { 2733 fdretcsb(fdc); 2734 mutex_exit(&fdc->c_lolock); 2735 2736 if (fdc->c_fdtype & FDCTYPE_DMA) { 2737 ddi_dma_mem_free(&mem_handle); 2738 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2739 (C, "fdrawioctl: (err)free dma memory\n")); 2740 } else { 2741 kmem_free(fa, fc); 2742 } 2743 2744 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2745 (C, "fdrawioctl: ddi_copyin error\n")); 2746 return (EFAULT); 2747 } 2748 2749 break; 2750 case FDRAW_WRCMD: 2751 case FDRAW_WRITEDEL: 2752 flag = B_WRITE; 2753 /* FALLTHROUGH */ 2754 case FDRAW_RDCMD: 2755 case FDRAW_READDEL: 2756 case FDRAW_READTRACK: 2757 /* Insert the appropriate drive number */ 2758 csb->csb_cmds[1] = csb->csb_cmds[1] | (unit & DRV_MASK); 2759 if (fdc->c_fdtype & FDCTYPE_SB) 2760 csb->csb_cmds[1] |= IPS; 2761 csb->csb_opflags = CSB_OFXFEROPS + CSB_OFTIMEIT; 2762 csb->csb_nrslts = NRBRW; 2763 break; 2764 2765 default: 2766 fdretcsb(fdc); 2767 mutex_exit(&fdc->c_lolock); 2768 return (EINVAL); 2769 } 2770 2771 if ((csb->csb_opflags & CSB_OFXFEROPS) && (fdr.fdr_nbytes == 0)) { 2772 fdretcsb(fdc); 2773 mutex_exit(&fdc->c_lolock); 2774 return (EINVAL); 2775 } 2776 csb->csb_opflags |= CSB_OFRAWIOCTL; 2777 2778 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2779 (C, "fdrawioctl: nbytes = %u\n", fdr.fdr_nbytes)); 2780 2781 if ((fdr.fdr_cmd[0] & 0x0f) != FDRAW_FORMAT) { 2782 if ((fc = (uint_t)fdr.fdr_nbytes) > 0) { 2783 /* 2784 * In SunOS 4.X, we used to as_fault things in. 2785 * We really cannot do this in 5.0/SVr4. Unless 2786 * someone really believes that speed is of the 2787 * essence here, it is just much simpler to do 2788 * this in kernel space and use copyin/copyout. 2789 */ 2790 if (fdc->c_fdtype & FDCTYPE_DMA) { 2791 mutex_enter(&fdc->c_hilock); 2792 res = ddi_dma_mem_alloc(fdc->c_dmahandle, fc, 2793 &attr, DDI_DMA_STREAMING, 2794 DDI_DMA_DONTWAIT, 0, &fa, &real_length, 2795 &mem_handle); 2796 2797 if (res != DDI_SUCCESS) { 2798 fdretcsb(fdc); 2799 mutex_exit(&fdc->c_lolock); 2800 mutex_exit(&fdc->c_hilock); 2801 return (EIO); 2802 } 2803 2804 if (flag == B_WRITE) 2805 fdc->c_csb.csb_read = CSB_WRITE; 2806 else 2807 fdc->c_csb.csb_read = CSB_READ; 2808 2809 if (fdstart_dma(fdc, fa, fc) != 0) { 2810 ddi_dma_mem_free(&mem_handle); 2811 fdretcsb(fdc); 2812 mutex_exit(&fdc->c_lolock); 2813 mutex_exit(&fdc->c_hilock); 2814 return (EIO); 2815 } 2816 mutex_exit(&fdc->c_hilock); 2817 2818 } else { 2819 fa = kmem_zalloc(fc, KM_SLEEP); 2820 } 2821 2822 if (flag == B_WRITE) { 2823 if (ddi_copyin(fdr.fdr_addr, fa, fc, mode)) { 2824 if (fdc->c_fdtype & FDCTYPE_DMA) 2825 ddi_dma_mem_free(&mem_handle); 2826 else 2827 kmem_free(fa, fc); 2828 fdretcsb(fdc); 2829 mutex_exit(&fdc->c_lolock); 2830 FDERRPRINT(FDEP_L1, FDEM_RAWI, (C, 2831 "fdrawioctl: can't copy data\n")); 2832 2833 return (EFAULT); 2834 } 2835 } 2836 csb->csb_addr = fa; 2837 csb->csb_len = fc; 2838 } else { 2839 csb->csb_addr = 0; 2840 csb->csb_len = 0; 2841 } 2842 } else { 2843 csb->csb_addr = fa; 2844 csb->csb_len = fc; 2845 } 2846 2847 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2848 (C, "cmd: %x %x %x %x %x %x %x %x %x %x\n", csb->csb_cmds[0], 2849 csb->csb_cmds[1], csb->csb_cmds[2], csb->csb_cmds[3], 2850 csb->csb_cmds[4], csb->csb_cmds[5], csb->csb_cmds[6], 2851 csb->csb_cmds[7], csb->csb_cmds[8], csb->csb_cmds[9])); 2852 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2853 (C, "nbytes: %x, opflags: %x, addr: %p, len: %x\n", 2854 csb->csb_ncmds, csb->csb_opflags, (void *)csb->csb_addr, 2855 csb->csb_len)); 2856 2857 2858 /* 2859 * Note that we ignore any error return s from fdexec. 2860 * This is the way the driver has been, and it may be 2861 * that the raw ioctl senders simply don't want to 2862 * see any errors returned in this fashion. 2863 */ 2864 2865 if ((csb->csb_opflags & CSB_OFNORESULTS) || 2866 (csb->csb_opflags & CSB_OFIMMEDIATE)) { 2867 (void) fdexec(fdc, 0); /* don't sleep, don't check change */ 2868 } else { 2869 (void) fdexec(fdc, FDXC_SLEEP | FDXC_CHECKCHG); 2870 } 2871 2872 2873 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2874 (C, "rslt: %x %x %x %x %x %x %x %x %x %x\n", csb->csb_rslt[0], 2875 csb->csb_rslt[1], csb->csb_rslt[2], csb->csb_rslt[3], 2876 csb->csb_rslt[4], csb->csb_rslt[5], csb->csb_rslt[6], 2877 csb->csb_rslt[7], csb->csb_rslt[8], csb->csb_rslt[9])); 2878 2879 if ((fdr.fdr_cmd[0] & 0x0f) != FDRAW_FORMAT && fc && 2880 flag == B_READ && err == 0) { 2881 if (ddi_copyout(fa, fdr.fdr_addr, fc, mode)) { 2882 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2883 (C, "fdrawioctl: can't copy read data\n")); 2884 2885 err = EFAULT; 2886 } 2887 } 2888 2889 2890 if (fc) { 2891 if (fdc->c_fdtype & FDCTYPE_DMA) { 2892 ddi_dma_mem_free(&mem_handle); 2893 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2894 (C, "fdrawioctl: free dma memory\n")); 2895 } else { 2896 kmem_free(fa, fc); 2897 } 2898 } 2899 2900 2901 /* copy cmd results into fdr */ 2902 for (i = 0; (int)i <= (int)csb->csb_nrslts; i++) 2903 fdr.fdr_result[i] = csb->csb_rslt[i]; 2904 fdr.fdr_nbytes = fdc->c_csb.csb_rlen; /* return resid */ 2905 2906 switch (ddi_model_convert_from(mode)) { 2907 #ifdef _MULTI_DATAMODEL 2908 case DDI_MODEL_ILP32: 2909 bcopy(fdr.fdr_cmd, fdr32.fdr_cmd, sizeof (fdr32.fdr_cmd)); 2910 fdr32.fdr_cnum = fdr.fdr_cnum; 2911 bcopy(fdr.fdr_result, fdr32.fdr_result, 2912 sizeof (fdr32.fdr_result)); 2913 fdr32.fdr_nbytes = fdr.fdr_nbytes; 2914 fdr32.fdr_addr = (caddr32_t)(uintptr_t)fdr.fdr_addr; 2915 if (ddi_copyout(&fdr32, (caddr_t)arg, sizeof (fdr32), mode)) { 2916 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2917 (C, "fdrawioctl: can't copy results32\n")); 2918 err = EFAULT; 2919 } 2920 break; 2921 #endif 2922 case DDI_MODEL_NONE: 2923 default: 2924 if (ddi_copyout(&fdr, (caddr_t)arg, sizeof (fdr), mode)) { 2925 FDERRPRINT(FDEP_L1, FDEM_RAWI, 2926 (C, "fdrawioctl: can't copy results\n")); 2927 err = EFAULT; 2928 } 2929 break; 2930 } 2931 2932 fdretcsb(fdc); 2933 mutex_exit(&fdc->c_lolock); 2934 return (0); 2935 } 2936 2937 /* 2938 * fdformat 2939 * format a track 2940 * For PIO, builds a table of sector data values with 16 bytes 2941 * (sizeof fdc's fifo) of dummy on end. This is so than when fdc->c_len 2942 * goes to 0 and fd_intr sends a TC that all the real formatting will 2943 * have already been done. 2944 * 2945 * - called with the low level lock held 2946 */ 2947 static int 2948 fdformat(struct fdctlr *fdc, int unit, int cyl, int hd) 2949 { 2950 struct fdcsb *csb; 2951 struct fdunit *un; 2952 struct fd_char *ch; 2953 int cmdresult; 2954 uchar_t *fmthdrs; 2955 caddr_t fd; 2956 int i; 2957 size_t real_length; 2958 ddi_device_acc_attr_t attr; 2959 ddi_acc_handle_t mem_handle; 2960 2961 FDERRPRINT(FDEP_L1, FDEM_FORM, 2962 (C, "fdformat cyl %d, hd %d\n", cyl, hd)); 2963 fdgetcsb(fdc); 2964 2965 ASSERT(fdc->c_un->un_unit_no == unit); 2966 2967 csb = &fdc->c_csb; 2968 un = fdc->c_un; 2969 ch = un->un_chars; 2970 2971 /* setup common things in csb */ 2972 csb->csb_unit = (uchar_t)unit; 2973 2974 /* 2975 * The controller needs to do a seek before 2976 * each format to get to right cylinder. 2977 */ 2978 if (fdrecalseek(fdc, unit, cyl, FDXC_CHECKCHG)) { 2979 fdretcsb(fdc); 2980 return (EIO); 2981 } 2982 2983 /* 2984 * now do the format itself 2985 */ 2986 csb->csb_nrslts = NRBRW; 2987 csb->csb_opflags = CSB_OFXFEROPS | CSB_OFTIMEIT; 2988 2989 csb->csb_cmds[0] = FDRAW_FORMAT; 2990 /* always or in MFM bit */ 2991 csb->csb_cmds[0] |= MFM; 2992 csb->csb_cmds[1] = (hd << 2) | (unit & 0x03); 2993 csb->csb_cmds[2] = ch->fdc_medium ? 3 : 2; 2994 csb->csb_cmds[3] = ch->fdc_secptrack; 2995 csb->csb_cmds[4] = GPLF; 2996 csb->csb_cmds[5] = FDATA; 2997 csb->csb_ncmds = 6; 2998 csb->csb_maxretry = rwretry; 2999 csb->csb_retrys = 0; 3000 3001 /* 3002 * NOTE: have to add size of fifo also - for dummy format action 3003 * if PIO is being used. 3004 */ 3005 3006 3007 if (fdc->c_fdtype & FDCTYPE_DMA) { 3008 3009 csb->csb_len = (uint_t)4 * ch->fdc_secptrack; 3010 3011 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 3012 attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC; 3013 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 3014 3015 mutex_enter(&fdc->c_hilock); 3016 3017 cmdresult = ddi_dma_mem_alloc(fdc->c_dmahandle, csb->csb_len, 3018 &attr, DDI_DMA_STREAMING, 3019 DDI_DMA_DONTWAIT, 0, &fd, &real_length, 3020 &mem_handle); 3021 3022 if (cmdresult != DDI_SUCCESS) { 3023 mutex_exit(&fdc->c_hilock); 3024 return (cmdresult); 3025 } 3026 3027 fdc->c_csb.csb_read = CSB_WRITE; 3028 if (fdstart_dma(fdc, fd, csb->csb_len) != 0) { 3029 ddi_dma_mem_free(&mem_handle); 3030 mutex_exit(&fdc->c_hilock); 3031 return (-1); 3032 } 3033 mutex_exit(&fdc->c_hilock); 3034 3035 3036 } else { 3037 csb->csb_len = (uint_t)4 * ch->fdc_secptrack + 16; 3038 fd = kmem_zalloc(csb->csb_len, KM_SLEEP); 3039 fmthdrs = (uchar_t *)fd; 3040 } 3041 3042 csb->csb_addr = (caddr_t)fd; 3043 3044 for (i = 1; i <= ch->fdc_secptrack; i++) { 3045 *fd++ = (uchar_t)cyl; /* cylinder */ 3046 *fd++ = (uchar_t)hd; /* head */ 3047 *fd++ = (uchar_t)i; /* sector number */ 3048 *fd++ = ch->fdc_medium ? 3 : 2; /* sec_size code */ 3049 } 3050 3051 if ((cmdresult = fdexec(fdc, FDXC_SLEEP | FDXC_CHECKCHG)) == 0) { 3052 if (csb->csb_cmdstat) 3053 cmdresult = EIO; /* XXX TBD NYD for now */ 3054 } 3055 3056 if (fdc->c_fdtype & FDCTYPE_DMA) { 3057 ddi_dma_mem_free(&mem_handle); 3058 } else { 3059 kmem_free((caddr_t)fmthdrs, csb->csb_len); 3060 } 3061 3062 fdretcsb(fdc); 3063 3064 return (cmdresult); 3065 } 3066 3067 /* 3068 * fdstart 3069 * called from fd_strategy() or from fdXXXX() to setup and 3070 * start operations of read or write only (using buf structs). 3071 * Because the chip doesn't handle crossing cylinder boundaries on 3072 * the fly, this takes care of those boundary conditions. Note that 3073 * it sleeps until the operation is done *within fdstart* - so that 3074 * when fdstart returns, the operation is already done. 3075 * 3076 * - called with the low level lock held 3077 * 3078 */ 3079 3080 static int slavio_index_pulse_work_around = 0; 3081 3082 static void 3083 fdstart(struct fdctlr *fdc) 3084 { 3085 struct buf *bp; 3086 struct fdcsb *csb; 3087 struct fdunit *un; 3088 struct fd_char *ch; 3089 struct dk_map32 *dkm; 3090 uint_t part; /* partition number for the transfer */ 3091 uint_t start_part; /* starting block of the partition */ 3092 uint_t last_part; /* last block of the partition */ 3093 uint_t blk; /* starting block of transfer on diskette */ 3094 uint_t sect; /* starting block's offset into track */ 3095 uint_t cyl; /* starting cylinder of the transfer */ 3096 uint_t bincyl; /* starting blocks's offset into cylinder */ 3097 uint_t secpcyl; /* number of sectors per cylinder */ 3098 uint_t phys_blkno; /* no. of blocks on the diskette */ 3099 uint_t head; /* one of two diskette heads */ 3100 uint_t unit; 3101 uint_t len, tlen; 3102 caddr_t addr; 3103 caddr_t temp_addr; 3104 uint_t partial_read = 0; 3105 int sb_temp_buf_used = 0; 3106 3107 bp = fdc->c_actf; 3108 3109 while (bp != NULL) { 3110 3111 fdc->c_actf = bp->av_forw; 3112 fdc->c_current = bp; 3113 3114 /* 3115 * Initialize the buf structure. The residual count is 3116 * initially the number of bytes to be read or written 3117 */ 3118 bp->b_flags &= ~B_ERROR; 3119 bp->b_error = 0; 3120 bp->b_resid = bp->b_bcount; 3121 bp_mapin(bp); /* map in buffers */ 3122 3123 addr = bp->b_un.b_addr; /* assign buffer address */ 3124 3125 /* 3126 * Find the unit and partition numbers. 3127 */ 3128 unit = fdc->c_un->un_unit_no; 3129 un = fdc->c_un; 3130 ch = un->un_chars; 3131 part = FDPARTITION(bp->b_edev); 3132 dkm = &un->un_label.dkl_map[part]; 3133 3134 if (un->un_chars->fdc_medium) { 3135 phys_blkno = bp->b_blkno >> 1; 3136 } else { 3137 phys_blkno = bp->b_blkno; 3138 } 3139 3140 if (un->un_iostat) { 3141 kstat_waitq_to_runq(KIOSP); 3142 } 3143 3144 FDERRPRINT(FDEP_L1, FDEM_STRT, 3145 (C, "fdstart: bp=0x%p blkno=0x%x bcount=0x%x\n", 3146 (void *)bp, (int)bp->b_blkno, (int)bp->b_bcount)); 3147 3148 /* 3149 * Get the csb and initialize the values that are the same 3150 * for DMA and PIO. 3151 */ 3152 fdgetcsb(fdc); /* get csb (maybe wait for it) */ 3153 csb = &fdc->c_csb; 3154 csb->csb_unit = unit; /* floppy unit number */ 3155 3156 3157 /* 3158 * bugID:4133425 : If the controller is SLAVIO, and 3159 * the read does not reach end of track, then modify 3160 * the tlen to read until the end of track to a temp 3161 * buffer and disable MT. After the read is over, 3162 * copy the useful portion of the data to 'addr'. 3163 * Enable this feature only when 3164 * slavio_index_pulse_work_aound variable is 3165 * set in /etc/system. 3166 */ 3167 3168 3169 if (bp->b_flags & B_READ) { 3170 if (((fdc->c_fdtype & FDCTYPE_SLAVIO) && 3171 slavio_index_pulse_work_around) || 3172 (fdc->c_fdtype & FDCTYPE_TCBUG)) 3173 csb->csb_cmds[0] = SK | FDRAW_RDCMD | MFM; 3174 else 3175 csb->csb_cmds[0] = MT | SK | FDRAW_RDCMD | MFM; 3176 } else { 3177 if (fdc->c_fdtype & FDCTYPE_TCBUG) 3178 csb->csb_cmds[0] = FDRAW_WRCMD | MFM; 3179 else 3180 csb->csb_cmds[0] = MT | FDRAW_WRCMD | MFM; 3181 } 3182 3183 3184 if (bp->b_flags & B_READ) 3185 fdc->c_csb.csb_read = CSB_READ; 3186 else 3187 fdc->c_csb.csb_read = CSB_WRITE; 3188 3189 3190 csb->csb_cmds[5] = ch->fdc_medium ? 3 : 2; /* sector size */ 3191 csb->csb_cmds[6] = ch->fdc_secptrack; /* EOT-# of sectors/trk */ 3192 csb->csb_cmds[7] = GPLN; /* GPL - gap 3 size code */ 3193 csb->csb_cmds[8] = SSSDTL; /* DTL - be 0xFF if N != 0 */ 3194 3195 csb->csb_ncmds = NCBRW; /* number of command bytes */ 3196 csb->csb_nrslts = NRBRW; /* number of result bytes */ 3197 3198 3199 /* 3200 * opflags for interrupt handler, et.al. 3201 */ 3202 csb->csb_opflags = CSB_OFXFEROPS | CSB_OFTIMEIT; 3203 3204 3205 /* 3206 * Make sure the transfer does not go off the end 3207 * of the partition. Limit the actual amount transferred 3208 * to fit the partition. 3209 */ 3210 3211 blk = phys_blkno; 3212 start_part = (dkm->dkl_cylno * ch->fdc_secptrack 3213 * ch->fdc_nhead); 3214 blk = blk + start_part; 3215 last_part = start_part + dkm->dkl_nblk; 3216 3217 if ((blk + (bp->b_bcount / ch->fdc_sec_size)) > last_part) 3218 len = (last_part - blk) * ch->fdc_sec_size; 3219 else 3220 len = (uint_t)bp->b_bcount; 3221 3222 /* 3223 * now we have the real start blk, 3224 * addr and len for xfer op 3225 * sectors per cylinder 3226 */ 3227 secpcyl = ch->fdc_nhead * ch->fdc_secptrack; 3228 3229 /* 3230 * The controller can transfer up to a cylinder at a time. 3231 * Early revs of the 82077 have a bug that causes the chip to 3232 * fail to respond to the Terminal Count signal. Due to this 3233 * bug, controllers with type FDCTYPE_TCBUG, only transfer up 3234 * to a track at a time. 3235 * See earlier comment for bugID:4133425 for index pulse 3236 * work around. 3237 */ 3238 3239 while (len != 0) { 3240 3241 cyl = blk / secpcyl; /* cylinder of transfer */ 3242 bincyl = blk % secpcyl; /* blk within cylinder */ 3243 head = bincyl / ch->fdc_secptrack; 3244 sect = (bincyl % ch->fdc_secptrack) + 1; 3245 /* sect w/in track */ 3246 3247 /* 3248 * If the desired block and length will go beyond the 3249 * cylinder end, limit it to the cylinder end. 3250 */ 3251 3252 if ((fdc->c_fdtype & FDCTYPE_SLAVIO) && 3253 slavio_index_pulse_work_around && 3254 (fdc->c_csb.csb_read == CSB_READ)) { 3255 3256 tlen = (ch->fdc_secptrack - sect + 1) * 3257 ch->fdc_sec_size; 3258 if (len < tlen) { 3259 partial_read = 1; 3260 temp_addr = (caddr_t)kmem_alloc(tlen, 3261 KM_SLEEP); 3262 } 3263 3264 } else if (fdc->c_fdtype & FDCTYPE_TCBUG) { 3265 tlen = len; 3266 if (len > ((ch->fdc_secptrack - sect + 1) * 3267 ch->fdc_sec_size)) 3268 tlen = (ch->fdc_secptrack - sect + 1) 3269 * ch->fdc_sec_size; 3270 } else { 3271 if (len > ((secpcyl - bincyl) 3272 * ch->fdc_sec_size)) 3273 tlen = (secpcyl - bincyl) 3274 * ch->fdc_sec_size; 3275 3276 else 3277 tlen = len; 3278 } 3279 if (fdc->c_fdtype & FDCTYPE_SB) { 3280 /* 3281 * To avoid underrun errors during IFB activity. 3282 */ 3283 if (tlen > max_fd_dma_len) 3284 tlen = max_fd_dma_len; 3285 } 3286 3287 FDERRPRINT(FDEP_L1, FDEM_STRT, 3288 (C, " blk 0x%x, addr 0x%p, len 0x%x\n", 3289 blk, (void *)addr, len)); 3290 FDERRPRINT(FDEP_L1, FDEM_STRT, 3291 (C, "cyl:%x, head:%x, sec:%x\n", 3292 cyl, head, sect)); 3293 3294 FDERRPRINT(FDEP_L1, FDEM_STRT, 3295 (C, " resid 0x%lx, tlen %d\n", 3296 bp->b_resid, tlen)); 3297 3298 /* 3299 * Finish programming the command 3300 */ 3301 csb->csb_cmds[1] = (head << 2) | unit; 3302 if (fdc->c_fdtype & FDCTYPE_SB) 3303 csb->csb_cmds[1] |= IPS; 3304 3305 csb->csb_cmds[2] = cyl; /* C - cylinder address */ 3306 csb->csb_cmds[3] = head; /* H - head number */ 3307 csb->csb_cmds[4] = sect; /* R - sector number */ 3308 if (fdc->c_fdtype & FDCTYPE_TCBUG) 3309 csb->csb_cmds[6] = sect + 3310 (tlen / ch->fdc_sec_size) - 1; 3311 3312 csb->csb_len = tlen; 3313 if (partial_read) 3314 csb->csb_addr = temp_addr; 3315 else 3316 csb->csb_addr = addr; 3317 3318 /* retry this many times max */ 3319 csb->csb_maxretry = rwretry; 3320 csb->csb_retrys = 0; 3321 3322 /* If platform supports DMA, set up DMA resources */ 3323 if (fdc->c_fdtype & FDCTYPE_DMA) { 3324 if ((fdc->c_fdtype & FDCTYPE_SB) && 3325 (((uint32_t)(uintptr_t)addr & 0xFFFF0000) != 3326 (((uint32_t)(uintptr_t)addr + tlen) & 3327 0xFFFF0000))) { 3328 csb->csb_addr = fdc->dma_buf; 3329 sb_temp_buf_used = 1; 3330 if (csb->csb_read != CSB_READ) { 3331 bcopy(addr, fdc->dma_buf, tlen); 3332 } 3333 } 3334 mutex_enter(&fdc->c_hilock); 3335 3336 if (fdstart_dma(fdc, csb->csb_addr, 3337 tlen) != 0) { 3338 3339 bp->b_flags |= B_ERROR; 3340 bp->b_error = EAGAIN; 3341 3342 mutex_exit(&fdc->c_hilock); 3343 FDERRPRINT(FDEP_L1, FDEM_STRT, 3344 (C, "fdstart: no dma resources\n")); 3345 3346 break; 3347 } 3348 mutex_exit(&fdc->c_hilock); 3349 3350 } 3351 3352 bp->b_error = fdexec(fdc, FDXC_SLEEP|FDXC_CHECKCHG); 3353 if (bp->b_error != 0) { 3354 /* 3355 * error in fdexec 3356 */ 3357 FDERRPRINT(FDEP_L1, FDEM_STRT, (C, 3358 "fdstart: bad exec of bp: 0x%p, err %d\n", 3359 (void *)bp, bp->b_error)); 3360 3361 bp->b_flags |= B_ERROR; 3362 if (partial_read) { 3363 partial_read = 0; 3364 kmem_free(temp_addr, tlen); 3365 } 3366 break; 3367 } 3368 3369 /* 3370 * If it was a partial read, copy the useful 3371 * portion of data to 'addr'. 3372 */ 3373 if (partial_read) { 3374 partial_read = 0; 3375 bcopy(temp_addr, addr, len); 3376 kmem_free(temp_addr, tlen); 3377 tlen = len; 3378 } 3379 if ((fdc->c_fdtype & FDCTYPE_SB) && 3380 (csb->csb_read == CSB_READ)) { 3381 if (sb_temp_buf_used) { 3382 bcopy(fdc->dma_buf, addr, tlen); 3383 sb_temp_buf_used = 0; 3384 } 3385 } 3386 3387 blk += tlen / ch->fdc_sec_size; 3388 len -= tlen; 3389 addr += tlen; 3390 bp->b_resid -= tlen; 3391 3392 } 3393 3394 FDERRPRINT(FDEP_L1, FDEM_STRT, 3395 (C, "fdstart done: b_resid %lu, b_count %lu, csb_rlen %d\n", 3396 bp->b_resid, bp->b_bcount, fdc->c_csb.csb_rlen)); 3397 3398 fdc->c_current = 0; 3399 fdretcsb(fdc); 3400 if (un->un_iostat) { 3401 if (bp->b_flags & B_READ) { 3402 KIOSP->reads++; 3403 KIOSP->nread += 3404 (bp->b_bcount - bp->b_resid); 3405 } else { 3406 KIOSP->writes++; 3407 KIOSP->nwritten += (bp->b_bcount - bp->b_resid); 3408 } 3409 kstat_runq_exit(KIOSP); 3410 } 3411 biodone(bp); 3412 3413 /* 3414 * Look at the next buffer 3415 */ 3416 bp = fdc->c_actf; 3417 3418 } 3419 } 3420 3421 /* 3422 * Set up DMA resources 3423 * The DMA handle was initialized in fd_attach() 3424 * Assumes the handle has already been allocated by fd_attach() 3425 */ 3426 static int 3427 fdstart_dma(struct fdctlr *fdc, caddr_t addr, uint_t len) 3428 { 3429 int flags; /* flags for setting up resources */ 3430 int res; 3431 3432 FDERRPRINT(FDEP_L1, FDEM_SDMA, (C, "fdstart_dma: start\n")); 3433 3434 if (fdc->c_csb.csb_read == CSB_READ) { 3435 flags = DDI_DMA_READ; 3436 } else { 3437 flags = DDI_DMA_WRITE; 3438 } 3439 3440 3441 /* allow partial mapping to maximize the portability of the driver */ 3442 flags = flags | DDI_DMA_PARTIAL; 3443 3444 FDERRPRINT(FDEP_L1, FDEM_SDMA, (C, "fdstart_dma: amt. asked for %d\n", 3445 len)); 3446 3447 /* 3448 * Zero out the current cookie. This is done to ensure that 3449 * the previous transfers cookie information can in no way be 3450 * used. 3451 */ 3452 bzero((char *)&fdc->c_csb.csb_dmacookie, 3453 sizeof (fdc->c_csb.csb_dmacookie)); 3454 fdc->c_csb.csb_nwin = 0; 3455 fdc->c_csb.csb_windex = 0; 3456 fdc->c_csb.csb_ccount = 0; 3457 3458 res = ddi_dma_addr_bind_handle(fdc->c_dmahandle, NULL, addr, len, 3459 flags, DDI_DMA_DONTWAIT, 0, &fdc->c_csb.csb_dmacookie, 3460 &fdc->c_csb.csb_ccount); 3461 3462 switch (res) { 3463 case DDI_DMA_MAPPED: 3464 /* 3465 * There is one window. csb_windex is the index 3466 * into the array of windows. If there are n 3467 * windows then, (0 <= windex <= n-1). csb_windex 3468 * represents the index of the next window 3469 * to be processed. 3470 */ 3471 fdc->c_csb.csb_nwin = 1; 3472 fdc->c_csb.csb_windex = 1; 3473 3474 3475 FDERRPRINT(FDEP_L1, FDEM_SDMA, 3476 (C, "fdstart_dma: DDI_DMA_MAPPED\n")); 3477 3478 break; 3479 case DDI_DMA_PARTIAL_MAP: 3480 3481 /* 3482 * obtain the number of DMA windows 3483 */ 3484 if (ddi_dma_numwin(fdc->c_dmahandle, 3485 &fdc->c_csb.csb_nwin) != DDI_SUCCESS) { 3486 return (-1); 3487 } 3488 3489 3490 FDERRPRINT(FDEP_L1, FDEM_SDMA, 3491 (C, "fdstart_dma: partially mapped %d windows\n", 3492 fdc->c_csb.csb_nwin)); 3493 3494 /* 3495 * The DMA window currently in use is window number 3496 * one. 3497 */ 3498 fdc->c_csb.csb_windex = 1; 3499 3500 break; 3501 case DDI_DMA_NORESOURCES: 3502 FDERRPRINT(FDEP_L1, FDEM_SDMA, 3503 (C, "fdstart_dma: no resources\n")); 3504 return (-1); 3505 case DDI_DMA_NOMAPPING: 3506 FDERRPRINT(FDEP_L1, FDEM_SDMA, 3507 (C, "fdstart_dma: no mapping\n")); 3508 return (-1); 3509 case DDI_DMA_TOOBIG: 3510 FDERRPRINT(FDEP_L1, FDEM_SDMA, 3511 (C, "fdstart_dma: too big\n")); 3512 return (-1); 3513 3514 case DDI_DMA_INUSE: 3515 FDERRPRINT(FDEP_L1, FDEM_SDMA, 3516 (C, "fdstart_dma: dma inuse\n")); 3517 return (-1); 3518 default: 3519 FDERRPRINT(FDEP_L1, FDEM_SDMA, 3520 (C, "fdstart_dma: result is 0x%x\n", res)); 3521 return (-1); 3522 3523 }; 3524 3525 FDERRPRINT(FDEP_L1, FDEM_SDMA, 3526 (C, "fdstart_dma: bound the handle\n")); 3527 3528 ASSERT(fdc->c_csb.csb_dmacookie.dmac_size); 3529 3530 FDERRPRINT(FDEP_L1, FDEM_SDMA, (C, "fdstart_dma: done\n")); 3531 return (0); 3532 } 3533 3534 3535 /* 3536 * fd_unbind_handle: unbind a dma handle if one exists 3537 * return EIO if unbind failes 3538 */ 3539 static int 3540 fd_unbind_handle(struct fdctlr *fdc) 3541 { 3542 if ((fdc->c_fdtype & FDCTYPE_DMA) && 3543 ((fdc->c_csb.csb_read == CSB_READ) || 3544 (fdc->c_csb.csb_read == CSB_WRITE))) { 3545 mutex_enter(&fdc->c_hilock); 3546 3547 if (fdc->c_fdtype & FDCTYPE_SB) { 3548 if (fdc->sb_dma_lock) { 3549 release_sb_dma(fdc); 3550 } 3551 } 3552 3553 /* 3554 * If the byte count isn't zero, then the DMA engine is 3555 * still doing a transfer. If the byte count is nonzero, 3556 * reset the DMA engine to cause it to drain. 3557 */ 3558 3559 if (get_data_count_register(fdc) != 0) { 3560 FDERRPRINT(FDEP_L1, FDEM_EXEC, 3561 (C, "unbind & byte count isn't zero\n")); 3562 3563 reset_dma_controller(fdc); 3564 set_dma_control_register(fdc, DCSR_INIT_BITS); 3565 } 3566 3567 if (ddi_dma_unbind_handle(fdc->c_dmahandle) != DDI_SUCCESS) { 3568 FDERRPRINT(FDEP_L1, FDEM_EXEC, 3569 (C, "problem unbinding the handle\n")); 3570 mutex_exit(&fdc->c_hilock); 3571 return (EIO); 3572 } 3573 mutex_exit(&fdc->c_hilock); 3574 } 3575 return (0); 3576 } 3577 3578 /* 3579 * fdexec 3580 * all commands go through here. Assumes the command block 3581 * fdctlr.c_csb is filled in. The bytes are sent to the 3582 * controller and then we do whatever else the csb says - 3583 * like wait for immediate results, etc. 3584 * 3585 * All waiting for operations done is in here - to allow retrys 3586 * and checking for disk changed - so we don't have to worry 3587 * about sleeping at interrupt level. 3588 * 3589 * RETURNS: 0 if all ok, 3590 * ENXIO - diskette not in drive 3591 * EBUSY - if chip is locked or busy 3592 * EIO - for timeout during sending cmds to chip 3593 * 3594 * to sleep: set FDXC_SLEEP, to check for disk 3595 * changed: set FDXC_CHECKCHG 3596 * 3597 * - called with the lock held 3598 */ 3599 static int 3600 fdexec(struct fdctlr *fdc, int flags) 3601 { 3602 struct fdcsb *csb; 3603 int i; 3604 int to, unit; 3605 uchar_t tmp; 3606 caddr_t a = (caddr_t)fdc; 3607 3608 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: flags:%x\n", flags)); 3609 3610 ASSERT(mutex_owned(&fdc->c_lolock)); 3611 3612 csb = &fdc->c_csb; 3613 unit = csb->csb_unit; 3614 3615 3616 ASSERT(unit == fdc->c_un->un_unit_no); 3617 3618 retry: 3619 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: cmd is %s\n", 3620 fdcmds[csb->csb_cmds[0] & 0x1f].cmdname)); 3621 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: transfer rate = %d\n", 3622 fdc->c_un->un_chars->fdc_transfer_rate)); 3623 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: sec size = %d\n", 3624 fdc->c_un->un_chars->fdc_sec_size)); 3625 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: nblocks (512) = %d\n", 3626 fdc->c_un->un_label.dkl_map[2].dkl_nblk)); 3627 3628 if ((fdc->c_fdtype & FDCTYPE_CTRLMASK) == FDCTYPE_82077) { 3629 fdexec_turn_on_motor(fdc, flags, unit); 3630 } 3631 3632 3633 fdselect(fdc, unit, 1); /* select drive */ 3634 3635 /* 3636 * select data rate for this unit/command 3637 */ 3638 switch (fdc->c_un->un_chars->fdc_transfer_rate) { 3639 case 500: 3640 Dsr(fdc, 0); 3641 break; 3642 case 300: 3643 Dsr(fdc, 1); 3644 break; 3645 case 250: 3646 Dsr(fdc, 2); 3647 break; 3648 } 3649 drv_usecwait(2); 3650 3651 3652 /* 3653 * If checking for changed is enabled (i.e., not seeking in checkdisk), 3654 * we sample the DSKCHG line to see if the diskette has wandered away. 3655 */ 3656 if ((flags & FDXC_CHECKCHG) && fdsense_chng(fdc, unit)) { 3657 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "diskette changed\n")); 3658 fdc->c_un->un_flags |= FDUNIT_CHANGED; 3659 3660 if (fdcheckdisk(fdc, unit)) { 3661 3662 (void) fd_unbind_handle(fdc); 3663 return (ENXIO); 3664 3665 } 3666 } 3667 3668 /* 3669 * gather some statistics 3670 */ 3671 switch (csb->csb_cmds[0] & 0x1f) { 3672 case FDRAW_RDCMD: 3673 fdc->fdstats.rd++; 3674 break; 3675 case FDRAW_WRCMD: 3676 fdc->fdstats.wr++; 3677 break; 3678 case FDRAW_REZERO: 3679 fdc->fdstats.recal++; 3680 break; 3681 case FDRAW_FORMAT: 3682 fdc->fdstats.form++; 3683 break; 3684 default: 3685 fdc->fdstats.other++; 3686 break; 3687 } 3688 3689 /* 3690 * Always set the opmode *prior* to poking the chip. 3691 * This way we don't have to do any locking at high level. 3692 */ 3693 csb->csb_raddr = 0; 3694 csb->csb_rlen = 0; 3695 if (csb->csb_opflags & CSB_OFSEEKOPS) { 3696 csb->csb_opmode = 2; 3697 } else if (csb->csb_opflags & CSB_OFIMMEDIATE) { 3698 csb->csb_opmode = 0; 3699 } else { 3700 csb->csb_opmode = 1; /* normal data xfer commands */ 3701 csb->csb_raddr = csb->csb_addr; 3702 csb->csb_rlen = csb->csb_len; 3703 } 3704 3705 bzero((caddr_t)csb->csb_rslt, 10); 3706 csb->csb_status = 0; 3707 csb->csb_cmdstat = 0; 3708 3709 3710 /* 3711 * Program the DMA engine with the length and address of the transfer 3712 * (DMA is only used on a read or a write) 3713 */ 3714 if ((fdc->c_fdtype & FDCTYPE_DMA) && 3715 ((fdc->c_csb.csb_read == CSB_READ) || 3716 (fdc->c_csb.csb_read == CSB_WRITE))) { 3717 mutex_enter(&fdc->c_hilock); 3718 3719 /* Reset the dcsr to clear it of all errors */ 3720 3721 reset_dma_controller(fdc); 3722 3723 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "cookie addr 0x%p\n", 3724 (void *)fdc->c_csb.csb_dmacookie.dmac_laddress)); 3725 3726 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "cookie length %ld\n", 3727 fdc->c_csb.csb_dmacookie.dmac_size)); 3728 ASSERT(fdc->c_csb.csb_dmacookie.dmac_size); 3729 3730 set_data_count_register(fdc, 3731 fdc->c_csb.csb_dmacookie.dmac_size); 3732 set_data_address_register(fdc, 3733 fdc->c_csb.csb_dmacookie.dmac_laddress); 3734 3735 /* Program the DCSR */ 3736 3737 if (fdc->c_csb.csb_read == CSB_READ) 3738 set_dma_mode(fdc, CSB_READ); 3739 else 3740 set_dma_mode(fdc, CSB_WRITE); 3741 mutex_exit(&fdc->c_hilock); 3742 } 3743 3744 /* 3745 * I saw this (chip unexpectedly busy) happen when i shoved the 3746 * floppy into the drive while 3747 * running a dd if= /dev/rfd0c. so it *is* possible for this to happen. 3748 * we need to do a ctlr reset ... 3749 */ 3750 3751 if (Msr(fdc) & CB) { 3752 /* tried to give command to chip when it is busy! */ 3753 FDERRPRINT(FDEP_L3, FDEM_EXEC, 3754 (C, "fdc: unexpectedly busy-stat 0x%x\n", Msr(fdc))); 3755 csb->csb_cmdstat = 1; /* XXX TBD ERRS NYD for now */ 3756 3757 (void) fd_unbind_handle(fdc); 3758 return (EBUSY); 3759 } 3760 3761 /* Give command to the controller */ 3762 for (i = 0; i < (int)csb->csb_ncmds; i++) { 3763 3764 /* Test the readiness of the controller to receive the cmd */ 3765 for (to = FD_CRETRY; to; to--) { 3766 if ((Msr(fdc) & (DIO|RQM)) == RQM) 3767 break; 3768 } 3769 if (to == 0) { 3770 FDERRPRINT(FDEP_L2, FDEM_EXEC, 3771 (C, "fdc: no RQM - stat 0x%x\n", Msr(fdc))); 3772 csb->csb_cmdstat = 1; 3773 3774 (void) fd_unbind_handle(fdc); 3775 return (EIO); 3776 } 3777 3778 Set_Fifo(fdc, csb->csb_cmds[i]); 3779 3780 FDERRPRINT(FDEP_L1, FDEM_EXEC, 3781 (C, "fdexec: sent 0x%x, Msr 0x%x\n", csb->csb_cmds[i], 3782 Msr(fdc))); 3783 3784 } 3785 3786 3787 /* 3788 * Start watchdog timer on data transfer type commands - required 3789 * in case a diskette is not present or is unformatted 3790 */ 3791 if (csb->csb_opflags & CSB_OFTIMEIT) { 3792 fdc->c_timeid = timeout(fdwatch, a, 3793 tosec * drv_usectohz(1000000)); 3794 } 3795 3796 FDERRPRINT(FDEP_L1, FDEM_EXEC, 3797 (C, "fdexec: cmd sent, Msr 0x%x\n", Msr(fdc))); 3798 3799 /* If the operation has no results - then just return */ 3800 if (csb->csb_opflags & CSB_OFNORESULTS) { 3801 if (fdc->c_fdtype & FDCTYPE_82077) { 3802 if (fdc->c_mtimeid == 0) { 3803 fdc->c_mtimeid = timeout(fdmotoff, a, 3804 Motoff_delay); 3805 } 3806 } 3807 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: O K ..\n")); 3808 3809 /* 3810 * Make sure the last byte is received well by the 3811 * controller. On faster CPU, it may still be busy 3812 * by the time another command comes here. 3813 */ 3814 for (to = FD_CRETRY; to; to--) { 3815 if ((Msr(fdc) & (DIO|RQM)) == RQM) 3816 break; 3817 } 3818 if (to == 0) { 3819 csb->csb_cmdstat = 1; 3820 return (EIO); 3821 } 3822 3823 /* 3824 * An operation that has no results isn't doing DMA so, 3825 * there is no reason to try to unbind a handle 3826 */ 3827 return (0); 3828 } 3829 3830 /* 3831 * If this operation has no interrupt AND an immediate result 3832 * then we just busy wait for the results and stuff them into 3833 * the csb 3834 */ 3835 if (csb->csb_opflags & CSB_OFIMMEDIATE) { 3836 to = FD_RRETRY; 3837 csb->csb_nrslts = 0; 3838 /* 3839 * Wait while this command is still going on. 3840 */ 3841 while ((tmp = Msr(fdc)) & CB) { 3842 /* 3843 * If RQM + DIO, then a result byte is at hand. 3844 */ 3845 if ((tmp & (RQM|DIO|CB)) == (RQM|DIO|CB)) { 3846 csb->csb_rslt[csb->csb_nrslts++] = 3847 Fifo(fdc); 3848 /* 3849 * FDERRPRINT(FDEP_L4, FDEM_EXEC, 3850 * (C, "fdexec: got result 0x%x\n", 3851 * csb->csb_nrslts)); 3852 */ 3853 } else if (--to == 0) { 3854 FDERRPRINT(FDEP_L4, FDEM_EXEC, 3855 (C, "fdexec: timeout, Msr%x, nr%x\n", 3856 Msr(fdc), csb->csb_nrslts)); 3857 3858 csb->csb_status = 2; 3859 if (fdc->c_fdtype & FDCTYPE_82077) { 3860 if (fdc->c_mtimeid == 0) { 3861 fdc->c_mtimeid = timeout( 3862 fdmotoff, a, Motoff_delay); 3863 } 3864 } 3865 /* 3866 * There is no DMA happening. No need to 3867 * try freeing a handle. 3868 */ 3869 3870 return (EIO); 3871 } 3872 } 3873 } 3874 3875 /* 3876 * If told to sleep here, well then sleep! 3877 */ 3878 3879 if (flags & FDXC_SLEEP) { 3880 fdc->c_flags |= FDCFLG_WAITING; 3881 while (fdc->c_flags & FDCFLG_WAITING) { 3882 cv_wait(&fdc->c_iocv, &fdc->c_lolock); 3883 } 3884 } 3885 3886 /* 3887 * kludge for end-of-cylinder error which must be ignored!!! 3888 */ 3889 3890 if ((fdc->c_fdtype & FDCTYPE_TCBUG) && 3891 ((csb->csb_rslt[0] & IC_SR0) == 0x40) && 3892 (csb->csb_rslt[1] & EN_SR1)) 3893 csb->csb_rslt[0] &= ~IC_SR0; 3894 3895 /* 3896 * See if there was an error detected, if so, fdrecover() 3897 * will check it out and say what to do. 3898 * 3899 * Don't do this, though, if this was the Sense Drive Status 3900 * or the Dump Registers command. 3901 */ 3902 if (((csb->csb_rslt[0] & IC_SR0) || (fdc->c_csb.csb_dcsr_rslt) || 3903 (csb->csb_status)) && 3904 ((csb->csb_cmds[0] != FDRAW_SENSE_DRV) && 3905 (csb->csb_cmds[0] != DUMPREG))) { 3906 /* if it can restarted OK, then do so, else return error */ 3907 if (fdrecover(fdc) != 0) { 3908 if (fdc->c_fdtype & FDCTYPE_82077) { 3909 if (fdc->c_mtimeid == 0) { 3910 fdc->c_mtimeid = timeout(fdmotoff, 3911 a, Motoff_delay); 3912 } 3913 } 3914 3915 /* 3916 * If this was a dma transfer, unbind the handle so 3917 * that other transfers may use it. 3918 */ 3919 3920 (void) fd_unbind_handle(fdc); 3921 return (EIO); 3922 } else { 3923 /* ASSUMES that cmd is still intact in csb */ 3924 goto retry; 3925 } 3926 } 3927 3928 /* things went ok */ 3929 if (fdc->c_fdtype & FDCTYPE_82077) { 3930 if (fdc->c_mtimeid == 0) { 3931 fdc->c_mtimeid = timeout(fdmotoff, a, Motoff_delay); 3932 } 3933 } 3934 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "fdexec: O K ..........\n")); 3935 3936 if (fd_unbind_handle(fdc)) 3937 return (EIO); 3938 3939 return (0); 3940 } 3941 3942 /* 3943 * Turn on the drive's motor 3944 * 3945 * - called with the low level lock held 3946 */ 3947 static void 3948 fdexec_turn_on_motor(struct fdctlr *fdc, int flags, uint_t unit) 3949 { 3950 clock_t local_lbolt; 3951 timeout_id_t timeid; 3952 3953 /* 3954 * The low level mutex may not be held over the call to 3955 * untimeout(). See the manpage for details. 3956 */ 3957 timeid = fdc->c_mtimeid; 3958 fdc->c_mtimeid = 0; 3959 if (timeid) { 3960 mutex_exit(&fdc->c_lolock); 3961 (void) untimeout(timeid); 3962 mutex_enter(&fdc->c_lolock); 3963 } 3964 3965 ASSERT(fdc->c_un->un_unit_no == unit); 3966 3967 3968 set_rotational_speed(fdc, unit); 3969 3970 if (!(Dor(fdc) & (MOTEN(unit)))) { 3971 /* 3972 * Turn on the motor 3973 */ 3974 FDERRPRINT(FDEP_L1, FDEM_EXEC, 3975 (C, "fdexec: turning on motor\n")); 3976 3977 /* LINTED */ 3978 Set_dor(fdc, (MOTEN(unit)), 1); 3979 3980 if (flags & FDXC_SLEEP) { 3981 local_lbolt = ddi_get_lbolt(); 3982 (void) cv_timedwait(&fdc->c_motoncv, 3983 &fdc->c_lolock, local_lbolt + Moton_delay); 3984 } else { 3985 drv_usecwait(1000000); 3986 } 3987 } 3988 3989 } 3990 3991 /* 3992 * fdrecover 3993 * see if possible to retry an operation. 3994 * All we can do is restart the operation. If we are out of allowed 3995 * retries - return non-zero so that the higher levels will be notified. 3996 * 3997 * RETURNS: 0 if ok to restart, !0 if can't or out of retries 3998 * - called with the low level lock held 3999 */ 4000 static int 4001 fdrecover(struct fdctlr *fdc) 4002 { 4003 struct fdcsb *csb; 4004 4005 FDERRPRINT(FDEP_L1, FDEM_RECO, (C, "fdrecover\n")); 4006 csb = &fdc->c_csb; 4007 4008 if (fdc->c_flags & FDCFLG_TIMEDOUT) { 4009 struct fdcsb savecsb; 4010 4011 fdc->c_flags ^= FDCFLG_TIMEDOUT; 4012 csb->csb_rslt[1] |= TO_SR1; 4013 FDERRPRINT(FDEP_L1, FDEM_RECO, 4014 (C, "fd%d: %s timed out\n", csb->csb_unit, 4015 fdcmds[csb->csb_cmds[0] & 0x1f].cmdname)); 4016 4017