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 /* use private csb */ 4018 savecsb = fdc->c_csb; 4019 bzero(&fdc->c_csb, sizeof (struct fdcsb)); 4020 FDERRPRINT(FDEP_L1, FDEM_RECO, (C, "fdc: resetting\n")); 4021 4022 (void) fdreset(fdc); 4023 4024 if (fdc->c_fdtype & FDCTYPE_DMA) { 4025 mutex_enter(&fdc->c_hilock); 4026 /* Reset the DMA engine as well */ 4027 reset_dma_controller(fdc); 4028 set_dma_control_register(fdc, DCSR_INIT_BITS); 4029 mutex_exit(&fdc->c_hilock); 4030 } 4031 4032 4033 /* check change first?? */ 4034 /* don't ckchg in fdexec, too convoluted */ 4035 (void) fdrecalseek(fdc, savecsb.csb_unit, -1, 0); 4036 fdc->c_csb = savecsb; /* restore original csb */ 4037 } 4038 4039 /* 4040 * gather statistics on errors 4041 */ 4042 if (csb->csb_rslt[1] & DE_SR1) { 4043 fdc->fdstats.de++; 4044 } 4045 if (csb->csb_rslt[1] & OR_SR1) { 4046 fdc->fdstats.run++; 4047 } 4048 if (csb->csb_rslt[1] & (ND_SR1+MA_SR1)) { 4049 fdc->fdstats.bfmt++; 4050 } 4051 if (csb->csb_rslt[1] & TO_SR1) { 4052 fdc->fdstats.to++; 4053 } 4054 4055 /* 4056 * If raw ioctl don't examine results just pass status 4057 * back via fdraw. Raw commands are timed too, so put this 4058 * after the above check. 4059 */ 4060 if (csb->csb_opflags & CSB_OFRAWIOCTL) { 4061 return (1); 4062 } 4063 4064 4065 /* 4066 * if there was a pci bus error, do not retry 4067 */ 4068 4069 if (csb->csb_dcsr_rslt == 1) { 4070 FDERRPRINT(FDEP_L3, FDEM_RECO, 4071 (C, "fd%d: host bus error\n", 0)); 4072 return (1); 4073 } 4074 4075 /* 4076 * If there was an error with the DMA functions, do not retry 4077 */ 4078 if (csb->csb_dma_rslt == 1) { 4079 FDERRPRINT(FDEP_L1, FDEM_RECO, 4080 (C, "fd%d: DMA interface error\n", csb->csb_unit)); 4081 return (1); 4082 } 4083 4084 4085 /* 4086 * if we have run out of retries, return an error 4087 * XXX need better status interp 4088 */ 4089 4090 csb->csb_retrys++; 4091 if (csb->csb_retrys > csb->csb_maxretry) { 4092 FDERRPRINT(FDEP_L3, FDEM_RECO, 4093 (C, "fd%d: %s failed (%x %x %x)\n", 4094 0, fdcmds[csb->csb_cmds[0] & 0x1f].cmdname, 4095 csb->csb_rslt[0], csb->csb_rslt[1], csb->csb_rslt[2])); 4096 if (csb->csb_rslt[1] & NW_SR1) { 4097 FDERRPRINT(FDEP_L3, FDEM_RECO, 4098 (C, "fd%d: not writable\n", 0)); 4099 } 4100 if (csb->csb_rslt[1] & DE_SR1) { 4101 FDERRPRINT(FDEP_L3, FDEM_RECO, 4102 (C, "fd%d: crc error blk %d\n", 0, 4103 (int)fdc->c_current->b_blkno)); 4104 } 4105 if (csb->csb_rslt[1] & OR_SR1) { 4106 if (fdc->c_fdtype & FDCTYPE_SB) { 4107 /* 4108 * When using southbridge chip we need to 4109 * retry atleast 10 times to shake off the 4110 * underrun err. 4111 */ 4112 if (csb->csb_retrys <= rwretry) 4113 return (0); 4114 } 4115 FDERRPRINT(FDEP_L3, FDEM_RECO, 4116 (C, "fd%d: over/underrun\n", 0)); 4117 } 4118 4119 if (csb->csb_rslt[1] & (ND_SR1+MA_SR1)) { 4120 FDERRPRINT(FDEP_L3, FDEM_RECO, 4121 (C, "fd%d: bad format\n", 0)); 4122 } 4123 4124 if (csb->csb_rslt[1] & TO_SR1) { 4125 FDERRPRINT(FDEP_L3, FDEM_RECO, 4126 (C, "fd%d: timeout\n", 0)); 4127 } 4128 4129 csb->csb_cmdstat = 1; /* failed - give up */ 4130 return (1); 4131 } 4132 4133 if (csb->csb_opflags & CSB_OFSEEKOPS) { 4134 /* seek, recal type commands - just look at st0 */ 4135 FDERRPRINT(FDEP_L2, FDEM_RECO, 4136 (C, "fd%d: %s error : st0 0x%x\n", csb->csb_unit, 4137 fdcmds[csb->csb_cmds[0] & 0x1f].cmdname, 4138 csb->csb_rslt[0])); 4139 } 4140 if (csb->csb_opflags & CSB_OFXFEROPS) { 4141 /* rd, wr, fmt type commands - look at st0, st1, st2 */ 4142 FDERRPRINT(FDEP_L2, FDEM_RECO, 4143 (C, "fd%d: %s error : st0=0x%x st1=0x%x st2=0x%x\n", 4144 csb->csb_unit, fdcmds[csb->csb_cmds[0] & 0x1f].cmdname, 4145 csb->csb_rslt[0], csb->csb_rslt[1], csb->csb_rslt[2])); 4146 } 4147 4148 return (0); /* tell fdexec to retry */ 4149 } 4150 4151 /* 4152 * Interrupt handle for DMA 4153 */ 4154 4155 static uint_t 4156 fdintr_dma() 4157 { 4158 struct fdctlr *fdc; 4159 off_t off; 4160 size_t len; 4161 uint_t ccount; 4162 uint_t windex; 4163 uint_t done = 0; 4164 int tmp_dcsr; 4165 int to; 4166 uchar_t tmp; 4167 int i = 0; 4168 int res = DDI_INTR_UNCLAIMED; 4169 int not_cheerio = 1; 4170 4171 /* search for a controller that's expecting an interrupt */ 4172 fdc = fdctlrs; 4173 4174 if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 4175 tmp_dcsr = get_dma_control_register(fdc); 4176 if (!(tmp_dcsr & DCSR_INT_PEND) && !(DCSR_ERR_PEND & tmp_dcsr)) 4177 return (res); 4178 not_cheerio = 0; 4179 } 4180 4181 mutex_enter(&fdc->c_hilock); 4182 4183 if (fdc->c_csb.csb_opmode == 0x0) { 4184 fdc->c_csb.csb_opmode = 2; 4185 } 4186 if (fdc->sb_dma_lock) { 4187 release_sb_dma(fdc); 4188 } 4189 4190 /* 4191 * An interrupt can come from either the floppy controller or 4192 * or the DMA engine. The DMA engine will only issue an 4193 * interrupt if there was an error. 4194 */ 4195 4196 switch (fdc->c_csb.csb_opmode) { 4197 case 0x1: 4198 /* read/write/format data-xfer case */ 4199 4200 FDERRPRINT(FDEP_L1, FDEM_INTR, 4201 (C, "fdintr_dma: opmode 1\n")); 4202 4203 /* 4204 * See if the interrupt is from the floppy 4205 * controller. If there is, take out the status bytes. 4206 */ 4207 4208 if (not_cheerio || (tmp_dcsr & DCSR_INT_PEND)) { 4209 4210 FDERRPRINT(FDEP_L1, FDEM_INTR, 4211 (C, "fdintr_dma: INT_PEND \n")); 4212 4213 res = DDI_INTR_CLAIMED; 4214 4215 to = FD_RRETRY; 4216 fdc->c_csb.csb_nrslts = 0; 4217 4218 /* check status */ 4219 i = 0; 4220 4221 /* 4222 * CB turns off once all the result bytes are 4223 * read. 4224 * 4225 * NOTE: the counters are there so that the 4226 * handler will never get stuck in a loop. 4227 * If the counters do reach their maximum 4228 * values, then a catastrophic error has 4229 * occurred. This should never be the case. 4230 * The counters only came into play during 4231 * development. 4232 */ 4233 while (((tmp = Msr(fdc)) & CB) && 4234 (i < 1000001)) { 4235 4236 /* 4237 * If RQM + DIO, then a result byte 4238 * is at hand. 4239 */ 4240 if ((tmp & (RQM|DIO|CB)) == 4241 (RQM|DIO|CB)) { 4242 fdc->c_csb.csb_rslt 4243 [fdc->c_csb.csb_nrslts++] 4244 = Fifo(fdc); 4245 4246 FDERRPRINT(FDEP_L1, FDEM_INTR, 4247 (C, 4248 "fdintr_dma: res 0x%x\n", 4249 fdc->c_csb.csb_rslt 4250 [fdc->c_csb.csb_nrslts 4251 - 1])); 4252 4253 } else if (--to == 0) { 4254 /* 4255 * controller was never 4256 * ready to give results 4257 */ 4258 fdc->c_csb.csb_status = 2; 4259 break; 4260 } 4261 i++; 4262 } 4263 if (i == 10000) { 4264 FDERRPRINT(FDEP_L1, FDEM_INTR, 4265 (C, "First loop overran\n")); 4266 } 4267 } 4268 4269 /* 4270 * See if the interrupt is from the DMA engine, 4271 * which will only interrupt on an error 4272 */ 4273 if ((!not_cheerio) && (tmp_dcsr & DCSR_ERR_PEND)) { 4274 4275 res = DDI_INTR_CLAIMED; 4276 4277 done = 1; 4278 fdc->c_csb.csb_dcsr_rslt = 1; 4279 FDERRPRINT(FDEP_L1, FDEM_INTR, 4280 (C, "fdintr_dma: Error pending\n")); 4281 reset_dma_controller(fdc); 4282 set_dma_control_register(fdc, DCSR_INIT_BITS); 4283 break; 4284 } 4285 4286 /* TCBUG kludge */ 4287 if ((fdc->c_fdtype & FDCTYPE_TCBUG) && 4288 ((fdc->c_csb.csb_rslt[0] & IC_SR0) == 0x40) && 4289 (fdc->c_csb.csb_rslt[1] & EN_SR1)) { 4290 4291 fdc->c_csb.csb_rslt[0] &= ~IC_SR0; 4292 4293 fdc->c_csb.csb_rslt[1] &= ~EN_SR1; 4294 4295 4296 } 4297 4298 4299 /* Exit if there were errors in the DMA */ 4300 if (((fdc->c_csb.csb_rslt[0] & IC_SR0) != 0) || 4301 (fdc->c_csb.csb_rslt[1] != 0) || 4302 (fdc->c_csb.csb_rslt[2] != 0)) { 4303 done = 1; 4304 FDERRPRINT(FDEP_L1, FDEM_INTR, 4305 (C, "fdintr_dma: errors in command\n")); 4306 4307 4308 break; 4309 } 4310 4311 4312 FDERRPRINT(FDEP_L1, FDEM_INTR, 4313 (C, "fdintr_dma: dbcr 0x%x\n", 4314 get_data_count_register(fdc))); 4315 /* 4316 * The csb_ccount is the number of cookies that still 4317 * need to be processed. A cookie was just processed 4318 * so decrement the cookie counter. 4319 */ 4320 if (fdc->c_csb.csb_ccount == 0) { 4321 done = 1; 4322 break; 4323 } 4324 fdc->c_csb.csb_ccount--; 4325 ccount = fdc->c_csb.csb_ccount; 4326 4327 windex = fdc->c_csb.csb_windex; 4328 4329 /* 4330 * If there are no more cookies and all the windows 4331 * have been DMA'd, then DMA is done. 4332 * 4333 */ 4334 if ((ccount == 0) && (windex == fdc->c_csb.csb_nwin)) { 4335 4336 done = 1; 4337 4338 /* 4339 * The handle is unbound in fdexec 4340 */ 4341 4342 break; 4343 } 4344 4345 if (ccount != 0) { 4346 /* process the next cookie */ 4347 ddi_dma_nextcookie(fdc->c_dmahandle, 4348 &fdc->c_csb.csb_dmacookie); 4349 4350 FDERRPRINT(FDEP_L1, FDEM_INTR, 4351 (C, "cookie addr 0x%" PRIx64 "\n", 4352 fdc->c_csb.csb_dmacookie.dmac_laddress)); 4353 4354 FDERRPRINT(FDEP_L1, FDEM_INTR, 4355 (C, "cookie length %lu\n", 4356 fdc->c_csb.csb_dmacookie.dmac_size)); 4357 4358 } else { 4359 4360 (void) ddi_dma_getwin(fdc->c_dmahandle, 4361 fdc->c_csb.csb_windex, 4362 &off, &len, 4363 &fdc->c_csb.csb_dmacookie, 4364 &fdc->c_csb.csb_ccount); 4365 fdc->c_csb.csb_windex++; 4366 4367 FDERRPRINT(FDEP_L1, FDEM_INTR, 4368 (C, "fdintr_dma: process %d window\n", 4369 fdc->c_csb.csb_windex)); 4370 4371 FDERRPRINT(FDEP_L1, FDEM_INTR, 4372 (C, "fdintr_dma: process no. cookies %d\n", 4373 fdc->c_csb.csb_ccount)); 4374 4375 FDERRPRINT(FDEP_L1, FDEM_INTR, 4376 (C, "cookie addr 0x%" PRIx64 "\n", 4377 fdc->c_csb.csb_dmacookie.dmac_laddress)); 4378 4379 FDERRPRINT(FDEP_L1, FDEM_INTR, 4380 (C, "cookie length %lu\n", 4381 fdc->c_csb.csb_dmacookie.dmac_size)); 4382 } 4383 4384 /* 4385 * Program the DMA engine with the length and 4386 * the address of the transfer 4387 */ 4388 4389 ASSERT(fdc->c_csb.csb_dmacookie.dmac_size); 4390 4391 set_data_count_register(fdc, 4392 fdc->c_csb.csb_dmacookie.dmac_size); 4393 set_data_address_register(fdc, 4394 fdc->c_csb.csb_dmacookie.dmac_laddress); 4395 4396 FDERRPRINT(FDEP_L1, FDEM_INTR, (C, 4397 "fdintr_dma: size 0x%lx\n", 4398 fdc->c_csb.csb_dmacookie.dmac_size)); 4399 4400 4401 /* reprogram the controller */ 4402 fdc->c_csb.csb_cmds[2] = fdc->c_csb.csb_rslt[3]; 4403 fdc->c_csb.csb_cmds[3] = fdc->c_csb.csb_rslt[4]; 4404 fdc->c_csb.csb_cmds[4] = fdc->c_csb.csb_rslt[5]; 4405 fdc->c_csb.csb_cmds[1] = (fdc->c_csb.csb_cmds[1] 4406 & ~0x04) | (fdc->c_csb.csb_rslt[4] << 2); 4407 4408 for (i = 0; i < (int)fdc->c_csb.csb_ncmds; i++) { 4409 4410 /* 4411 * Test the readiness of the controller 4412 * to receive the cmd 4413 */ 4414 for (to = FD_CRETRY; to; to--) { 4415 if ((Msr(fdc) & (DIO|RQM)) == RQM) 4416 break; 4417 } 4418 if (to == 0) { 4419 FDERRPRINT(FDEP_L2, FDEM_EXEC, 4420 (C, 4421 "fdc: no RQM - stat 0x%x\n", 4422 Msr(fdc))); 4423 /* stop the DMA from happening */ 4424 fdc->c_csb.csb_status = 2; 4425 done = 1; 4426 break; 4427 } 4428 4429 Set_Fifo(fdc, fdc->c_csb.csb_cmds[i]); 4430 4431 FDERRPRINT(FDEP_L1, FDEM_INTR, 4432 (C, 4433 "fdintr_dma: sent 0x%x, Msr 0x%x\n", 4434 fdc->c_csb.csb_cmds[i], Msr(fdc))); 4435 } 4436 4437 /* reenable DMA */ 4438 if ((!not_cheerio) && (!done)) 4439 set_dma_control_register(fdc, tmp_dcsr | 4440 DCSR_EN_DMA); 4441 break; 4442 4443 case 0x2: 4444 /* seek/recal type cmd */ 4445 FDERRPRINT(FDEP_L1, FDEM_INTR, 4446 (C, "fintr_dma: opmode 2\n")); 4447 4448 /* 4449 * See if the interrupt is from the DMA engine, 4450 * which will only interrupt if there was an error. 4451 */ 4452 if ((!not_cheerio) && (tmp_dcsr & DCSR_ERR_PEND)) { 4453 res = DDI_INTR_CLAIMED; 4454 done = 1; 4455 fdc->c_csb.csb_dcsr_rslt = 1; 4456 reset_dma_controller(fdc); 4457 set_dma_control_register(fdc, DCSR_INIT_BITS); 4458 4459 break; 4460 } 4461 4462 4463 /* See if the interrupt is from the floppy controller */ 4464 if (not_cheerio || (tmp_dcsr & DCSR_INT_PEND)) { 4465 4466 res = DDI_INTR_CLAIMED; 4467 4468 4469 /* 4470 * Wait until there's no longer a command 4471 * in progress 4472 */ 4473 4474 FDERRPRINT(FDEP_L1, FDEM_INTR, 4475 (C, "fdintr_dma: interrupt pending\n")); 4476 i = 0; 4477 while (((Msr(fdc) & CB)) && (i < 10000)) { 4478 i++; 4479 } 4480 4481 if (i == 10000) 4482 FDERRPRINT(FDEP_L1, FDEM_INTR, 4483 (C, "2nd loop overran !!!\n")); 4484 4485 /* 4486 * Check the RQM bit to see if the controller is 4487 * ready to transfer status of the command. 4488 */ 4489 i = 0; 4490 while ((!(Msr(fdc) & RQM)) && (i < 10000)) { 4491 i++; 4492 } 4493 4494 if (i == 10000) 4495 FDERRPRINT(FDEP_L1, FDEM_INTR, 4496 (C, "3rd loop overran !!!\n")); 4497 4498 /* 4499 * Issue the Sense Interrupt Status Command 4500 */ 4501 Set_Fifo(fdc, SNSISTAT); 4502 4503 i = 0; 4504 while ((!(Msr(fdc) & RQM)) && (i < 10000)) { 4505 i++; 4506 } 4507 if (i == 10000) 4508 FDERRPRINT(FDEP_L1, FDEM_INTR, 4509 (C, "4th loop overran !!!\n")); 4510 4511 /* Store the first result byte */ 4512 fdc->c_csb.csb_rslt[0] = Fifo(fdc); 4513 4514 i = 0; 4515 while ((!(Msr(fdc) & RQM)) && (i < 10000)) { 4516 i++; 4517 } 4518 if (i == 10000) 4519 FDERRPRINT(FDEP_L1, FDEM_INTR, 4520 (C, "5th loop overran !!!\n")); 4521 4522 /* Store the second result byte */ 4523 fdc->c_csb.csb_rslt[1] = Fifo(fdc); 4524 4525 done = 1; 4526 } 4527 4528 } 4529 4530 /* 4531 * We are done with the actual interrupt handling here. 4532 * The portion below should be actually be done by fd_lointr(). 4533 * We should be triggering the fd_lointr here and exiting. 4534 * However for want of time this will be done in the next FIX. 4535 * 4536 * Hence for now we will release hilock only and keep the remaining 4537 * code as it is. 4538 * Releasing of hilock ensures that we don't hold on to the 4539 * lolock and hilock at the same time. 4540 * hilock is acquired each time dma related registers are accessed. 4541 */ 4542 mutex_exit(&fdc->c_hilock); 4543 /* Make signal and get out of interrupt handler */ 4544 if (done) { 4545 mutex_enter(&fdc->c_lolock); 4546 4547 fdc->c_csb.csb_opmode = 0; 4548 4549 /* reset watchdog timer if armed and not already triggered */ 4550 4551 4552 if (fdc->c_timeid) { 4553 timeout_id_t timeid = fdc->c_timeid; 4554 fdc->c_timeid = 0; 4555 mutex_exit(&fdc->c_lolock); 4556 (void) untimeout(timeid); 4557 mutex_enter(&fdc->c_lolock); 4558 } 4559 4560 4561 if (fdc->c_flags & FDCFLG_WAITING) { 4562 /* 4563 * somebody's waiting on finish of fdctlr/csb, 4564 * wake them 4565 */ 4566 4567 FDERRPRINT(FDEP_L1, FDEM_INTR, 4568 (C, "fdintr_dma: signal the waiter\n")); 4569 4570 fdc->c_flags ^= FDCFLG_WAITING; 4571 cv_signal(&fdc->c_iocv); 4572 4573 /* 4574 * FDCFLG_BUSY is NOT cleared, NOR is the csb given 4575 * back; the operation just finished can look at the csb 4576 */ 4577 } else { 4578 FDERRPRINT(FDEP_L1, FDEM_INTR, 4579 (C, "fdintr_dma: nobody sleeping (%x %x %x)\n", 4580 fdc->c_csb.csb_rslt[0], fdc->c_csb.csb_rslt[1], 4581 fdc->c_csb.csb_rslt[2])); 4582 } 4583 mutex_exit(&fdc->c_lolock); 4584 } 4585 /* update high level interrupt counter */ 4586 if (fdc->c_intrstat) 4587 KIOIP->intrs[KSTAT_INTR_HARD]++; 4588 4589 4590 FDERRPRINT(FDEP_L1, FDEM_INTR, (C, "fdintr_dma: done\n")); 4591 return (res); 4592 } 4593 4594 /* 4595 * fd_lointr 4596 * This is the low level SW interrupt handler triggered by the high 4597 * level interrupt handler (or by fdwatch). 4598 */ 4599 static uint_t 4600 fd_lointr(caddr_t arg) 4601 { 4602 struct fdctlr *fdc = (struct fdctlr *)arg; 4603 struct fdcsb *csb; 4604 4605 csb = &fdc->c_csb; 4606 FDERRPRINT(FDEP_L1, FDEM_INTR, (C, "fdintr: opmode %d\n", 4607 csb->csb_opmode)); 4608 /* 4609 * Check that lowlevel interrupt really meant to trigger us. 4610 */ 4611 if (csb->csb_opmode != 4) { 4612 /* 4613 * This should probably be protected, but, what the 4614 * heck...the cost isn't worth the accuracy for this 4615 * statistic. 4616 */ 4617 if (fdc->c_intrstat) 4618 KIOIP->intrs[KSTAT_INTR_SPURIOUS]++; 4619 return (DDI_INTR_UNCLAIMED); 4620 } 4621 4622 mutex_enter(&fdc->c_lolock); 4623 csb->csb_opmode = 0; 4624 4625 /* reset watchdog timer if armed and not already triggered */ 4626 if (fdc->c_timeid) { 4627 timeout_id_t timeid = fdc->c_timeid; 4628 fdc->c_timeid = 0; 4629 mutex_exit(&fdc->c_lolock); 4630 (void) untimeout(timeid); 4631 mutex_enter(&fdc->c_lolock); 4632 4633 } 4634 4635 if (fdc->c_flags & FDCFLG_WAITING) { 4636 /* 4637 * somebody's waiting on finish of fdctlr/csb, wake them 4638 */ 4639 fdc->c_flags ^= FDCFLG_WAITING; 4640 cv_signal(&fdc->c_iocv); 4641 4642 /* 4643 * FDCFLG_BUSY is NOT cleared, NOR is the csb given back; so 4644 * the operation just finished can look at the csb 4645 */ 4646 } else { 4647 FDERRPRINT(FDEP_L3, FDEM_INTR, 4648 (C, "fdintr: nobody sleeping (%x %x %x)\n", 4649 csb->csb_rslt[0], csb->csb_rslt[1], csb->csb_rslt[2])); 4650 } 4651 if (fdc->c_intrstat) 4652 KIOIP->intrs[KSTAT_INTR_SOFT]++; 4653 mutex_exit(&fdc->c_lolock); 4654 return (DDI_INTR_CLAIMED); 4655 } 4656 4657 /* 4658 * fdwatch 4659 * is called from timein() when a floppy operation has expired. 4660 */ 4661 static void 4662 fdwatch(void *arg) 4663 { 4664 struct fdctlr *fdc = arg; 4665 int old_opmode; 4666 struct fdcsb *csb; 4667 4668 FDERRPRINT(FDEP_L1, FDEM_WATC, (C, "fdwatch\n")); 4669 4670 mutex_enter(&fdc->c_lolock); 4671 if (fdc->c_timeid == 0) { 4672 /* 4673 * fdintr got here first, ergo, no timeout condition.. 4674 */ 4675 4676 FDERRPRINT(FDEP_L1, FDEM_WATC, 4677 (C, "fdwatch: no timeout\n")); 4678 4679 mutex_exit(&fdc->c_lolock); 4680 return; 4681 } 4682 fdc->c_timeid = 0; 4683 csb = &fdc->c_csb; 4684 4685 mutex_enter(&fdc->c_hilock); 4686 /* 4687 * XXXX: We should probably reset the bloody chip 4688 */ 4689 old_opmode = csb->csb_opmode; 4690 4691 FDERRPRINT(FDEP_L1, FDEM_WATC, 4692 (C, "fd%d: timeout, opmode:%d\n", csb->csb_unit, old_opmode)); 4693 4694 csb->csb_opmode = 4; 4695 mutex_exit(&fdc->c_hilock); 4696 4697 FDERRPRINT(FDEP_L1, FDEM_WATC, (C, "fdwatch: cmd %s timed out\n", 4698 fdcmds[csb->csb_cmds[0] & 0x1f].cmdname)); 4699 fdc->c_flags |= FDCFLG_TIMEDOUT; 4700 csb->csb_status = CSB_CMDTO; 4701 4702 if ((fdc->c_fdtype & FDCTYPE_DMA) == 0) { 4703 ddi_trigger_softintr(fdc->c_softid); 4704 KIOIP->intrs[KSTAT_INTR_WATCHDOG]++; 4705 mutex_exit(&fdc->c_lolock); 4706 } else { 4707 mutex_exit(&fdc->c_lolock); 4708 (void) fd_lointr((caddr_t)fdctlrs); 4709 } 4710 } 4711 4712 /* 4713 * fdgetcsb 4714 * wait until the csb is free 4715 */ 4716 static void 4717 fdgetcsb(struct fdctlr *fdc) 4718 { 4719 FDERRPRINT(FDEP_L1, FDEM_GETC, (C, "fdgetcsb\n")); 4720 ASSERT(mutex_owned(&fdc->c_lolock)); 4721 while (fdc->c_flags & FDCFLG_BUSY) { 4722 fdc->c_flags |= FDCFLG_WANT; 4723 cv_wait(&fdc->c_csbcv, &fdc->c_lolock); 4724 } 4725 fdc->c_flags |= FDCFLG_BUSY; /* got it! */ 4726 } 4727 4728 /* 4729 * fdretcsb 4730 * return csb 4731 */ 4732 static void 4733 fdretcsb(struct fdctlr *fdc) 4734 { 4735 4736 ASSERT(mutex_owned(&fdc->c_lolock)); 4737 FDERRPRINT(FDEP_L1, FDEM_RETC, (C, "fdretcsb\n")); 4738 fdc->c_flags &= ~FDCFLG_BUSY; /* let go */ 4739 4740 fdc->c_csb.csb_read = 0; 4741 4742 if (fdc->c_flags & FDCFLG_WANT) { 4743 fdc->c_flags ^= FDCFLG_WANT; 4744 /* 4745 * broadcast the signal. One thread will wake up and 4746 * set the flags to FDCFLG_BUSY. If more than one thread is 4747 * waiting then each thread will wake up in turn. The first 4748 * thread to wake-up will set the FDCFLG_BUSY flag and the 4749 * subsequent threads will will wake-up, but reset the 4750 * flag to FDCFLG_WANT because the FDCFLG_BUSY bit is set. 4751 */ 4752 cv_broadcast(&fdc->c_csbcv); 4753 } 4754 } 4755 4756 4757 /* 4758 * fdreset 4759 * reset THE controller, and configure it to be 4760 * the way it ought to be 4761 * ASSUMES: that it already owns the csb/fdctlr! 4762 * 4763 * - called with the low level lock held 4764 */ 4765 static int 4766 fdreset(struct fdctlr *fdc) 4767 { 4768 struct fdcsb *csb; 4769 clock_t local_lbolt = 0; 4770 timeout_id_t timeid; 4771 4772 FDERRPRINT(FDEP_L1, FDEM_RESE, (C, "fdreset\n")); 4773 4774 ASSERT(mutex_owned(&fdc->c_lolock)); 4775 4776 /* count resets */ 4777 fdc->fdstats.reset++; 4778 4779 /* 4780 * On the 82077, the DSR will clear itself after a reset. Upon exiting 4781 * the reset, a polling interrupt will be generated. If the floppy 4782 * interrupt is enabled, it's possible for cv_signal() to be called 4783 * before cv_wait(). This will cause the system to hang. Turn off 4784 * the floppy interrupt to avoid this race condition 4785 */ 4786 if ((fdc->c_fdtype & FDCTYPE_CTRLMASK) == FDCTYPE_82077) { 4787 /* 4788 * We need to perform any timeouts before we Reset the 4789 * controller. We cannot afford to drop the c_lolock mutex after 4790 * Resetting the controller. The reason is that we get a spate 4791 * of interrupts until we take the controller out of reset. 4792 * The way we avoid this spate of continuous interrupts is by 4793 * holding on to the c_lolock and forcing the fdintr_dma routine 4794 * to go to sleep waiting for this mutex. 4795 */ 4796 /* Do not hold the mutex across the untimeout call */ 4797 timeid = fdc->c_mtimeid; 4798 fdc->c_mtimeid = 0; 4799 if (timeid) { 4800 mutex_exit(&fdc->c_lolock); 4801 (void) untimeout(timeid); 4802 mutex_enter(&fdc->c_lolock); 4803 } 4804 /* LINTED */ 4805 Set_dor(fdc, DMAGATE, 0); 4806 FDERRPRINT(FDEP_L1, FDEM_RESE, (C, "fdreset: set dor\n")); 4807 } 4808 4809 /* toggle software reset */ 4810 Dsr(fdc, SWR); 4811 4812 drv_usecwait(5); 4813 4814 FDERRPRINT(FDEP_L1, FDEM_RESE, 4815 (C, "fdreset: toggled software reset\n")); 4816 4817 /* 4818 * This sets the data rate to 500Kbps (for high density) 4819 * XXX should use current characteristics instead XXX 4820 */ 4821 Dsr(fdc, 0); 4822 drv_usecwait(5); 4823 switch (fdc->c_fdtype & FDCTYPE_CTRLMASK) { 4824 case FDCTYPE_82077: 4825 /* 4826 * when we bring the controller out of reset it will generate 4827 * a polling interrupt. fdintr() will field it and schedule 4828 * fd_lointr(). There will be no one sleeping but we are 4829 * expecting an interrupt so.... 4830 */ 4831 fdc->c_flags |= FDCFLG_WAITING; 4832 4833 /* 4834 * The reset bit must be cleared to take the 077 out of 4835 * reset state and the DMAGATE bit must be high to enable 4836 * interrupts. 4837 */ 4838 /* LINTED */ 4839 Set_dor(fdc, DMAGATE|RESET, 1); 4840 4841 FDERRPRINT(FDEP_L1, FDEM_ATTA, 4842 (C, "fdattach: Dor 0x%x\n", Dor(fdc))); 4843 4844 local_lbolt = ddi_get_lbolt(); 4845 if (cv_timedwait(&fdc->c_iocv, &fdc->c_lolock, 4846 local_lbolt + drv_usectohz(1000000)) == -1) { 4847 return (-1); 4848 } 4849 break; 4850 4851 default: 4852 fdc->c_flags |= FDCFLG_WAITING; 4853 4854 /* 4855 * A timed wait is not used because it's possible for the timer 4856 * to go off before the controller has a chance to interrupt. 4857 */ 4858 cv_wait(&fdc->c_iocv, &fdc->c_lolock); 4859 break; 4860 } 4861 csb = &fdc->c_csb; 4862 4863 /* setup common things in csb */ 4864 csb->csb_unit = fdc->c_un->un_unit_no; 4865 csb->csb_nrslts = 0; 4866 csb->csb_opflags = CSB_OFNORESULTS; 4867 csb->csb_maxretry = 0; 4868 csb->csb_retrys = 0; 4869 4870 csb->csb_read = CSB_NULL; 4871 4872 /* send SPECIFY command to fdc */ 4873 /* csb->unit is don't care */ 4874 csb->csb_cmds[0] = FDRAW_SPECIFY; 4875 csb->csb_cmds[1] = fdspec[0]; /* step rate, head unload time */ 4876 if (fdc->c_fdtype & FDCTYPE_DMA) 4877 csb->csb_cmds[2] = SPEC_DMA_MODE; 4878 else 4879 csb->csb_cmds[2] = fdspec[1]; /* head load time, DMA mode */ 4880 4881 csb->csb_ncmds = 3; 4882 4883 /* XXX for now ignore errors, they "CAN'T HAPPEN" */ 4884 (void) fdexec(fdc, 0); /* no FDXC_CHECKCHG, ... */ 4885 /* no results */ 4886 4887 /* send CONFIGURE command to fdc */ 4888 /* csb->unit is don't care */ 4889 csb->csb_cmds[0] = CONFIGURE; 4890 csb->csb_cmds[1] = fdconf[0]; /* motor info, motor delays */ 4891 csb->csb_cmds[2] = fdconf[1]; /* enaimplsk, disapoll, fifothru */ 4892 csb->csb_cmds[3] = fdconf[2]; /* track precomp */ 4893 csb->csb_ncmds = 4; 4894 4895 csb->csb_read = CSB_NULL; 4896 4897 csb->csb_retrys = 0; 4898 4899 /* XXX for now ignore errors, they "CAN'T HAPPEN" */ 4900 (void) fdexec(fdc, 0); /* no FDXC_CHECKCHG, ... */ 4901 return (0); 4902 } 4903 4904 /* 4905 * fdrecalseek 4906 * performs recalibrates or seeks if the "arg" is -1 does a 4907 * recalibrate on a drive, else it seeks to the cylinder of 4908 * the drive. The recalibrate is also used to find a drive, 4909 * ie if the drive is not there, the controller says "error" 4910 * on the operation 4911 * NOTE: that there is special handling of this operation in the hardware 4912 * interrupt routine - it causes the operation to appear to have results; 4913 * ie the results of the SENSE INTERRUPT STATUS that the hardware interrupt 4914 * function did for us. 4915 * NOTE: because it uses sleep/wakeup it must be protected in a critical 4916 * section so create one before calling it! 4917 * 4918 * RETURNS: 0 for ok, 4919 * else errno from fdexec, 4920 * or ENODEV if error (infers hardware type error) 4921 * 4922 * - called with the low level lock held 4923 */ 4924 static int 4925 fdrecalseek(struct fdctlr *fdc, int unit, int arg, int execflg) 4926 { 4927 struct fdcsb *csb; 4928 int result; 4929 4930 ASSERT(fdc->c_un->un_unit_no == unit); 4931 4932 FDERRPRINT(FDEP_L1, FDEM_RECA, (C, "fdrecalseek to %d\n", arg)); 4933 4934 /* XXX TODO: check see argument for <= num cyls OR < 256 */ 4935 4936 csb = &fdc->c_csb; 4937 csb->csb_unit = (uchar_t)unit; 4938 csb->csb_cmds[1] = unit & 0x03; 4939 4940 if (arg == -1) { /* is recal... */ 4941 csb->csb_cmds[0] = FDRAW_REZERO; 4942 csb->csb_ncmds = 2; 4943 } else { 4944 csb->csb_cmds[0] = FDRAW_SEEK; 4945 csb->csb_cmds[2] = (uchar_t)arg; 4946 csb->csb_ncmds = 3; 4947 } 4948 csb->csb_nrslts = 2; /* 2 for SENSE INTERRUPTS */ 4949 csb->csb_opflags = CSB_OFSEEKOPS | CSB_OFTIMEIT; 4950 /* 4951 * MAYBE NYD need to set retries to different values? - depending on 4952 * drive characteristics - if we get to high capacity drives 4953 */ 4954 csb->csb_maxretry = skretry; 4955 csb->csb_retrys = 0; 4956 4957 /* send cmd off to fdexec */ 4958 if (result = fdexec(fdc, FDXC_SLEEP | execflg)) { 4959 goto out; 4960 } 4961 4962 /* 4963 * if recal, test for equipment check error 4964 * ASSUMES result = 0 from above call 4965 */ 4966 if (arg == -1) { 4967 result = 0; 4968 } else { 4969 /* for seeks, any old error will do */ 4970 if ((csb->csb_rslt[0] & IC_SR0) || csb->csb_cmdstat) 4971 result = ENODEV; 4972 } 4973 4974 out: 4975 return (result); 4976 } 4977 4978 /* 4979 * fdsensedrv 4980 * do a sense_drive command. used by fdopen and fdcheckdisk. 4981 * 4982 * - called with the lock held 4983 */ 4984 static int 4985 fdsensedrv(struct fdctlr *fdc, int unit) 4986 { 4987 struct fdcsb *csb; 4988 4989 ASSERT(fdc->c_un->un_unit_no == unit); 4990 4991 csb = &fdc->c_csb; 4992 4993 /* setup common things in csb */ 4994 csb->csb_unit = (uchar_t)unit; 4995 csb->csb_opflags = CSB_OFIMMEDIATE; 4996 csb->csb_cmds[0] = FDRAW_SENSE_DRV; 4997 /* MOT bit set means don't delay */ 4998 csb->csb_cmds[1] = MOT | (unit & 0x03); 4999 csb->csb_ncmds = 2; 5000 csb->csb_nrslts = 1; 5001 csb->csb_maxretry = skretry; 5002 csb->csb_retrys = 0; 5003 5004 /* XXX for now ignore errors, they "CAN'T HAPPEN" */ 5005 (void) fdexec(fdc, 0); /* DON't check changed!, no sleep */ 5006 5007 FDERRPRINT(FDEP_L1, FDEM_CHEK, 5008 (C, "fdsensedrv: result 0x%x", csb->csb_rslt[0])); 5009 5010 return (csb->csb_rslt[0]); /* return status byte 3 */ 5011 } 5012 5013 /* 5014 * fdcheckdisk 5015 * check to see if the disk is still there - do a recalibrate, 5016 * then see if DSKCHG line went away, if so, diskette is in; else 5017 * it's (still) out. 5018 */ 5019 5020 static int 5021 fdcheckdisk(struct fdctlr *fdc, int unit) 5022 { 5023 auto struct fdcsb savecsb; 5024 struct fdcsb *csb; 5025 int err, st3; 5026 int seekto; /* where to seek for reset of DSKCHG */ 5027 5028 FDERRPRINT(FDEP_L1, FDEM_CHEK, 5029 (C, "fdcheckdisk, unit %d\n", unit)); 5030 5031 ASSERT(fdc->c_un->un_unit_no == unit); 5032 5033 /* 5034 * save old csb 5035 */ 5036 5037 csb = &fdc->c_csb; 5038 savecsb = fdc->c_csb; 5039 bzero((caddr_t)csb, sizeof (*csb)); 5040 5041 /* 5042 * Read drive status to see if at TRK0, if so, seek to cyl 1, 5043 * else seek to cyl 0. We do this because the controller is 5044 * "smart" enough to not send any step pulses (which are how 5045 * the DSKCHG line gets reset) if it sees TRK0 'cause it 5046 * knows the drive is already recalibrated. 5047 */ 5048 st3 = fdsensedrv(fdc, unit); 5049 5050 /* check TRK0 bit in status */ 5051 if (st3 & T0_SR3) 5052 seekto = 1; /* at TRK0, seek out */ 5053 else 5054 seekto = 0; 5055 5056 /* 5057 * DON'T recurse check changed 5058 */ 5059 err = fdrecalseek(fdc, unit, seekto, 0); 5060 5061 /* "restore" old csb, check change state */ 5062 fdc->c_csb = savecsb; 5063 5064 /* any recal/seek errors are too serious to attend to */ 5065 if (err) { 5066 FDERRPRINT(FDEP_L2, FDEM_CHEK, 5067 (C, "fdcheckdisk err %d\n", err)); 5068 return (err); 5069 } 5070 5071 /* 5072 * if disk change still asserted, no diskette in drive! 5073 */ 5074 if (fdsense_chng(fdc, csb->csb_unit)) { 5075 FDERRPRINT(FDEP_L2, FDEM_CHEK, 5076 (C, "fdcheckdisk no disk\n")); 5077 return (1); 5078 } 5079 return (0); 5080 } 5081 5082 /* 5083 * fdselect() - select drive, needed for external to chip select logic 5084 * fdeject() - ejects drive, must be previously selected 5085 * fdsense_chng() - sense disk changed line from previously selected drive 5086 * return s 1 is signal asserted, else 0 5087 */ 5088 /* ARGSUSED */ 5089 static void 5090 fdselect(struct fdctlr *fdc, int unit, int on) 5091 { 5092 5093 ASSERT(fdc->c_un->un_unit_no == unit); 5094 5095 FDERRPRINT(FDEP_L1, FDEM_DSEL, 5096 (C, "fdselect, unit %d, on = %d\n", unit, on)); 5097 5098 switch (fdc->c_fdtype & FDCTYPE_AUXIOMASK) { 5099 case FDCTYPE_MACHIO: 5100 set_auxioreg(AUX_DRVSELECT, on); 5101 break; 5102 5103 case FDCTYPE_SLAVIO: 5104 case FDCTYPE_CHEERIO: 5105 FDERRPRINT(FDEP_L1, FDEM_ATTA, 5106 (C, "fdselect: (before) Dor 0x%x\n", Dor(fdc))); 5107 5108 if (unit == 0) { 5109 Set_dor(fdc, DRVSEL, !on); 5110 } else { 5111 Set_dor(fdc, DRVSEL, on); 5112 } 5113 5114 FDERRPRINT(FDEP_L1, FDEM_ATTA, 5115 (C, "fdselect: Dor 0x%x\n", Dor(fdc))); 5116 5117 break; 5118 5119 default: 5120 break; 5121 } 5122 } 5123 5124 /* ARGSUSED */ 5125 static void 5126 fdeject(struct fdctlr *fdc, int unit) 5127 { 5128 struct fdunit *un; 5129 5130 ASSERT(fdc->c_un->un_unit_no == unit); 5131 5132 un = fdc->c_un; 5133 5134 FDERRPRINT(FDEP_L1, FDEM_EJEC, (C, "fdeject\n")); 5135 /* 5136 * assume delay of function calling sufficient settling time 5137 * eject line is NOT driven by inverter so it is true low 5138 */ 5139 switch (fdc->c_fdtype & FDCTYPE_AUXIOMASK) { 5140 case FDCTYPE_MACHIO: 5141 set_auxioreg(AUX_EJECT, 0); 5142 drv_usecwait(2); 5143 set_auxioreg(AUX_EJECT, 1); 5144 break; 5145 5146 case FDCTYPE_SLAVIO: 5147 if (!(Dor(fdc) & MOTEN(unit))) { 5148 /* LINTED */ 5149 Set_dor(fdc, MOTEN(unit), 1); 5150 } 5151 drv_usecwait(2); /* just to settle */ 5152 /* LINTED */ 5153 Set_dor(fdc, EJECT, 1); 5154 drv_usecwait(2); 5155 /* LINTED */ 5156 Set_dor(fdc, EJECT, 0); 5157 break; 5158 case FDCTYPE_CHEERIO: 5159 if (!(Dor(fdc) & MOTEN(unit))) { 5160 /* LINTED */ 5161 Set_dor(fdc, MOTEN(unit), 1); 5162 } 5163 drv_usecwait(2); /* just to settle */ 5164 /* LINTED */ 5165 Set_dor(fdc, EJECT_DMA, 1); 5166 drv_usecwait(2); 5167 /* LINTED */ 5168 Set_dor(fdc, EJECT_DMA, 0); 5169 break; 5170 } 5171 /* 5172 * XXX set ejected state? 5173 */ 5174 un->un_ejected = 1; 5175 } 5176 5177 /* ARGSUSED */ 5178 static int 5179 fdsense_chng(struct fdctlr *fdc, int unit) 5180 { 5181 int changed = 0; 5182 5183 FDERRPRINT(FDEP_L1, FDEM_SCHG, (C, "fdsense_chng:start\n")); 5184 5185 ASSERT(fdc->c_un->un_unit_no == unit); 5186 5187 /* 5188 * Do not turn on the motor of a pollable drive 5189 */ 5190 if (fd_pollable) { 5191 FDERRPRINT(FDEP_L1, FDEM_SCHG, (C, "pollable: don't turn on motor\n")); 5192 /* 5193 * Invert the sense of the DSKCHG for pollable drives 5194 */ 5195 if (Dir(fdc) & DSKCHG) 5196 changed = 0; 5197 else 5198 changed = 1; 5199 5200 return (changed); 5201 } 5202 5203 switch (fdc->c_fdtype & FDCTYPE_AUXIOMASK) { 5204 case FDCTYPE_MACHIO: 5205 if (*fdc->c_auxiova & AUX_DISKCHG) 5206 changed = 1; 5207 break; 5208 5209 case FDCTYPE_SB: 5210 case FDCTYPE_SLAVIO: 5211 case FDCTYPE_CHEERIO: 5212 if (!(Dor(fdc) & MOTEN(unit))) { 5213 /* LINTED */ 5214 Set_dor(fdc, MOTEN(unit), 1); 5215 } 5216 drv_usecwait(2); /* just to settle */ 5217 if (Dir(fdc) & DSKCHG) 5218 changed = 1; 5219 break; 5220 } 5221 5222 FDERRPRINT(FDEP_L1, FDEM_SCHG, (C, "fdsense_chng:end\n")); 5223 5224 return (changed); 5225 } 5226 5227 /* 5228 * if it can read a valid label it does so, else it will use a 5229 * default. If it can`t read the diskette - that is an error. 5230 * 5231 * RETURNS: 0 for ok - meaning that it could at least read the device, 5232 * !0 for error XXX TBD NYD error codes 5233 * 5234 * - called with the low level lock held 5235 */ 5236 static int 5237 fdgetlabel(struct fdctlr *fdc, int unit) 5238 { 5239 struct dk_label *label = NULL; 5240 struct fdunit *un; 5241 short *sp; 5242 short count; 5243 short xsum; /* checksum */ 5244 int i, tries; 5245 int err = 0; 5246 short oldlvl; 5247 5248 FDERRPRINT(FDEP_L1, FDEM_GETL, 5249 (C, "fdgetlabel: unit %d\n", unit)); 5250 5251 un = fdc->c_un; 5252 un->un_flags &= ~(FDUNIT_UNLABELED); 5253 5254 ASSERT(fdc->c_un->un_unit_no == unit); 5255 5256 /* Do not print errors since this is a private cmd */ 5257 5258 oldlvl = fderrlevel; 5259 5260 5261 fderrlevel = FDEP_L4; 5262 5263 label = (struct dk_label *) 5264 kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 5265 5266 /* 5267 * try different characteristics (ie densities) by attempting to read 5268 * from the diskette. The diskette may not be present or 5269 * is unformatted. 5270 * 5271 * First, the last sector of the first track is read. If this 5272 * passes, attempt to read the last sector + 1 of the first track. 5273 * For example, for a high density diskette, sector 18 is read. If 5274 * the diskette is high density, this will pass. Next, try to 5275 * read sector 19 of the first track. This should fail. If it 5276 * passes, this is not a high density diskette. Finally, read 5277 * the first sector which should contain a label. 5278 * 5279 * if un->un_curfdtype is -1 then the current characteristics 5280 * were set by FDIOSCHAR and need to try it as well as everything 5281 * in the table 5282 */ 5283 if (un->un_curfdtype == -1) { 5284 tries = nfdtypes+1; 5285 FDERRPRINT(FDEP_L1, FDEM_GETL, 5286 (C, "fdgetl: un_curfdtype is -1\n")); 5287 5288 } else { 5289 tries = nfdtypes; 5290 5291 /* Always start with the highest density (1.7MB) */ 5292 un->un_curfdtype = 0; 5293 *(un->un_chars) = fdtypes[un->un_curfdtype]; 5294 } 5295 5296 FDERRPRINT(FDEP_L1, FDEM_GETL, 5297 (C, "fdgetl: no. of tries %d\n", tries)); 5298 FDERRPRINT(FDEP_L1, FDEM_GETL, 5299 (C, "fdgetl: no. of curfdtype %d\n", un->un_curfdtype)); 5300 5301 for (i = 0; i < tries; i++) { 5302 FDERRPRINT(FDEP_L1, FDEM_GETL, 5303 (C, "fdgetl: trying %d\n", i)); 5304 5305 if (!(err = fdrw(fdc, unit, FDREAD, 0, 0, 5306 un->un_chars->fdc_secptrack, (caddr_t)label, 5307 sizeof (struct dk_label))) && 5308 5309 fdrw(fdc, unit, FDREAD, 0, 0, 5310 un->un_chars->fdc_secptrack + 1, 5311 (caddr_t)label, sizeof (struct dk_label)) && 5312 5313 !(err = fdrw(fdc, unit, FDREAD, 0, 0, 1, (caddr_t)label, 5314 sizeof (struct dk_label)))) { 5315 5316 FDERRPRINT(FDEP_L1, FDEM_GETL, 5317 (C, "fdgetl: succeeded\n")); 5318 5319 break; 5320 } 5321 5322 /* 5323 * try the next entry in the characteristics tbl 5324 * If curfdtype is -1, the nxt entry in tbl is 0 (the first). 5325 */ 5326 5327 un->un_curfdtype = (un->un_curfdtype + 1) % nfdtypes; 5328 *(un->un_chars) = fdtypes[un->un_curfdtype]; 5329 5330 5331 } 5332 5333 /* print errors again */ 5334 fderrlevel = oldlvl; 5335 5336 /* Couldn't read anything */ 5337 if (err) { 5338 5339 /* The default characteristics are high density (1.4MB) */ 5340 un->un_curfdtype = 1; 5341 *(un->un_chars) = fdtypes[un->un_curfdtype]; 5342 5343 fdunpacklabel(&fdlbl_high_80, &un->un_label); 5344 5345 FDERRPRINT(FDEP_L1, FDEM_GETL, 5346 (C, "fdgetl: Can't autosense diskette\n")); 5347 5348 goto out; 5349 } 5350 5351 FDERRPRINT(FDEP_L1, FDEM_GETL, 5352 (C, "fdgetl: fdtype=%d !!!\n", un->un_curfdtype)); 5353 FDERRPRINT(FDEP_L1, FDEM_GETL, 5354 (C, "fdgetl: rate=%d ssize=%d !!!\n", 5355 un->un_chars->fdc_transfer_rate, un->un_chars->fdc_sec_size)); 5356 5357 /* 5358 * _something_ was read - look for unixtype label 5359 */ 5360 if (label->dkl_magic != DKL_MAGIC) { 5361 5362 /* 5363 * The label isn't a unix label. However, the diskette 5364 * is formatted because we were able to read the first 5365 * cylinder. 5366 */ 5367 5368 FDERRPRINT(FDEP_L1, FDEM_GETL, 5369 (C, "fdgetl: not unix label\n")); 5370 5371 goto nolabel; 5372 } 5373 5374 /* 5375 * Checksum the label 5376 */ 5377 count = sizeof (struct dk_label)/sizeof (short); 5378 sp = (short *)label; 5379 xsum = 0; 5380 while (count--) 5381 xsum ^= *sp++; /* should add up to 0 */ 5382 if (xsum) { 5383 5384 /* 5385 * The checksum fails. However, the diskette is formatted 5386 * because we were able to read the first cylinder 5387 */ 5388 5389 FDERRPRINT(FDEP_L1, FDEM_GETL, 5390 (C, "fdgetl: bad cksum\n")); 5391 5392 goto nolabel; 5393 } 5394 5395 /* 5396 * The diskette has a unix label with a correct checksum. 5397 * Copy the label into the unit structure 5398 */ 5399 un->un_label = *label; 5400 5401 goto out; 5402 5403 nolabel: 5404 /* 5405 * The diskette doesn't have a correct unix label, but it is formatted. 5406 * Use a default label according to the diskette's density 5407 * (mark default used) 5408 */ 5409 FDERRPRINT(FDEP_L1, FDEM_GETL, 5410 (C, "fdgetlabel: unit %d\n", unit)); 5411 un->un_flags |= FDUNIT_UNLABELED; 5412 switch (un->un_chars->fdc_secptrack) { 5413 case 9: 5414 fdunpacklabel(&fdlbl_low_80, &un->un_label); 5415 break; 5416 case 8: 5417 fdunpacklabel(&fdlbl_medium_80, &un->un_label); 5418 break; 5419 case 18: 5420 fdunpacklabel(&fdlbl_high_80, &un->un_label); 5421 break; 5422 case 21: 5423 fdunpacklabel(&fdlbl_high_21, &un->un_label); 5424 break; 5425 default: 5426 fdunpacklabel(&fdlbl_high_80, &un->un_label); 5427 break; 5428 } 5429 5430 out: 5431 if (label != NULL) 5432 kmem_free((caddr_t)label, sizeof (struct dk_label)); 5433 return (err); 5434 } 5435 5436 /* 5437 * fdrw- used only for reading labels and for DKIOCSVTOC ioctl 5438 * which reads the 1 sector. 5439 */ 5440 static int 5441 fdrw(struct fdctlr *fdc, int unit, int rw, int cyl, int head, 5442 int sector, caddr_t bufp, uint_t len) 5443 { 5444 struct fdcsb *csb; 5445 struct fd_char *ch; 5446 int cmdresult = 0; 5447 caddr_t dma_addr; 5448 size_t real_length; 5449 int res; 5450 ddi_device_acc_attr_t attr; 5451 ddi_acc_handle_t mem_handle = NULL; 5452 5453 FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fdrw\n")); 5454 5455 ASSERT(fdc->c_un->un_unit_no == unit); 5456 5457 CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc); 5458 5459 if (fdc->c_un->un_state == FD_STATE_STOPPED) { 5460 mutex_exit(&fdc->c_lolock); 5461 if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON)) 5462 != DDI_SUCCESS) { 5463 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power change \ 5464 failed. \n")); 5465 mutex_enter(&fdc->c_lolock); 5466 return (EIO); 5467 } 5468 5469 mutex_enter(&fdc->c_lolock); 5470 } 5471 5472 fdgetcsb(fdc); 5473 csb = &fdc->c_csb; 5474 ch = fdc->c_un->un_chars; 5475 if (rw == FDREAD) { 5476 if (fdc->c_fdtype & FDCTYPE_TCBUG) { 5477 /* 5478 * kludge for lack of Multitrack functionality 5479 */ 5480 csb->csb_cmds[0] = SK + FDRAW_RDCMD; 5481 } else 5482 csb->csb_cmds[0] = MT + SK + FDRAW_RDCMD; 5483 } else { /* write */ 5484 if (fdc->c_fdtype & FDCTYPE_TCBUG) { 5485 /* 5486 * kludge for lack of Multitrack functionality 5487 */ 5488 csb->csb_cmds[0] = FDRAW_WRCMD; 5489 } else 5490 csb->csb_cmds[0] = MT + FDRAW_WRCMD; 5491 } 5492 5493 if (rw == FDREAD) 5494 fdc->c_csb.csb_read = CSB_READ; 5495 else 5496 fdc->c_csb.csb_read = CSB_WRITE; 5497 5498 /* always or in MFM bit */ 5499 csb->csb_cmds[0] |= MFM; 5500 csb->csb_cmds[1] = (uchar_t)(unit | ((head & 0x1) << 2)); 5501 if (fdc->c_fdtype & FDCTYPE_SB) 5502 csb->csb_cmds[1] |= IPS; 5503 csb->csb_cmds[2] = (uchar_t)cyl; 5504 csb->csb_cmds[3] = (uchar_t)head; 5505 csb->csb_cmds[4] = (uchar_t)sector; 5506 csb->csb_cmds[5] = ch->fdc_medium ? 3 : 2; /* sector size code */ 5507 /* 5508 * kludge for end-of-cylinder error. 5509 */ 5510 if (fdc->c_fdtype & FDCTYPE_TCBUG) 5511 csb->csb_cmds[6] = sector + (len / ch->fdc_sec_size) - 1; 5512 else 5513 csb->csb_cmds[6] = 5514 (uchar_t)max(fdc->c_un->un_chars->fdc_secptrack, sector); 5515 csb->csb_len = len; 5516 csb->csb_cmds[7] = GPLN; 5517 csb->csb_cmds[8] = SSSDTL; 5518 csb->csb_ncmds = NCBRW; 5519 csb->csb_len = len; 5520 csb->csb_maxretry = 2; 5521 csb->csb_retrys = 0; 5522 bzero(csb->csb_rslt, NRBRW); 5523 csb->csb_nrslts = NRBRW; 5524 csb->csb_opflags = CSB_OFXFEROPS | CSB_OFTIMEIT; 5525 5526 /* If platform supports DMA, set up DMA resources */ 5527 if (fdc->c_fdtype & FDCTYPE_DMA) { 5528 5529 mutex_enter(&fdc->c_hilock); 5530 5531 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 5532 attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC; 5533 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 5534 5535 res = ddi_dma_mem_alloc(fdc->c_dmahandle, len, 5536 &attr, DDI_DMA_STREAMING, 5537 DDI_DMA_DONTWAIT, 0, &dma_addr, &real_length, 5538 &mem_handle); 5539 5540 if (res != DDI_SUCCESS) { 5541 FDERRPRINT(FDEP_L1, FDEM_RW, 5542 (C, "fdrw: dma mem alloc failed\n")); 5543 5544 fdretcsb(fdc); 5545 mutex_exit(&fdc->c_hilock); 5546 return (EIO); 5547 } 5548 5549 FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fdrw: allocated memory")); 5550 5551 if (fdstart_dma(fdc, dma_addr, len) != 0) { 5552 fdretcsb(fdc); 5553 ddi_dma_mem_free(&mem_handle); 5554 mutex_exit(&fdc->c_hilock); 5555 return (-1); 5556 5557 } 5558 5559 /* 5560 * If the command is a write, copy the data to be written to 5561 * dma_addr. 5562 */ 5563 5564 if (fdc->c_csb.csb_read == CSB_WRITE) { 5565 bcopy((char *)bufp, (char *)dma_addr, len); 5566 } 5567 5568 csb->csb_addr = dma_addr; 5569 mutex_exit(&fdc->c_hilock); 5570 } else { 5571 csb->csb_addr = bufp; 5572 } 5573 5574 5575 FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fdrw: call fdexec\n")); 5576 5577 if (fdexec(fdc, FDXC_SLEEP | FDXC_CHECKCHG) != 0) { 5578 fdretcsb(fdc); 5579 5580 if (mem_handle) 5581 ddi_dma_mem_free(&mem_handle); 5582 5583 return (EIO); 5584 5585 } 5586 5587 FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fdrw: fdexec returned\n")); 5588 5589 /* 5590 * if DMA was used and the command was a read 5591 * copy the results into bufp 5592 */ 5593 if (fdc->c_fdtype & FDCTYPE_DMA) { 5594 if (fdc->c_csb.csb_read == CSB_READ) { 5595 bcopy((char *)dma_addr, (char *)bufp, len); 5596 } 5597 ddi_dma_mem_free(&mem_handle); 5598 } 5599 5600 if (csb->csb_cmdstat) 5601 cmdresult = EIO; /* XXX TBD NYD for now */ 5602 5603 fdretcsb(fdc); 5604 return (cmdresult); 5605 } 5606 5607 /* 5608 * fdunpacklabel 5609 * this unpacks a (packed) struct dk_label into a standard dk_label. 5610 */ 5611 static void 5612 fdunpacklabel(struct packed_label *from, struct dk_label *to) 5613 { 5614 FDERRPRINT(FDEP_L1, FDEM_PACK, (C, "fdpacklabel\n")); 5615 bzero((caddr_t)to, sizeof (*to)); 5616 bcopy((caddr_t)&from->dkl_vname, (caddr_t)to->dkl_asciilabel, 5617 sizeof (to->dkl_asciilabel)); 5618 to->dkl_rpm = from->dkl_rpm; /* rotations per minute */ 5619 to->dkl_pcyl = from->dkl_pcyl; /* # physical cylinders */ 5620 to->dkl_apc = from->dkl_apc; /* alternates per cylinder */ 5621 to->dkl_intrlv = from->dkl_intrlv; /* interleave factor */ 5622 to->dkl_ncyl = from->dkl_ncyl; /* # of data cylinders */ 5623 to->dkl_acyl = from->dkl_acyl; /* # of alternate cylinders */ 5624 to->dkl_nhead = from->dkl_nhead; /* # of heads in this partition */ 5625 to->dkl_nsect = from->dkl_nsect; /* # of 512 byte sectors per track */ 5626 /* logical partitions */ 5627 bcopy((caddr_t)from->dkl_map, (caddr_t)to->dkl_map, 5628 sizeof (struct dk_map32) * NDKMAP); 5629 to->dkl_vtoc = from->dkl_vtoc; 5630 } 5631 5632 static struct fdctlr * 5633 fd_getctlr(dev_t dev) 5634 { 5635 5636 struct fdctlr *fdc = fdctlrs; 5637 int ctlr = FDCTLR(dev); 5638 5639 while (fdc) { 5640 if (ddi_get_instance(fdc->c_dip) == ctlr) 5641 return (fdc); 5642 fdc = fdc->c_next; 5643 } 5644 return (fdc); 5645 } 5646 5647 static int 5648 fd_unit_is_open(struct fdunit *un) 5649 { 5650 int i; 5651 for (i = 0; i < NDKMAP; i++) 5652 if (un->un_lyropen[i]) 5653 return (1); 5654 for (i = 0; i < OTYPCNT - 1; i++) 5655 if (un->un_regopen[i]) 5656 return (1); 5657 return (0); 5658 } 5659 5660 /* 5661 * Return the a vtoc structure in *vtoc. 5662 * The vtoc is built from information in 5663 * the diskette's label. 5664 */ 5665 static void 5666 fd_build_user_vtoc(struct fdunit *un, struct vtoc *vtoc) 5667 { 5668 int i; 5669 int nblks; /* DEV_BSIZE sectors per cylinder */ 5670 struct dk_map2 *lpart; 5671 struct dk_map32 *lmap; 5672 struct partition *vpart; 5673 5674 bzero(vtoc, sizeof (struct vtoc)); 5675 5676 /* Initialize info. needed by mboot. (unsupported) */ 5677 vtoc->v_bootinfo[0] = un->un_label.dkl_vtoc.v_bootinfo[0]; 5678 vtoc->v_bootinfo[1] = un->un_label.dkl_vtoc.v_bootinfo[1]; 5679 vtoc->v_bootinfo[2] = un->un_label.dkl_vtoc.v_bootinfo[2]; 5680 5681 /* Fill in vtoc sanity and version information */ 5682 vtoc->v_sanity = un->un_label.dkl_vtoc.v_sanity; 5683 vtoc->v_version = un->un_label.dkl_vtoc.v_version; 5684 5685 /* Copy the volume name */ 5686 bcopy(un->un_label.dkl_vtoc.v_volume, 5687 vtoc->v_volume, LEN_DKL_VVOL); 5688 5689 /* 5690 * The dk_map32 structure is based on DEV_BSIZE byte blocks. 5691 * However, medium density diskettes have 1024 byte blocks. 5692 * The number of sectors per partition listed in the dk_map32 structure 5693 * accounts for this by multiplying the number of 1024 byte 5694 * blocks by 2. (See the packed_label initializations.) The 5695 * 1024 byte block size can not be listed for medium density 5696 * diskettes because the kernel is hard coded for DEV_BSIZE 5697 * blocks. 5698 */ 5699 vtoc->v_sectorsz = DEV_BSIZE; 5700 vtoc->v_nparts = un->un_label.dkl_vtoc.v_nparts; 5701 5702 /* Copy the reserved space */ 5703 bcopy(un->un_label.dkl_vtoc.v_reserved, 5704 vtoc->v_reserved, sizeof (un->un_label.dkl_vtoc.v_reserved)); 5705 /* 5706 * Convert partitioning information. 5707 * 5708 * Note the conversion from starting cylinder number 5709 * to starting sector number. 5710 */ 5711 lmap = un->un_label.dkl_map; 5712 lpart = un->un_label.dkl_vtoc.v_part; 5713 vpart = vtoc->v_part; 5714 5715 nblks = (un->un_chars->fdc_nhead * un->un_chars->fdc_secptrack * 5716 un->un_chars->fdc_sec_size) / DEV_BSIZE; 5717 5718 for (i = 0; i < V_NUMPAR; i++) { 5719 vpart->p_tag = lpart->p_tag; 5720 vpart->p_flag = lpart->p_flag; 5721 vpart->p_start = lmap->dkl_cylno * nblks; 5722 vpart->p_size = lmap->dkl_nblk; 5723 5724 lmap++; 5725 lpart++; 5726 vpart++; 5727 } 5728 5729 /* Initialize timestamp and label */ 5730 bcopy(un->un_label.dkl_vtoc.v_timestamp, 5731 vtoc->timestamp, sizeof (vtoc->timestamp)); 5732 5733 bcopy(un->un_label.dkl_asciilabel, 5734 vtoc->v_asciilabel, LEN_DKL_ASCII); 5735 } 5736 5737 /* 5738 * Build a label out of a vtoc structure. 5739 */ 5740 static int 5741 fd_build_label_vtoc(struct fdunit *un, struct vtoc *vtoc) 5742 { 5743 struct dk_map32 *lmap; 5744 struct dk_map2 *lpart; 5745 struct partition *vpart; 5746 int nblks; /* no. blocks per cylinder */ 5747 int ncyl; 5748 int i; 5749 short sum, *sp; 5750 5751 /* Sanity-check the vtoc */ 5752 if ((vtoc->v_sanity != VTOC_SANE) || 5753 (vtoc->v_nparts > NDKMAP) || (vtoc->v_nparts <= 0)) { 5754 FDERRPRINT(FDEP_L1, FDEM_IOCT, 5755 (C, "fd_build_label: sanity check on vtoc failed\n")); 5756 return (EINVAL); 5757 } 5758 5759 nblks = (un->un_chars->fdc_nhead * un->un_chars->fdc_secptrack * 5760 un->un_chars->fdc_sec_size) / DEV_BSIZE; 5761 5762 vpart = vtoc->v_part; 5763 5764 /* 5765 * Check the partition information in the vtoc. The starting sectors 5766 * must lie along partition boundaries. (NDKMAP entries are checked 5767 * to ensure that the unused entries are set to 0 if vtoc->v_nparts 5768 * is less than NDKMAP) 5769 */ 5770 5771 for (i = 0; i < NDKMAP; i++) { 5772 if ((vpart->p_start % nblks) != 0) { 5773 return (EINVAL); 5774 } 5775 ncyl = vpart->p_start % nblks; 5776 ncyl += vpart->p_size % nblks; 5777 if ((vpart->p_size % nblks) != 0) 5778 ncyl++; 5779 if (ncyl > un->un_chars->fdc_ncyl) { 5780 return (EINVAL); 5781 } 5782 vpart++; 5783 } 5784 5785 /* 5786 * reinitialize the existing label 5787 */ 5788 bzero(&un->un_label, sizeof (un->un_label)); 5789 5790 /* Put appropriate vtoc structure fields into the disk label */ 5791 un->un_label.dkl_vtoc.v_bootinfo[0] = (uint32_t)vtoc->v_bootinfo[0]; 5792 un->un_label.dkl_vtoc.v_bootinfo[1] = (uint32_t)vtoc->v_bootinfo[1]; 5793 un->un_label.dkl_vtoc.v_bootinfo[2] = (uint32_t)vtoc->v_bootinfo[2]; 5794 5795 un->un_label.dkl_vtoc.v_sanity = vtoc->v_sanity; 5796 un->un_label.dkl_vtoc.v_version = vtoc->v_version; 5797 5798 bcopy(vtoc->v_volume, un->un_label.dkl_vtoc.v_volume, LEN_DKL_VVOL); 5799 5800 un->un_label.dkl_vtoc.v_nparts = vtoc->v_nparts; 5801 5802 bcopy(vtoc->v_reserved, un->un_label.dkl_vtoc.v_reserved, 5803 sizeof (un->un_label.dkl_vtoc.v_reserved)); 5804 5805 /* 5806 * Initialize cylinder information in the label. 5807 * Note the conversion from starting sector number 5808 * to starting cylinder number. 5809 * Return error if division results in a remainder. 5810 */ 5811 lmap = un->un_label.dkl_map; 5812 lpart = un->un_label.dkl_vtoc.v_part; 5813 vpart = vtoc->v_part; 5814 5815 for (i = 0; i < (int)vtoc->v_nparts; i++) { 5816 lpart->p_tag = vtoc->v_part[i].p_tag; 5817 lpart->p_flag = vtoc->v_part[i].p_flag; 5818 lmap->dkl_cylno = vpart->p_start / nblks; 5819 lmap->dkl_nblk = vpart->p_size; 5820 5821 lmap++; 5822 lpart++; 5823 vpart++; 5824 } 5825 5826 /* Copy the timestamp and ascii label */ 5827 for (i = 0; i < NDKMAP; i++) { 5828 un->un_label.dkl_vtoc.v_timestamp[i] = vtoc->timestamp[i]; 5829 } 5830 5831 5832 bcopy(vtoc->v_asciilabel, un->un_label.dkl_asciilabel, LEN_DKL_ASCII); 5833 5834 FDERRPRINT(FDEP_L1, FDEM_IOCT, 5835 (C, "fd_build_label: asciilabel %s\n", 5836 un->un_label.dkl_asciilabel)); 5837 5838 /* Initialize the magic number */ 5839 un->un_label.dkl_magic = DKL_MAGIC; 5840 5841 un->un_label.dkl_pcyl = un->un_chars->fdc_ncyl; 5842 5843 /* 5844 * The fdc_secptrack filed of the fd_char structure is the number 5845 * of sectors per track where the sectors are fdc_sec_size. The 5846 * dkl_nsect field of the dk_label structure is the number of 5847 * 512 (DEVBSIZE) byte sectors per track. 5848 */ 5849 un->un_label.dkl_nsect = (un->un_chars->fdc_secptrack * 5850 un->un_chars->fdc_sec_size) / DEV_BSIZE; 5851 5852 5853 un->un_label.dkl_ncyl = un->un_label.dkl_pcyl; 5854 un->un_label.dkl_nhead = un->un_chars->fdc_nhead; 5855 un->un_label.dkl_rpm = un->un_chars->fdc_medium ? 360 : 300; 5856 un->un_label.dkl_intrlv = 1; 5857 5858 /* Create the checksum */ 5859 sum = 0; 5860 un->un_label.dkl_cksum = 0; 5861 sp = (short *)&un->un_label; 5862 i = sizeof (struct dk_label)/sizeof (short); 5863 while (i--) { 5864 sum ^= *sp++; 5865 } 5866 un->un_label.dkl_cksum = sum; 5867 5868 return (0); 5869 } 5870 5871 /* 5872 * Check for auxio register node 5873 */ 5874 5875 int 5876 fd_isauxiodip(dev_info_t *dip) 5877 { 5878 if (strcmp(ddi_get_name(dip), "auxio") == 0 || 5879 strcmp(ddi_get_name(dip), "auxiliary-io") == 0) { 5880 return (1); 5881 } 5882 return (0); 5883 } 5884 5885 /* 5886 * Search for auxio register node, then for address property 5887 */ 5888 5889 caddr_t 5890 fd_getauxiova(dev_info_t *dip) 5891 { 5892 dev_info_t *auxdip; 5893 caddr_t addr; 5894 5895 /* 5896 * Search sibling list, which happens to be safe inside attach 5897 */ 5898 auxdip = ddi_get_child(ddi_get_parent(dip)); 5899 while (auxdip) { 5900 if (fd_isauxiodip(auxdip)) 5901 break; 5902 auxdip = ddi_get_next_sibling(auxdip); 5903 } 5904 5905 if (auxdip == NULL) 5906 return (NULL); 5907 5908 addr = (caddr_t)(uintptr_t)(caddr32_t)ddi_getprop(DDI_DEV_T_ANY, 5909 auxdip, DDI_PROP_DONTPASS, "address", 0); 5910 5911 return (addr); 5912 } 5913 5914 5915 /* 5916 * set_rotational speed 5917 * 300 rpm for high and low density. 5918 * 360 rpm for medium density. 5919 * for now, we assume that 3rd density is supported only for Sun4M, 5920 * not for Clones. (else we would have to check for 82077, and do 5921 * specific things for the MEDIUM_DENSITY BIT for clones. 5922 * this code should not break CLONES. 5923 * 5924 * REMARK: there is a SOny requirement, to deselect the drive then 5925 * select it again after the medium density change, since the 5926 * leading edge of the select line latches the rotational Speed. 5927 * then after that, we have to wait 500 ms for the rotation to 5928 * stabilize. 5929 * 5930 */ 5931 static void 5932 set_rotational_speed(struct fdctlr *fdc, int unit) 5933 { 5934 int check; 5935 int is_medium; 5936 5937 ASSERT(fdc->c_un->un_unit_no == unit); 5938 5939 /* 5940 * if we do not have a Sun4m, medium density is not supported. 5941 */ 5942 if (fdc->c_fdtype & FDCTYPE_MACHIO) 5943 return; 5944 5945 /* 5946 * if FDUNIT_SET_SPEED is set, set the speed. 5947 * else, 5948 * if there is a change, do it, if not leave it alone. 5949 * there is a change if un->un_chars->fdc_medium does not match 5950 * un->un_flags & FDUNIT_MEDIUM 5951 * un->un_flags & FDUNIT_MEDIUM specifies the last setting. 5952 * un->un_chars->fdc_medium specifies next setting. 5953 * if there is a change, wait 500ms according to Sony spec. 5954 */ 5955 5956 is_medium = fdc->c_un->un_chars->fdc_medium; 5957 5958 if (fdc->c_un->un_flags & FDUNIT_SET_SPEED) { 5959 check = 1; 5960 } else { 5961 check = is_medium ^ 5962 ((fdc->c_un->un_flags & FDUNIT_MEDIUM) ? 1 : 0); 5963 5964 /* Set the un_flags if necessary */ 5965 5966 if (check) 5967 fdc->c_un->un_flags ^= FDUNIT_MEDIUM; 5968 } 5969 5970 fdc->c_un->un_flags &= ~FDUNIT_SET_SPEED; 5971 5972 5973 if (check) { 5974 5975 fdselect(fdc, unit, 0); 5976 drv_usecwait(5); 5977 5978 if ((fdc->c_fdtype & FDCTYPE_AUXIOMASK) == FDCTYPE_SLAVIO) { 5979 Set_dor(fdc, MEDIUM_DENSITY, is_medium); 5980 } 5981 5982 if ((fdc->c_fdtype & FDCTYPE_AUXIOMASK) == FDCTYPE_CHEERIO) { 5983 if (is_medium) { 5984 Set_auxio(fdc, AUX_MEDIUM_DENSITY); 5985 } else { 5986 Set_auxio(fdc, AUX_HIGH_DENSITY); 5987 } 5988 5989 } 5990 5991 if (is_medium) { 5992 drv_usecwait(5); 5993 } 5994 5995 fdselect(fdc, unit, 1); /* Sony requirement */ 5996 FDERRPRINT(FDEP_L1, FDEM_EXEC, (C, "rotation:medium\n")); 5997 drv_usecwait(500000); 5998 } 5999 } 6000 6001 static void 6002 fd_media_watch(void *arg) 6003 { 6004 dev_t dev; 6005 struct fdunit *un; 6006 struct fdctlr *fdc; 6007 int unit; 6008 6009 dev = (dev_t)arg; 6010 fdc = fd_getctlr(dev); 6011 unit = fdc->c_un->un_unit_no; 6012 un = fdc->c_un; 6013 6014 mutex_enter(&fdc->c_lolock); 6015 6016 if (un->un_media_timeout_id == 0) { 6017 /* 6018 * Untimeout is about to be called. 6019 * Don't call fd_get_media_state again 6020 */ 6021 mutex_exit(&fdc->c_lolock); 6022 return; 6023 } 6024 6025 6026 un->un_media_state = fd_get_media_state(fdc, unit); 6027 cv_broadcast(&fdc->c_statecv); 6028 6029 mutex_exit(&fdc->c_lolock); 6030 6031 if (un->un_media_timeout) { 6032 un->un_media_timeout_id = timeout(fd_media_watch, 6033 (void *)(ulong_t)dev, un->un_media_timeout); 6034 } 6035 } 6036 6037 enum dkio_state 6038 fd_get_media_state(struct fdctlr *fdc, int unit) 6039 { 6040 enum dkio_state state; 6041 6042 ASSERT(fdc->c_un->un_unit_no == unit); 6043 6044 if (fdsense_chng(fdc, unit)) { 6045 /* check disk only if DSKCHG "high" */ 6046 if (fdcheckdisk(fdc, unit)) { 6047 state = DKIO_EJECTED; 6048 } else { 6049 state = DKIO_INSERTED; 6050 } 6051 } else { 6052 state = DKIO_INSERTED; 6053 } 6054 return (state); 6055 } 6056 6057 static int 6058 fd_check_media(dev_t dev, enum dkio_state state) 6059 { 6060 struct fdunit *un; 6061 struct fdctlr *fdc; 6062 int unit; 6063 6064 FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fd_check_media: start\n")); 6065 6066 fdc = fd_getctlr(dev); 6067 unit = fdc->c_un->un_unit_no; 6068 un = fdc->c_un; 6069 6070 mutex_enter(&fdc->c_lolock); 6071 6072 CHECK_AND_WAIT_FD_STATE_SUSPENDED(fdc); 6073 6074 if (fdc->c_un->un_state == FD_STATE_STOPPED) { 6075 mutex_exit(&fdc->c_lolock); 6076 if ((pm_raise_power(fdc->c_dip, 0, PM_LEVEL_ON)) 6077 != DDI_SUCCESS) { 6078 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "Power change \ 6079 failed. \n")); 6080 6081 (void) pm_idle_component(fdc->c_dip, 0); 6082 return (EIO); 6083 } 6084 6085 mutex_enter(&fdc->c_lolock); 6086 } 6087 6088 un->un_media_state = fd_get_media_state(fdc, unit); 6089 6090 /* turn on timeout */ 6091 un->un_media_timeout = drv_usectohz(fd_check_media_time); 6092 un->un_media_timeout_id = timeout(fd_media_watch, 6093 (void *)(ulong_t)dev, un->un_media_timeout); 6094 6095 while (un->un_media_state == state) { 6096 if (cv_wait_sig(&fdc->c_statecv, &fdc->c_lolock) == 0) { 6097 un->un_media_timeout = 0; 6098 mutex_exit(&fdc->c_lolock); 6099 return (EINTR); 6100 } 6101 } 6102 6103 if (un->un_media_timeout_id) { 6104 timeout_id_t timeid = un->un_media_timeout_id; 6105 un->un_media_timeout_id = 0; 6106 6107 mutex_exit(&fdc->c_lolock); 6108 (void) untimeout(timeid); 6109 mutex_enter(&fdc->c_lolock); 6110 } 6111 6112 if (un->un_media_state == DKIO_INSERTED) { 6113 if (fdgetlabel(fdc, unit)) { 6114 mutex_exit(&fdc->c_lolock); 6115 return (EIO); 6116 } 6117 } 6118 mutex_exit(&fdc->c_lolock); 6119 6120 FDERRPRINT(FDEP_L1, FDEM_RW, (C, "fd_check_media: end\n")); 6121 return (0); 6122 } 6123 6124 /* 6125 * fd_get_media_info : 6126 * Collects medium information for 6127 * DKIOCGMEDIAINFO ioctl. 6128 */ 6129 6130 static int 6131 fd_get_media_info(struct fdunit *un, caddr_t buf, int flag) 6132 { 6133 struct dk_minfo media_info; 6134 int err = 0; 6135 6136 media_info.dki_media_type = DK_FLOPPY; 6137 media_info.dki_lbsize = un->un_chars->fdc_sec_size; 6138 media_info.dki_capacity = un->un_chars->fdc_ncyl * 6139 un->un_chars->fdc_secptrack * un->un_chars->fdc_nhead; 6140 6141 if (ddi_copyout((caddr_t)&media_info, buf, 6142 sizeof (struct dk_minfo), flag)) 6143 err = EFAULT; 6144 return (err); 6145 } 6146 6147 /* 6148 * fd_power : 6149 * Power entry point of fd driver. 6150 */ 6151 6152 static int 6153 fd_power(dev_info_t *dip, int component, int level) 6154 { 6155 6156 struct fdctlr *fdc; 6157 int instance; 6158 int rval; 6159 6160 if ((level < PM_LEVEL_OFF) || (level > PM_LEVEL_ON) || 6161 (component != 0)) { 6162 return (DDI_FAILURE); 6163 } 6164 6165 instance = ddi_get_instance(dip); 6166 fdc = fd_getctlr(instance << FDINSTSHIFT); 6167 if (fdc->c_un == NULL) 6168 return (DDI_FAILURE); 6169 6170 if (level == PM_LEVEL_OFF) { 6171 rval = fd_pm_lower_power(fdc); 6172 } 6173 if (level == PM_LEVEL_ON) { 6174 rval = fd_pm_raise_power(fdc); 6175 } 6176 return (rval); 6177 } 6178 6179 /* 6180 * fd_pm_lower_power : 6181 * This function is called only during pm suspend. At this point, 6182 * the power management framework thinks the device is idle for 6183 * long enough to go to a low power mode. If the device is busy, 6184 * then this function returns DDI_FAILURE. 6185 */ 6186 6187 static int 6188 fd_pm_lower_power(struct fdctlr *fdc) 6189 { 6190 6191 mutex_enter(&fdc->c_lolock); 6192 6193 if ((fdc->c_un->un_state == FD_STATE_SUSPENDED) || 6194 (fdc->c_un->un_state == FD_STATE_STOPPED)) { 6195 mutex_exit(&fdc->c_lolock); 6196 return (DDI_SUCCESS); 6197 } 6198 6199 6200 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "fd_pm_lower_power called\n")); 6201 6202 /* if the device is busy then we fail the lower power request */ 6203 if (fdc->c_flags & FDCFLG_BUSY) { 6204 FDERRPRINT(FDEP_L2, FDEM_PWR, (C, "fd_pm_lower_power : \ 6205 controller is busy.\n")); 6206 mutex_exit(&fdc->c_lolock); 6207 return (DDI_FAILURE); 6208 } 6209 6210 fdc->c_un->un_state = FD_STATE_STOPPED; 6211 6212 mutex_exit(&fdc->c_lolock); 6213 return (DDI_SUCCESS); 6214 } 6215 6216 /* 6217 * fd_pm_raise_power : 6218 * This function performs the necessary steps for resuming a 6219 * device, either from pm suspend or CPR. Here the controller 6220 * is reset, initialized and the state is set to FD_STATE_NORMAL. 6221 */ 6222 6223 static int 6224 fd_pm_raise_power(struct fdctlr *fdc) 6225 { 6226 6227 struct fdunit *un = fdc->c_un; 6228 int unit; 6229 6230 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "fd_pm_raise_power called\n")); 6231 mutex_enter(&fdc->c_lolock); 6232 fdgetcsb(fdc); 6233 6234 /* Reset the dma engine */ 6235 if (fdc->c_fdtype & FDCTYPE_DMA) { 6236 mutex_enter(&fdc->c_hilock); 6237 reset_dma_controller(fdc); 6238 set_dma_control_register(fdc, DCSR_INIT_BITS); 6239 mutex_exit(&fdc->c_hilock); 6240 } 6241 6242 /* 6243 * Force a rotational speed set in the next 6244 * call to set_rotational_speed(). 6245 */ 6246 6247 fdc->c_un->un_flags |= FDUNIT_SET_SPEED; 6248 6249 /* Reset and configure the controller */ 6250 (void) fdreset(fdc); 6251 6252 unit = fdc->c_un->un_unit_no; 6253 6254 /* Recalibrate the drive */ 6255 if (fdrecalseek(fdc, unit, -1, 0) != 0) { 6256 FDERRPRINT(FDEP_L1, FDEM_PWR, (C, "raise_power : recalibrate \ 6257 failed\n")); 6258 fdretcsb(fdc); 6259 mutex_exit(&fdc->c_lolock); 6260 return (DDI_FAILURE); 6261 } 6262 6263 /* Select the drive through the AUXIO registers */ 6264 fdselect(fdc, unit, 0); 6265 un->un_state = FD_STATE_NORMAL; 6266 fdretcsb(fdc); 6267 mutex_exit(&fdc->c_lolock); 6268 return (DDI_SUCCESS); 6269 } 6270 6271 /* 6272 * create_pm_components : 6273 * creates the power management components for auto pm framework. 6274 */ 6275 6276 static void 6277 create_pm_components(dev_info_t *dip) 6278 { 6279 char *un_pm_comp[] = { "NAME=spindle-motor", "0=off", "1=on"}; 6280 6281 if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip, 6282 "pm-components", un_pm_comp, 3) == DDI_PROP_SUCCESS) { 6283 6284 (void) pm_raise_power(dip, 0, PM_LEVEL_ON); 6285 } 6286 } 6287 6288 /* 6289 * set_data_count_register(struct fdctlr *fdc, uint32_t count) 6290 * Set the data count in appropriate dma register. 6291 */ 6292 6293 static void 6294 set_data_count_register(struct fdctlr *fdc, uint32_t count) 6295 { 6296 if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 6297 struct cheerio_dma_reg *dma_reg; 6298 dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs; 6299 ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dbcr, count); 6300 } else if (fdc->c_fdtype & FDCTYPE_SB) { 6301 struct sb_dma_reg *dma_reg; 6302 count = count - 1; /* 8237 needs it */ 6303 dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs; 6304 switch (fdc->sb_dma_channel) { 6305 case 0 : 6306 ddi_put16(fdc->c_handlep_dma, 6307 (ushort_t *)&dma_reg->sb_dma_regs[DMA_0WCNT], 6308 count & 0xFFFF); 6309 break; 6310 case 1 : 6311 ddi_put16(fdc->c_handlep_dma, 6312 (ushort_t *)&dma_reg->sb_dma_regs[DMA_1WCNT], 6313 count & 0xFFFF); 6314 break; 6315 case 2 : 6316 ddi_put16(fdc->c_handlep_dma, 6317 (ushort_t *)&dma_reg->sb_dma_regs[DMA_2WCNT], 6318 count & 0xFFFF); 6319 break; 6320 case 3 : 6321 ddi_put16(fdc->c_handlep_dma, 6322 (ushort_t *)&dma_reg->sb_dma_regs[DMA_3WCNT], 6323 count & 0xFFFF); 6324 break; 6325 default : 6326 FDERRPRINT(FDEP_L3, FDEM_SDMA, 6327 (C, "set_data_count: wrong channel %x\n", 6328 fdc->sb_dma_channel)); 6329 break; 6330 } 6331 } 6332 } 6333 6334 /* 6335 * get_data_count_register(struct fdctlr *fdc) 6336 * Read the data count from appropriate dma register. 6337 */ 6338 6339 static uint32_t 6340 get_data_count_register(struct fdctlr *fdc) 6341 { 6342 uint32_t retval = 0; 6343 if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 6344 struct cheerio_dma_reg *dma_reg; 6345 dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs; 6346 retval = ddi_get32(fdc->c_handlep_dma, &dma_reg->fdc_dbcr); 6347 } else if (fdc->c_fdtype & FDCTYPE_SB) { 6348 struct sb_dma_reg *dma_reg; 6349 dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs; 6350 switch (fdc->sb_dma_channel) { 6351 case 0 : 6352 retval = ddi_get16(fdc->c_handlep_dma, 6353 (ushort_t *)&dma_reg->sb_dma_regs[DMA_0WCNT]); 6354 break; 6355 case 1 : 6356 retval = ddi_get16(fdc->c_handlep_dma, 6357 (ushort_t *)&dma_reg->sb_dma_regs[DMA_1WCNT]); 6358 break; 6359 case 2 : 6360 retval = ddi_get16(fdc->c_handlep_dma, 6361 (ushort_t *)&dma_reg->sb_dma_regs[DMA_2WCNT]); 6362 break; 6363 case 3 : 6364 retval = ddi_get16(fdc->c_handlep_dma, 6365 (ushort_t *)&dma_reg->sb_dma_regs[DMA_3WCNT]); 6366 break; 6367 default : 6368 FDERRPRINT(FDEP_L3, FDEM_SDMA, 6369 (C, "get_data_count: wrong channel %x\n", 6370 fdc->sb_dma_channel)); 6371 break; 6372 } 6373 retval = (uint32_t)((uint16_t)(retval +1)); 6374 } 6375 6376 return (retval); 6377 6378 } 6379 6380 /* 6381 * reset_dma_controller(struct fdctlr *fdc) 6382 * Reset and initialize the dma controller. 6383 */ 6384 6385 static void 6386 reset_dma_controller(struct fdctlr *fdc) 6387 { 6388 if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 6389 struct cheerio_dma_reg *dma_reg; 6390 dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs; 6391 ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr, DCSR_RESET); 6392 while (get_dma_control_register(fdc) & DCSR_CYC_PEND) 6393 ; 6394 ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr, 0); 6395 } else if (fdc->c_fdtype & FDCTYPE_SB) { 6396 struct sb_dma_reg *dma_reg; 6397 dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs; 6398 ddi_put8(fdc->c_handlep_dma, &dma_reg->sb_dma_regs[DMAC1_MASK], 6399 (fdc->sb_dma_channel & 0x3)); 6400 6401 } 6402 } 6403 6404 /* 6405 * Get the DMA control register for CHEERIO. 6406 * For SouthBridge 8237 DMA controller, this register is not valid. 6407 * So, just return 0. 6408 */ 6409 static uint32_t 6410 get_dma_control_register(struct fdctlr *fdc) 6411 { 6412 uint32_t retval = 0; 6413 if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 6414 struct cheerio_dma_reg *dma_reg; 6415 dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs; 6416 retval = ddi_get32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr); 6417 } 6418 6419 return (retval); 6420 } 6421 6422 6423 /* 6424 * set_data_address_register(struct fdctlr *fdc) 6425 * Set the data address in appropriate dma register. 6426 */ 6427 static void 6428 set_data_address_register(struct fdctlr *fdc, uint32_t address) 6429 { 6430 if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 6431 struct cheerio_dma_reg *dma_reg; 6432 dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs; 6433 ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dacr, address); 6434 } else if (fdc->c_fdtype & FDCTYPE_SB) { 6435 struct sb_dma_reg *dma_reg; 6436 dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs; 6437 switch (fdc->sb_dma_channel) { 6438 case 0 : 6439 ddi_put8(fdc->c_handlep_dma, 6440 &dma_reg->sb_dma_regs[DMA_0PAGE], 6441 (address & 0xFF0000) >>16); 6442 ddi_put8(fdc->c_handlep_dma, 6443 &dma_reg->sb_dma_regs[DMA_0HPG], 6444 (address & 0xFF000000) >>24); 6445 ddi_put16(fdc->c_handlep_dma, 6446 (ushort_t *)&dma_reg->sb_dma_regs[DMA_0ADR], 6447 address & 0xFFFF); 6448 break; 6449 case 1 : 6450 ddi_put8(fdc->c_handlep_dma, 6451 &dma_reg->sb_dma_regs[DMA_1PAGE], 6452 (address & 0xFF0000) >>16); 6453 ddi_put8(fdc->c_handlep_dma, 6454 &dma_reg->sb_dma_regs[DMA_1HPG], 6455 (address & 0xFF000000) >>24); 6456 ddi_put16(fdc->c_handlep_dma, 6457 (ushort_t *)&dma_reg->sb_dma_regs[DMA_1ADR], 6458 address & 0xFFFF); 6459 break; 6460 case 2 : 6461 ddi_put8(fdc->c_handlep_dma, 6462 &dma_reg->sb_dma_regs[DMA_2PAGE], 6463 (address & 0xFF0000) >>16); 6464 ddi_put8(fdc->c_handlep_dma, 6465 &dma_reg->sb_dma_regs[DMA_2HPG], 6466 (address & 0xFF000000) >>24); 6467 ddi_put16(fdc->c_handlep_dma, 6468 (ushort_t *)&dma_reg->sb_dma_regs[DMA_2ADR], 6469 address & 0xFFFF); 6470 break; 6471 case 3 : 6472 ddi_put8(fdc->c_handlep_dma, 6473 &dma_reg->sb_dma_regs[DMA_3PAGE], 6474 (address & 0xFF0000) >>16); 6475 ddi_put8(fdc->c_handlep_dma, 6476 &dma_reg->sb_dma_regs[DMA_3HPG], 6477 (address & 0xFF000000) >>24); 6478 ddi_put16(fdc->c_handlep_dma, 6479 (ushort_t *)&dma_reg->sb_dma_regs[DMA_3ADR], 6480 address & 0xFFFF); 6481 break; 6482 default : 6483 FDERRPRINT(FDEP_L3, FDEM_SDMA, 6484 (C, "set_data_address: wrong channel %x\n", 6485 fdc->sb_dma_channel)); 6486 break; 6487 } 6488 } 6489 6490 } 6491 6492 6493 /* 6494 * set_dma_mode(struct fdctlr *fdc, int val) 6495 * Set the appropriate dma direction and registers. 6496 */ 6497 static void 6498 set_dma_mode(struct fdctlr *fdc, int val) 6499 { 6500 if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 6501 struct cheerio_dma_reg *dma_reg; 6502 dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs; 6503 if (val == CSB_READ) 6504 ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr, 6505 DCSR_INIT_BITS|DCSR_WRITE); 6506 else 6507 ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr, 6508 DCSR_INIT_BITS); 6509 6510 } else if (fdc->c_fdtype & FDCTYPE_SB) { 6511 uint8_t mode_reg_val, chn_mask; 6512 struct sb_dma_reg *dma_reg; 6513 dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs; 6514 6515 if (val == CSB_READ) { 6516 mode_reg_val = fdc->sb_dma_channel | DMAMODE_READ 6517 | DMAMODE_SINGLE; 6518 } else { /* Read operation */ 6519 mode_reg_val = fdc->sb_dma_channel | DMAMODE_WRITE 6520 | DMAMODE_SINGLE; 6521 } 6522 ddi_put8(fdc->c_handlep_dma, &dma_reg->sb_dma_regs[DMAC1_MODE], 6523 mode_reg_val); 6524 chn_mask = 1 << (fdc->sb_dma_channel & 0x3); 6525 ddi_put8(fdc->c_handlep_dma, 6526 &dma_reg->sb_dma_regs[DMAC1_ALLMASK], ~chn_mask); 6527 fdc->sb_dma_lock = 1; 6528 } 6529 } 6530 6531 /* 6532 * This function is valid only for CHEERIO/RIO based 6533 * controllers. The control register for the dma channel 6534 * is initialized by this function. 6535 */ 6536 6537 static void 6538 set_dma_control_register(struct fdctlr *fdc, uint32_t val) 6539 { 6540 if (fdc->c_fdtype & FDCTYPE_CHEERIO) { 6541 struct cheerio_dma_reg *dma_reg; 6542 dma_reg = (struct cheerio_dma_reg *)fdc->c_dma_regs; 6543 ddi_put32(fdc->c_handlep_dma, &dma_reg->fdc_dcsr, val); 6544 } 6545 } 6546 6547 static void 6548 release_sb_dma(struct fdctlr *fdc) 6549 { 6550 struct sb_dma_reg *dma_reg; 6551 dma_reg = (struct sb_dma_reg *)fdc->c_dma_regs; 6552 /* Unmask all the channels to release the DMA controller */ 6553 ddi_put8(fdc->c_handlep_dma, 6554 &dma_reg->sb_dma_regs[DMAC1_ALLMASK], NULL); 6555 fdc->sb_dma_lock = 0; 6556 } 6557 6558 static void 6559 quiesce_fd_interrupt(struct fdctlr *fdc) 6560 { 6561 /* 6562 * The following code is put here to take care of HW problem. 6563 * The HW problem is as follows: 6564 * 6565 * After poweron the Southbridge floppy controller asserts the 6566 * interrupt in tristate. This causes continuous interrupts to 6567 * be generated. 6568 * Until the Hardware is FIXED we will have to use the following code 6569 * to set the interrupt line to proper state after poweron. 6570 */ 6571 if (fdc->c_fdtype & FDCTYPE_SB) { 6572 ddi_put8(fdc->c_handlep_cont, ((uint8_t *)fdc->c_dor), 6573 0x0); 6574 drv_usecwait(200); 6575 ddi_put8(fdc->c_handlep_cont, ((uint8_t *)fdc->c_dor), 6576 0xC); 6577 drv_usecwait(200); 6578 Set_Fifo(fdc, 0xE6); 6579 drv_usecwait(200); 6580 } 6581 } 6582