1 /* $NetBSD: fd.c,v 1.82 2000/06/04 19:15:02 cgd Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /*- 40 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. 41 * Copyright (c) 1995 Paul Kranenburg. 42 * Copyright (c) 1990 The Regents of the University of California. 43 * All rights reserved. 44 * 45 * This code is derived from software contributed to Berkeley by 46 * Don Ahn. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 1. Redistributions of source code must retain the above copyright 52 * notice, this list of conditions and the following disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 3. All advertising materials mentioning features or use of this software 57 * must display the following acknowledgement: 58 * This product includes software developed by the University of 59 * California, Berkeley and its contributors. 60 * 4. Neither the name of the University nor the names of its contributors 61 * may be used to endorse or promote products derived from this software 62 * without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 65 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 66 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 68 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 69 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 70 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 71 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 72 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 73 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 74 * SUCH DAMAGE. 75 * 76 * @(#)fd.c 7.4 (Berkeley) 5/25/91 77 */ 78 79 #include "opt_ddb.h" 80 #include "opt_md.h" 81 82 #include <sys/param.h> 83 #include <sys/systm.h> 84 #include <sys/callout.h> 85 #include <sys/kernel.h> 86 #include <sys/file.h> 87 #include <sys/ioctl.h> 88 #include <sys/device.h> 89 #include <sys/disklabel.h> 90 #include <sys/dkstat.h> 91 #include <sys/disk.h> 92 #include <sys/fdio.h> 93 #include <sys/buf.h> 94 #include <sys/malloc.h> 95 #include <sys/proc.h> 96 #include <sys/uio.h> 97 #include <sys/stat.h> 98 #include <sys/syslog.h> 99 #include <sys/queue.h> 100 #include <sys/conf.h> 101 102 #include <dev/cons.h> 103 104 #include <vm/vm.h> 105 106 #include <uvm/uvm_extern.h> 107 108 #include <machine/cpu.h> 109 #include <machine/autoconf.h> 110 #include <machine/conf.h> 111 112 #include <sparc/sparc/auxreg.h> 113 #include <sparc/dev/fdreg.h> 114 #include <sparc/dev/fdvar.h> 115 116 #define FDUNIT(dev) (minor(dev) / 8) 117 #define FDTYPE(dev) (minor(dev) % 8) 118 119 /* XXX misuse a flag to identify format operation */ 120 #define B_FORMAT B_XXX 121 122 #define FD_DEBUG 123 #ifdef FD_DEBUG 124 int fdc_debug = 0; 125 #endif 126 127 enum fdc_state { 128 DEVIDLE = 0, 129 MOTORWAIT, /* 1 */ 130 DOSEEK, /* 2 */ 131 SEEKWAIT, /* 3 */ 132 SEEKTIMEDOUT, /* 4 */ 133 SEEKCOMPLETE, /* 5 */ 134 DOIO, /* 6 */ 135 IOCOMPLETE, /* 7 */ 136 IOTIMEDOUT, /* 8 */ 137 IOCLEANUPWAIT, /* 9 */ 138 IOCLEANUPTIMEDOUT,/*10 */ 139 DORESET, /* 11 */ 140 RESETCOMPLETE, /* 12 */ 141 RESETTIMEDOUT, /* 13 */ 142 DORECAL, /* 14 */ 143 RECALWAIT, /* 15 */ 144 RECALTIMEDOUT, /* 16 */ 145 RECALCOMPLETE, /* 17 */ 146 }; 147 148 /* software state, per controller */ 149 struct fdc_softc { 150 struct device sc_dev; /* boilerplate */ 151 bus_space_tag_t sc_bustag; 152 153 struct callout sc_timo_ch; /* timeout callout */ 154 struct callout sc_intr_ch; /* pseudo-intr callout */ 155 156 struct fd_softc *sc_fd[4]; /* pointers to children */ 157 TAILQ_HEAD(drivehead, fd_softc) sc_drives; 158 enum fdc_state sc_state; 159 int sc_flags; 160 #define FDC_82077 0x01 161 #define FDC_NEEDHEADSETTLE 0x02 162 #define FDC_EIS 0x04 163 #define FDC_NEEDMOTORWAIT 0x08 164 int sc_errors; /* number of retries so far */ 165 int sc_overruns; /* number of DMA overruns */ 166 int sc_cfg; /* current configuration */ 167 struct fdcio sc_io; 168 #define sc_handle sc_io.fdcio_handle 169 #define sc_reg_msr sc_io.fdcio_reg_msr 170 #define sc_reg_fifo sc_io.fdcio_reg_fifo 171 #define sc_reg_dor sc_io.fdcio_reg_dor 172 #define sc_reg_drs sc_io.fdcio_reg_msr 173 #define sc_itask sc_io.fdcio_itask 174 #define sc_istatus sc_io.fdcio_istatus 175 #define sc_data sc_io.fdcio_data 176 #define sc_tc sc_io.fdcio_tc 177 #define sc_nstat sc_io.fdcio_nstat 178 #define sc_status sc_io.fdcio_status 179 #define sc_intrcnt sc_io.fdcio_intrcnt 180 }; 181 182 #undef FDC_C_HANDLER 183 #ifndef FDC_C_HANDLER 184 extern struct fdcio *fdciop; 185 #endif 186 187 /* controller driver configuration */ 188 int fdcmatch_mainbus __P((struct device *, struct cfdata *, void *)); 189 int fdcmatch_obio __P((struct device *, struct cfdata *, void *)); 190 void fdcattach_mainbus __P((struct device *, struct device *, void *)); 191 void fdcattach_obio __P((struct device *, struct device *, void *)); 192 193 int fdcattach __P((struct fdc_softc *, int)); 194 195 struct cfattach fdc_mainbus_ca = { 196 sizeof(struct fdc_softc), fdcmatch_mainbus, fdcattach_mainbus 197 }; 198 struct cfattach fdc_obio_ca = { 199 sizeof(struct fdc_softc), fdcmatch_obio, fdcattach_obio 200 }; 201 202 __inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t)); 203 204 /* 205 * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how 206 * we tell them apart. 207 */ 208 struct fd_type { 209 int sectrac; /* sectors per track */ 210 int heads; /* number of heads */ 211 int seccyl; /* sectors per cylinder */ 212 int secsize; /* size code for sectors */ 213 int datalen; /* data len when secsize = 0 */ 214 int steprate; /* step rate and head unload time */ 215 int gap1; /* gap len between sectors */ 216 int gap2; /* formatting gap */ 217 int cylinders; /* total num of cylinders */ 218 int size; /* size of disk in sectors */ 219 int step; /* steps per cylinder */ 220 int rate; /* transfer speed code */ 221 int fillbyte; /* format fill byte */ 222 int interleave; /* interleave factor (formatting) */ 223 char *name; 224 }; 225 226 /* The order of entries in the following table is important -- BEWARE! */ 227 struct fd_type fd_types[] = { 228 { 18,2,36,2,0xff,0xcf,0x1b,0x54,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB" }, /* 1.44MB diskette */ 229 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB" }, /* 3.5" 720kB diskette */ 230 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,0xf6,1, "360KB/x" }, /* 360kB in 720kB drive */ 231 { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS,0xf6,1, "1.2MB/NEC" } /* 1.2 MB japanese format */ 232 }; 233 234 /* software state, per disk (with up to 4 disks per ctlr) */ 235 struct fd_softc { 236 struct device sc_dv; /* generic device info */ 237 struct disk sc_dk; /* generic disk info */ 238 239 struct fd_type *sc_deftype; /* default type descriptor */ 240 struct fd_type *sc_type; /* current type descriptor */ 241 242 struct callout sc_motoron_ch; 243 struct callout sc_motoroff_ch; 244 245 daddr_t sc_blkno; /* starting block number */ 246 int sc_bcount; /* byte count left */ 247 int sc_skip; /* bytes already transferred */ 248 int sc_nblks; /* number of blocks currently tranferring */ 249 int sc_nbytes; /* number of bytes currently tranferring */ 250 251 int sc_drive; /* physical unit number */ 252 int sc_flags; 253 #define FD_OPEN 0x01 /* it's open */ 254 #define FD_MOTOR 0x02 /* motor should be on */ 255 #define FD_MOTOR_WAIT 0x04 /* motor coming up */ 256 int sc_cylin; /* where we think the head is */ 257 int sc_opts; /* user-set options */ 258 259 void *sc_sdhook; /* shutdownhook cookie */ 260 261 TAILQ_ENTRY(fd_softc) sc_drivechain; 262 int sc_ops; /* I/O ops since last switch */ 263 struct buf_queue sc_q; /* pending I/O requests */ 264 int sc_active; /* number of active I/O requests */ 265 }; 266 267 /* floppy driver configuration */ 268 int fdmatch __P((struct device *, struct cfdata *, void *)); 269 void fdattach __P((struct device *, struct device *, void *)); 270 271 struct cfattach fd_ca = { 272 sizeof(struct fd_softc), fdmatch, fdattach 273 }; 274 275 extern struct cfdriver fd_cd; 276 277 void fdgetdisklabel __P((dev_t)); 278 int fd_get_parms __P((struct fd_softc *)); 279 void fdstrategy __P((struct buf *)); 280 void fdstart __P((struct fd_softc *)); 281 int fdprint __P((void *, const char *)); 282 283 struct dkdriver fddkdriver = { fdstrategy }; 284 285 struct fd_type *fd_nvtotype __P((char *, int, int)); 286 void fd_set_motor __P((struct fdc_softc *fdc)); 287 void fd_motor_off __P((void *arg)); 288 void fd_motor_on __P((void *arg)); 289 int fdcresult __P((struct fdc_softc *fdc)); 290 int fdc_wrfifo __P((struct fdc_softc *fdc, u_char x)); 291 void fdcstart __P((struct fdc_softc *fdc)); 292 void fdcstatus __P((struct fdc_softc *fdc, char *s)); 293 void fdc_reset __P((struct fdc_softc *fdc)); 294 void fdctimeout __P((void *arg)); 295 void fdcpseudointr __P((void *arg)); 296 #ifdef FDC_C_HANDLER 297 int fdc_c_hwintr __P((void *)); 298 #else 299 void fdchwintr __P((void)); 300 #endif 301 int fdcswintr __P((void *)); 302 int fdcstate __P((struct fdc_softc *)); 303 void fdcretry __P((struct fdc_softc *fdc)); 304 void fdfinish __P((struct fd_softc *fd, struct buf *bp)); 305 int fdformat __P((dev_t, struct ne7_fd_formb *, struct proc *)); 306 void fd_do_eject __P((struct fd_softc *)); 307 void fd_mountroot_hook __P((struct device *)); 308 static int fdconf __P((struct fdc_softc *)); 309 static void establish_chip_type __P(( 310 struct fdc_softc *, 311 bus_space_tag_t, 312 bus_type_t, 313 bus_addr_t, 314 bus_size_t, 315 bus_space_handle_t)); 316 317 318 #if PIL_FDSOFT == 4 319 #define IE_FDSOFT IE_L4 320 #else 321 #error 4 322 #endif 323 324 #ifdef FDC_C_HANDLER 325 #if defined(SUN4M) 326 #define FD_SET_SWINTR do { \ 327 if (CPU_ISSUN4M) \ 328 raise(0, PIL_FDSOFT); \ 329 else \ 330 ienab_bis(IE_L4); \ 331 } while(0) 332 #else 333 #define FD_SET_SWINTR ienab_bis(IE_FDSOFT) 334 #endif /* defined(SUN4M) */ 335 #endif /* FDC_C_HANDLER */ 336 337 #define OBP_FDNAME (CPU_ISSUN4M ? "SUNW,fdtwo" : "fd") 338 339 int 340 fdcmatch_mainbus(parent, match, aux) 341 struct device *parent; 342 struct cfdata *match; 343 void *aux; 344 { 345 struct mainbus_attach_args *ma = aux; 346 347 /* 348 * Floppy controller is on mainbus on sun4c. 349 */ 350 if (!CPU_ISSUN4C) 351 return (0); 352 353 /* sun4c PROMs call the controller "fd" */ 354 if (strcmp("fd", ma->ma_name) != 0) 355 return (0); 356 357 return (bus_space_probe(ma->ma_bustag, 358 ma->ma_iospace, 359 ma->ma_paddr, 360 1, /* probe size */ 361 0, /* offset */ 362 0, /* flags */ 363 NULL, NULL)); 364 } 365 366 int 367 fdcmatch_obio(parent, match, aux) 368 struct device *parent; 369 struct cfdata *match; 370 void *aux; 371 { 372 union obio_attach_args *uoba = aux; 373 struct sbus_attach_args *sa; 374 375 /* 376 * Floppy controller is on obio on sun4m. 377 */ 378 if (uoba->uoba_isobio4 != 0) 379 return (0); 380 381 sa = &uoba->uoba_sbus; 382 383 /* sun4m PROMs call the controller "SUNW,fdtwo" */ 384 if (strcmp("SUNW,fdtwo", sa->sa_name) != 0) 385 return (0); 386 387 return (bus_space_probe(sa->sa_bustag, sa->sa_slot, sa->sa_offset, 388 1, /* probe size */ 389 0, /* offset */ 390 0, /* flags */ 391 NULL, NULL)); 392 } 393 394 static void 395 establish_chip_type(fdc, tag, type, addr, size, handle) 396 struct fdc_softc *fdc; 397 bus_space_tag_t tag; 398 bus_type_t type; 399 bus_addr_t addr; 400 bus_size_t size; 401 bus_space_handle_t handle; 402 { 403 u_int8_t v; 404 405 /* 406 * This hack from Chris Torek: apparently DOR really 407 * addresses MSR/DRS on a 82072. 408 * We used to rely on the VERSION command to tell the 409 * difference (which did not work). 410 */ 411 412 /* First, check the size of the register bank */ 413 if (size < 8) 414 /* It isn't a 82077 */ 415 return; 416 417 /* Then probe the DOR register offset */ 418 if (bus_space_probe(tag, type, addr, 419 1, /* probe size */ 420 FDREG77_DOR, /* offset */ 421 0, /* flags */ 422 NULL, NULL) == 0) { 423 424 /* It isn't a 82077 */ 425 return; 426 } 427 428 v = bus_space_read_1(tag, handle, FDREG77_DOR); 429 if (v == NE7_RQM) { 430 /* 431 * Value in DOR looks like it's really MSR 432 */ 433 bus_space_write_1(tag, handle, FDREG77_DOR, FDC_250KBPS); 434 v = bus_space_read_1(tag, handle, FDREG77_DOR); 435 if (v == NE7_RQM) { 436 /* 437 * The value in the DOR didn't stick; 438 * it isn't a 82077 439 */ 440 return; 441 } 442 } 443 444 fdc->sc_flags |= FDC_82077; 445 } 446 447 /* 448 * Arguments passed between fdcattach and fdprobe. 449 */ 450 struct fdc_attach_args { 451 int fa_drive; 452 struct fd_type *fa_deftype; 453 }; 454 455 /* 456 * Print the location of a disk drive (called just before attaching the 457 * the drive). If `fdc' is not NULL, the drive was found but was not 458 * in the system config file; print the drive name as well. 459 * Return QUIET (config_find ignores this if the device was configured) to 460 * avoid printing `fdN not configured' messages. 461 */ 462 int 463 fdprint(aux, fdc) 464 void *aux; 465 const char *fdc; 466 { 467 register struct fdc_attach_args *fa = aux; 468 469 if (!fdc) 470 printf(" drive %d", fa->fa_drive); 471 return (QUIET); 472 } 473 474 /* 475 * Configure several parameters and features on the FDC. 476 * Return 0 on success. 477 */ 478 static int 479 fdconf(fdc) 480 struct fdc_softc *fdc; 481 { 482 int vroom; 483 484 if (fdc_wrfifo(fdc, NE7CMD_DUMPREG) || fdcresult(fdc) != 10) 485 return (-1); 486 487 /* 488 * dumpreg[7] seems to be a motor-off timeout; set it to whatever 489 * the PROM thinks is appropriate. 490 */ 491 if ((vroom = fdc->sc_status[7]) == 0) 492 vroom = 0x64; 493 494 /* Configure controller to use FIFO and Implied Seek */ 495 if (fdc_wrfifo(fdc, NE7CMD_CFG) != 0) 496 return (-1); 497 if (fdc_wrfifo(fdc, vroom) != 0) 498 return (-1); 499 if (fdc_wrfifo(fdc, fdc->sc_cfg) != 0) 500 return (-1); 501 if (fdc_wrfifo(fdc, 0) != 0) /* PRETRK */ 502 return (-1); 503 /* No result phase for the NE7CMD_CFG command */ 504 505 if ((fdc->sc_flags & FDC_82077) != 0) { 506 /* Lock configuration across soft resets. */ 507 if (fdc_wrfifo(fdc, NE7CMD_LOCK | CFG_LOCK) != 0 || 508 fdcresult(fdc) != 1) { 509 #ifdef DEBUG 510 printf("fdconf: CFGLOCK failed"); 511 #endif 512 return (-1); 513 } 514 } 515 516 return (0); 517 #if 0 518 if (fdc_wrfifo(fdc, NE7CMD_VERSION) == 0 && 519 fdcresult(fdc) == 1 && fdc->sc_status[0] == 0x90) { 520 if (fdc_debug) 521 printf("[version cmd]"); 522 } 523 #endif 524 } 525 526 void 527 fdcattach_mainbus(parent, self, aux) 528 struct device *parent, *self; 529 void *aux; 530 { 531 struct fdc_softc *fdc = (void *)self; 532 struct mainbus_attach_args *ma = aux; 533 534 fdc->sc_bustag = ma->ma_bustag; 535 536 if (bus_space_map2( 537 ma->ma_bustag, 538 ma->ma_iospace, 539 ma->ma_paddr, 540 ma->ma_size, 541 BUS_SPACE_MAP_LINEAR, 542 0, 543 &fdc->sc_handle) != 0) { 544 printf("%s: cannot map registers\n", self->dv_xname); 545 return; 546 } 547 548 establish_chip_type(fdc, 549 ma->ma_bustag, 550 ma->ma_iospace, 551 ma->ma_paddr, 552 ma->ma_size, 553 fdc->sc_handle); 554 555 if (fdcattach(fdc, ma->ma_pri) != 0) 556 bus_space_unmap(ma->ma_bustag, fdc->sc_handle, ma->ma_size); 557 } 558 559 void 560 fdcattach_obio(parent, self, aux) 561 struct device *parent, *self; 562 void *aux; 563 { 564 struct fdc_softc *fdc = (void *)self; 565 union obio_attach_args *uoba = aux; 566 struct sbus_attach_args *sa = &uoba->uoba_sbus; 567 568 if (sa->sa_nintr == 0) { 569 printf(": no interrupt line configured\n"); 570 return; 571 } 572 573 fdc->sc_bustag = sa->sa_bustag; 574 575 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 576 sa->sa_offset, 577 sa->sa_size, 578 BUS_SPACE_MAP_LINEAR, 579 0, 580 &fdc->sc_handle) != 0) { 581 printf("%s: cannot map control registers\n", 582 self->dv_xname); 583 return; 584 } 585 586 establish_chip_type(fdc, 587 sa->sa_bustag, 588 sa->sa_slot, 589 sa->sa_offset, 590 sa->sa_size, 591 fdc->sc_handle); 592 593 if (strcmp(getpropstring(sa->sa_node, "status"), "disabled") == 0) { 594 printf(": no drives attached\n"); 595 return; 596 } 597 598 if (fdcattach(fdc, sa->sa_pri) != 0) 599 bus_space_unmap(sa->sa_bustag, fdc->sc_handle, sa->sa_size); 600 } 601 602 int 603 fdcattach(fdc, pri) 604 struct fdc_softc *fdc; 605 int pri; 606 { 607 struct fdc_attach_args fa; 608 int drive_attached; 609 char code; 610 611 callout_init(&fdc->sc_timo_ch); 612 callout_init(&fdc->sc_intr_ch); 613 614 fdc->sc_state = DEVIDLE; 615 fdc->sc_itask = FDC_ITASK_NONE; 616 fdc->sc_istatus = FDC_ISTATUS_NONE; 617 fdc->sc_flags |= FDC_EIS; 618 TAILQ_INIT(&fdc->sc_drives); 619 620 if ((fdc->sc_flags & FDC_82077) != 0) { 621 fdc->sc_reg_msr = FDREG77_MSR; 622 fdc->sc_reg_fifo = FDREG77_FIFO; 623 fdc->sc_reg_dor = FDREG77_DOR; 624 code = '7'; 625 fdc->sc_flags |= FDC_NEEDMOTORWAIT; 626 } else { 627 fdc->sc_reg_msr = FDREG72_MSR; 628 fdc->sc_reg_fifo = FDREG72_FIFO; 629 fdc->sc_reg_dor = 0; 630 code = '2'; 631 } 632 633 printf(" softpri %d: chip 8207%c\n", PIL_FDSOFT, code); 634 635 /* 636 * Configure controller; enable FIFO, Implied seek, no POLL mode?. 637 * Note: CFG_EFIFO is active-low, initial threshold value: 8 638 */ 639 fdc->sc_cfg = CFG_EIS|/*CFG_EFIFO|*/CFG_POLL|(8 & CFG_THRHLD_MASK); 640 if (fdconf(fdc) != 0) { 641 printf("%s: no drives attached\n", fdc->sc_dev.dv_xname); 642 return (-1); 643 } 644 645 #ifdef FDC_C_HANDLER 646 (void)bus_intr_establish(fdc->sc_bustag, pri, 0, 647 fdc_c_hwintr, fdc); 648 #else 649 fdciop = &fdc->sc_io; 650 (void)bus_intr_establish(fdc->sc_bustag, pri, 651 BUS_INTR_ESTABLISH_FASTTRAP, 652 (int (*) __P((void *)))fdchwintr, NULL); 653 #endif 654 (void)bus_intr_establish(fdc->sc_bustag, PIL_FDSOFT, 655 BUS_INTR_ESTABLISH_SOFTINTR, 656 fdcswintr, fdc); 657 658 evcnt_attach_dynamic(&fdc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 659 fdc->sc_dev.dv_xname, "intr"); 660 661 /* physical limit: four drives per controller. */ 662 drive_attached = 0; 663 for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) { 664 fa.fa_deftype = NULL; /* unknown */ 665 fa.fa_deftype = &fd_types[0]; /* XXX */ 666 if (config_found(&fdc->sc_dev, (void *)&fa, fdprint) != NULL) 667 drive_attached = 1; 668 } 669 670 if (drive_attached == 0) { 671 /* XXX - dis-establish interrupts here */ 672 /* return (-1); */ 673 } 674 675 return (0); 676 } 677 678 int 679 fdmatch(parent, match, aux) 680 struct device *parent; 681 struct cfdata *match; 682 void *aux; 683 { 684 struct fdc_softc *fdc = (void *)parent; 685 bus_space_tag_t t = fdc->sc_bustag; 686 bus_space_handle_t h = fdc->sc_handle; 687 struct fdc_attach_args *fa = aux; 688 int drive = fa->fa_drive; 689 int n, ok; 690 691 if (drive > 0) 692 /* XXX - for now, punt on more than one drive */ 693 return (0); 694 695 if ((fdc->sc_flags & FDC_82077) != 0) { 696 /* select drive and turn on motor */ 697 bus_space_write_1(t, h, fdc->sc_reg_dor, 698 drive | FDO_FRST | FDO_MOEN(drive)); 699 /* wait for motor to spin up */ 700 delay(250000); 701 } else { 702 auxregbisc(AUXIO4C_FDS, 0); 703 } 704 fdc->sc_nstat = 0; 705 fdc_wrfifo(fdc, NE7CMD_RECAL); 706 fdc_wrfifo(fdc, drive); 707 708 /* Wait for recalibration to complete */ 709 for (n = 0; n < 10000; n++) { 710 u_int8_t v; 711 712 delay(1000); 713 v = bus_space_read_1(t, h, fdc->sc_reg_msr); 714 if ((v & (NE7_RQM|NE7_DIO|NE7_CB)) == NE7_RQM) { 715 /* wait a bit longer till device *really* is ready */ 716 delay(100000); 717 if (fdc_wrfifo(fdc, NE7CMD_SENSEI)) 718 break; 719 if (fdcresult(fdc) == 1 && fdc->sc_status[0] == 0x80) 720 /* 721 * Got `invalid command'; we interpret it 722 * to mean that the re-calibrate hasn't in 723 * fact finished yet 724 */ 725 continue; 726 break; 727 } 728 } 729 n = fdc->sc_nstat; 730 #ifdef FD_DEBUG 731 if (fdc_debug) { 732 int i; 733 printf("fdprobe: %d stati:", n); 734 for (i = 0; i < n; i++) 735 printf(" 0x%x", fdc->sc_status[i]); 736 printf("\n"); 737 } 738 #endif 739 ok = (n == 2 && (fdc->sc_status[0] & 0xf8) == 0x20) ? 1 : 0; 740 741 /* turn off motor */ 742 if ((fdc->sc_flags & FDC_82077) != 0) { 743 /* deselect drive and turn motor off */ 744 bus_space_write_1(t, h, fdc->sc_reg_dor, FDO_FRST | FDO_DS); 745 } else { 746 auxregbisc(0, AUXIO4C_FDS); 747 } 748 749 return (ok); 750 } 751 752 /* 753 * Controller is working, and drive responded. Attach it. 754 */ 755 void 756 fdattach(parent, self, aux) 757 struct device *parent, *self; 758 void *aux; 759 { 760 struct fdc_softc *fdc = (void *)parent; 761 struct fd_softc *fd = (void *)self; 762 struct fdc_attach_args *fa = aux; 763 struct fd_type *type = fa->fa_deftype; 764 int drive = fa->fa_drive; 765 766 callout_init(&fd->sc_motoron_ch); 767 callout_init(&fd->sc_motoroff_ch); 768 769 /* XXX Allow `flags' to override device type? */ 770 771 if (type) 772 printf(": %s %d cyl, %d head, %d sec\n", type->name, 773 type->cylinders, type->heads, type->sectrac); 774 else 775 printf(": density unknown\n"); 776 777 BUFQ_INIT(&fd->sc_q); 778 fd->sc_cylin = -1; 779 fd->sc_drive = drive; 780 fd->sc_deftype = type; 781 fdc->sc_fd[drive] = fd; 782 783 fdc_wrfifo(fdc, NE7CMD_SPECIFY); 784 fdc_wrfifo(fdc, type->steprate); 785 /* XXX head load time == 6ms */ 786 fdc_wrfifo(fdc, 6 | NE7_SPECIFY_NODMA); 787 788 /* 789 * Initialize and attach the disk structure. 790 */ 791 fd->sc_dk.dk_name = fd->sc_dv.dv_xname; 792 fd->sc_dk.dk_driver = &fddkdriver; 793 disk_attach(&fd->sc_dk); 794 795 /* 796 * Establish a mountroot_hook anyway in case we booted 797 * with RB_ASKNAME and get selected as the boot device. 798 */ 799 mountroothook_establish(fd_mountroot_hook, &fd->sc_dv); 800 801 /* Make sure the drive motor gets turned off at shutdown time. */ 802 fd->sc_sdhook = shutdownhook_establish(fd_motor_off, fd); 803 } 804 805 __inline struct fd_type * 806 fd_dev_to_type(fd, dev) 807 struct fd_softc *fd; 808 dev_t dev; 809 { 810 int type = FDTYPE(dev); 811 812 if (type > (sizeof(fd_types) / sizeof(fd_types[0]))) 813 return (NULL); 814 return (type ? &fd_types[type - 1] : fd->sc_deftype); 815 } 816 817 void 818 fdstrategy(bp) 819 register struct buf *bp; /* IO operation to perform */ 820 { 821 struct fd_softc *fd; 822 int unit = FDUNIT(bp->b_dev); 823 int sz; 824 int s; 825 826 /* Valid unit, controller, and request? */ 827 if (unit >= fd_cd.cd_ndevs || 828 (fd = fd_cd.cd_devs[unit]) == 0 || 829 bp->b_blkno < 0 || 830 (((bp->b_bcount % FD_BSIZE(fd)) != 0 || 831 (bp->b_blkno * DEV_BSIZE) % FD_BSIZE(fd) != 0) && 832 (bp->b_flags & B_FORMAT) == 0)) { 833 bp->b_error = EINVAL; 834 goto bad; 835 } 836 837 /* If it's a null transfer, return immediately. */ 838 if (bp->b_bcount == 0) 839 goto done; 840 841 sz = howmany(bp->b_bcount, DEV_BSIZE); 842 843 if (bp->b_blkno + sz > (fd->sc_type->size * DEV_BSIZE) / FD_BSIZE(fd)) { 844 sz = (fd->sc_type->size * DEV_BSIZE) / FD_BSIZE(fd) 845 - bp->b_blkno; 846 if (sz == 0) { 847 /* If exactly at end of disk, return EOF. */ 848 bp->b_resid = bp->b_bcount; 849 goto done; 850 } 851 if (sz < 0) { 852 /* If past end of disk, return EINVAL. */ 853 bp->b_error = EINVAL; 854 goto bad; 855 } 856 /* Otherwise, truncate request. */ 857 bp->b_bcount = sz << DEV_BSHIFT; 858 } 859 860 bp->b_rawblkno = bp->b_blkno; 861 bp->b_cylinder = (bp->b_blkno * DEV_BSIZE) / 862 (FD_BSIZE(fd) * fd->sc_type->seccyl); 863 864 #ifdef FD_DEBUG 865 if (fdc_debug > 1) 866 printf("fdstrategy: b_blkno %d b_bcount %ld blkno %d cylin %ld\n", 867 bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylinder); 868 #endif 869 870 /* Queue transfer on drive, activate drive and controller if idle. */ 871 s = splbio(); 872 disksort_cylinder(&fd->sc_q, bp); 873 callout_stop(&fd->sc_motoroff_ch); /* a good idea */ 874 if (fd->sc_active == 0) 875 fdstart(fd); 876 #ifdef DIAGNOSTIC 877 else { 878 struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent; 879 if (fdc->sc_state == DEVIDLE) { 880 printf("fdstrategy: controller inactive\n"); 881 fdcstart(fdc); 882 } 883 } 884 #endif 885 splx(s); 886 return; 887 888 bad: 889 bp->b_flags |= B_ERROR; 890 done: 891 /* Toss transfer; we're done early. */ 892 biodone(bp); 893 } 894 895 void 896 fdstart(fd) 897 struct fd_softc *fd; 898 { 899 struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent; 900 int active = fdc->sc_drives.tqh_first != 0; 901 902 /* Link into controller queue. */ 903 fd->sc_active = 1; 904 TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); 905 906 /* If controller not already active, start it. */ 907 if (!active) 908 fdcstart(fdc); 909 } 910 911 void 912 fdfinish(fd, bp) 913 struct fd_softc *fd; 914 struct buf *bp; 915 { 916 struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent; 917 918 /* 919 * Move this drive to the end of the queue to give others a `fair' 920 * chance. We only force a switch if N operations are completed while 921 * another drive is waiting to be serviced, since there is a long motor 922 * startup delay whenever we switch. 923 */ 924 if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) { 925 fd->sc_ops = 0; 926 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); 927 if (BUFQ_NEXT(bp) != NULL) { 928 TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); 929 } else 930 fd->sc_active = 0; 931 } 932 bp->b_resid = fd->sc_bcount; 933 fd->sc_skip = 0; 934 BUFQ_REMOVE(&fd->sc_q, bp); 935 936 biodone(bp); 937 /* turn off motor 5s from now */ 938 callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd); 939 fdc->sc_state = DEVIDLE; 940 } 941 942 void 943 fdc_reset(fdc) 944 struct fdc_softc *fdc; 945 { 946 bus_space_tag_t t = fdc->sc_bustag; 947 bus_space_handle_t h = fdc->sc_handle; 948 949 if ((fdc->sc_flags & FDC_82077) != 0) { 950 bus_space_write_1(t, h, fdc->sc_reg_dor, 951 FDO_FDMAEN | FDO_MOEN(0)); 952 } 953 954 bus_space_write_1(t, h, fdc->sc_reg_drs, DRS_RESET); 955 delay(10); 956 bus_space_write_1(t, h, fdc->sc_reg_drs, 0); 957 958 if ((fdc->sc_flags & FDC_82077) != 0) { 959 bus_space_write_1(t, h, fdc->sc_reg_dor, 960 FDO_FRST | FDO_FDMAEN | FDO_DS); 961 } 962 #ifdef FD_DEBUG 963 if (fdc_debug) 964 printf("fdc reset\n"); 965 #endif 966 } 967 968 void 969 fd_set_motor(fdc) 970 struct fdc_softc *fdc; 971 { 972 struct fd_softc *fd; 973 u_char status; 974 int n; 975 976 if ((fdc->sc_flags & FDC_82077) != 0) { 977 status = FDO_FRST | FDO_FDMAEN; 978 if ((fd = fdc->sc_drives.tqh_first) != NULL) 979 status |= fd->sc_drive; 980 981 for (n = 0; n < 4; n++) 982 if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR)) 983 status |= FDO_MOEN(n); 984 bus_space_write_1(fdc->sc_bustag, fdc->sc_handle, 985 fdc->sc_reg_dor, status); 986 } else { 987 988 for (n = 0; n < 4; n++) { 989 if ((fd = fdc->sc_fd[n]) != NULL && 990 (fd->sc_flags & FD_MOTOR) != 0) { 991 auxregbisc(AUXIO4C_FDS, 0); 992 return; 993 } 994 } 995 auxregbisc(0, AUXIO4C_FDS); 996 } 997 } 998 999 void 1000 fd_motor_off(arg) 1001 void *arg; 1002 { 1003 struct fd_softc *fd = arg; 1004 int s; 1005 1006 s = splbio(); 1007 fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); 1008 fd_set_motor((struct fdc_softc *)fd->sc_dv.dv_parent); 1009 splx(s); 1010 } 1011 1012 void 1013 fd_motor_on(arg) 1014 void *arg; 1015 { 1016 struct fd_softc *fd = arg; 1017 struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent; 1018 int s; 1019 1020 s = splbio(); 1021 fd->sc_flags &= ~FD_MOTOR_WAIT; 1022 if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT)) 1023 (void) fdcstate(fdc); 1024 splx(s); 1025 } 1026 1027 /* 1028 * Get status bytes off the FDC after a command has finished 1029 * Returns the number of status bytes read; -1 on error. 1030 * The return value is also stored in `sc_nstat'. 1031 */ 1032 int 1033 fdcresult(fdc) 1034 struct fdc_softc *fdc; 1035 { 1036 bus_space_tag_t t = fdc->sc_bustag; 1037 bus_space_handle_t h = fdc->sc_handle; 1038 int j, n = 0; 1039 1040 for (j = 10000; j; j--) { 1041 u_int8_t v = bus_space_read_1(t, h, fdc->sc_reg_msr); 1042 v &= (NE7_DIO | NE7_RQM | NE7_CB); 1043 if (v == NE7_RQM) 1044 return (fdc->sc_nstat = n); 1045 if (v == (NE7_DIO | NE7_RQM | NE7_CB)) { 1046 if (n >= sizeof(fdc->sc_status)) { 1047 log(LOG_ERR, "fdcresult: overrun\n"); 1048 return (-1); 1049 } 1050 fdc->sc_status[n++] = 1051 bus_space_read_1(t, h, fdc->sc_reg_fifo); 1052 } else 1053 delay(1); 1054 } 1055 1056 log(LOG_ERR, "fdcresult: timeout\n"); 1057 return (fdc->sc_nstat = -1); 1058 } 1059 1060 /* 1061 * Write a command byte to the FDC. 1062 * Returns 0 on success; -1 on failure (i.e. timeout) 1063 */ 1064 int 1065 fdc_wrfifo(fdc, x) 1066 struct fdc_softc *fdc; 1067 u_int8_t x; 1068 { 1069 bus_space_tag_t t = fdc->sc_bustag; 1070 bus_space_handle_t h = fdc->sc_handle; 1071 int i; 1072 1073 for (i = 100000; i-- > 0;) { 1074 u_int8_t v = bus_space_read_1(t, h, fdc->sc_reg_msr); 1075 if ((v & (NE7_DIO|NE7_RQM)) == NE7_RQM) { 1076 /* The chip is ready */ 1077 bus_space_write_1(t, h, fdc->sc_reg_fifo, x); 1078 return (0); 1079 } 1080 delay(1); 1081 } 1082 return (-1); 1083 } 1084 1085 int 1086 fdopen(dev, flags, fmt, p) 1087 dev_t dev; 1088 int flags, fmt; 1089 struct proc *p; 1090 { 1091 int unit, pmask; 1092 struct fd_softc *fd; 1093 struct fd_type *type; 1094 1095 unit = FDUNIT(dev); 1096 if (unit >= fd_cd.cd_ndevs) 1097 return (ENXIO); 1098 fd = fd_cd.cd_devs[unit]; 1099 if (fd == NULL) 1100 return (ENXIO); 1101 type = fd_dev_to_type(fd, dev); 1102 if (type == NULL) 1103 return (ENXIO); 1104 1105 if ((fd->sc_flags & FD_OPEN) != 0 && 1106 fd->sc_type != type) 1107 return (EBUSY); 1108 1109 fd->sc_type = type; 1110 fd->sc_cylin = -1; 1111 fd->sc_flags |= FD_OPEN; 1112 1113 /* 1114 * Only update the disklabel if we're not open anywhere else. 1115 */ 1116 if (fd->sc_dk.dk_openmask == 0) 1117 fdgetdisklabel(dev); 1118 1119 pmask = (1 << DISKPART(dev)); 1120 1121 switch (fmt) { 1122 case S_IFCHR: 1123 fd->sc_dk.dk_copenmask |= pmask; 1124 break; 1125 1126 case S_IFBLK: 1127 fd->sc_dk.dk_bopenmask |= pmask; 1128 break; 1129 } 1130 fd->sc_dk.dk_openmask = 1131 fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask; 1132 1133 return (0); 1134 } 1135 1136 int 1137 fdclose(dev, flags, fmt, p) 1138 dev_t dev; 1139 int flags, fmt; 1140 struct proc *p; 1141 { 1142 struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)]; 1143 int pmask = (1 << DISKPART(dev)); 1144 1145 fd->sc_flags &= ~FD_OPEN; 1146 fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT); 1147 1148 switch (fmt) { 1149 case S_IFCHR: 1150 fd->sc_dk.dk_copenmask &= ~pmask; 1151 break; 1152 1153 case S_IFBLK: 1154 fd->sc_dk.dk_bopenmask &= ~pmask; 1155 break; 1156 } 1157 fd->sc_dk.dk_openmask = 1158 fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask; 1159 1160 return (0); 1161 } 1162 1163 int 1164 fdread(dev, uio, flag) 1165 dev_t dev; 1166 struct uio *uio; 1167 int flag; 1168 { 1169 1170 return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio)); 1171 } 1172 1173 int 1174 fdwrite(dev, uio, flag) 1175 dev_t dev; 1176 struct uio *uio; 1177 int flag; 1178 { 1179 1180 return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio)); 1181 } 1182 1183 void 1184 fdcstart(fdc) 1185 struct fdc_softc *fdc; 1186 { 1187 1188 #ifdef DIAGNOSTIC 1189 /* only got here if controller's drive queue was inactive; should 1190 be in idle state */ 1191 if (fdc->sc_state != DEVIDLE) { 1192 printf("fdcstart: not idle\n"); 1193 return; 1194 } 1195 #endif 1196 (void) fdcstate(fdc); 1197 } 1198 1199 void 1200 fdcstatus(fdc, s) 1201 struct fdc_softc *fdc; 1202 char *s; 1203 { 1204 struct fd_softc *fd = fdc->sc_drives.tqh_first; 1205 int n; 1206 char bits[64]; 1207 1208 /* Just print last status */ 1209 n = fdc->sc_nstat; 1210 1211 #if 0 1212 /* 1213 * A 82072 seems to return <invalid command> on 1214 * gratuitous Sense Interrupt commands. 1215 */ 1216 if (n == 0 && (fdc->sc_flags & FDC_82077) != 0) { 1217 fdc_wrfifo(fdc, NE7CMD_SENSEI); 1218 (void) fdcresult(fdc); 1219 n = 2; 1220 } 1221 #endif 1222 1223 printf("%s: %s: state %d", 1224 fd ? fd->sc_dv.dv_xname : "fdc", s, fdc->sc_state); 1225 1226 switch (n) { 1227 case 0: 1228 printf("\n"); 1229 break; 1230 case 2: 1231 printf(" (st0 %s cyl %d)\n", 1232 bitmask_snprintf(fdc->sc_status[0], NE7_ST0BITS, 1233 bits, sizeof(bits)), fdc->sc_status[1]); 1234 break; 1235 case 7: 1236 printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0], 1237 NE7_ST0BITS, bits, sizeof(bits))); 1238 printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1], 1239 NE7_ST1BITS, bits, sizeof(bits))); 1240 printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2], 1241 NE7_ST2BITS, bits, sizeof(bits))); 1242 printf(" cyl %d head %d sec %d)\n", 1243 fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]); 1244 break; 1245 #ifdef DIAGNOSTIC 1246 default: 1247 printf(" fdcstatus: weird size: %d\n", n); 1248 break; 1249 #endif 1250 } 1251 } 1252 1253 void 1254 fdctimeout(arg) 1255 void *arg; 1256 { 1257 struct fdc_softc *fdc = arg; 1258 struct fd_softc *fd; 1259 int s; 1260 1261 s = splbio(); 1262 fd = fdc->sc_drives.tqh_first; 1263 if (fd == NULL) { 1264 printf("%s: timeout but no I/O pending: state %d, istatus=%d\n", 1265 fdc->sc_dev.dv_xname, 1266 fdc->sc_state, fdc->sc_istatus); 1267 fdc->sc_state = DEVIDLE; 1268 goto out; 1269 } 1270 1271 if (BUFQ_FIRST(&fd->sc_q) != NULL) 1272 fdc->sc_state++; 1273 else 1274 fdc->sc_state = DEVIDLE; 1275 1276 (void) fdcstate(fdc); 1277 out: 1278 splx(s); 1279 1280 } 1281 1282 void 1283 fdcpseudointr(arg) 1284 void *arg; 1285 { 1286 struct fdc_softc *fdc = arg; 1287 int s; 1288 1289 /* Just ensure it has the right spl. */ 1290 s = splbio(); 1291 (void) fdcstate(fdc); 1292 splx(s); 1293 } 1294 1295 1296 #ifdef FDC_C_HANDLER 1297 /* 1298 * hardware interrupt entry point: must be converted to `fast' 1299 * (in-window) handler. 1300 */ 1301 int 1302 fdc_c_hwintr(arg) 1303 void *arg; 1304 { 1305 struct fdc_softc *fdc = arg; 1306 bus_space_tag_t t = fdc->sc_bustag; 1307 bus_space_handle_t h = fdc->sc_handle; 1308 1309 switch (fdc->sc_itask) { 1310 case FDC_ITASK_NONE: 1311 return (0); 1312 case FDC_ITASK_SENSI: 1313 if (fdc_wrfifo(fdc, NE7CMD_SENSEI) != 0 || fdcresult(fdc) != 0) 1314 fdc->sc_istatus = FDC_ISTATUS_ERROR; 1315 else 1316 fdc->sc_istatus = FDC_ISTATUS_DONE; 1317 FD_SET_SWINTR; 1318 return (1); 1319 case FDC_ITASK_DMA: 1320 /* Proceed with pseudo-dma below */ 1321 break; 1322 default: 1323 printf("fdc: stray hard interrupt: itask=%d\n", fdc->sc_itask); 1324 fdc->sc_istatus = FDC_ISTATUS_SPURIOUS; 1325 FD_SET_SWINTR; 1326 return (1); 1327 } 1328 1329 /* 1330 * Pseudo DMA in progress 1331 */ 1332 for (;;) { 1333 u_int8_t msr; 1334 1335 msr = bus_space_read_1(t, h, fdc->sc_reg_msr); 1336 1337 if ((msr & NE7_RQM) == 0) 1338 /* That's all this round */ 1339 break; 1340 1341 if ((msr & NE7_NDM) == 0) { 1342 fdcresult(fdc); 1343 fdc->sc_istatus = FDC_ISTATUS_DONE; 1344 FD_SET_SWINTR; 1345 printf("fdc: overrun: tc = %d\n", fdc->sc_tc); 1346 break; 1347 } 1348 1349 /* Another byte can be transferred */ 1350 if ((msr & NE7_DIO) != 0) 1351 *fdc->sc_data = 1352 bus_space_read_1(t, h, fdc->sc_reg_fifo); 1353 else 1354 bus_space_write_1(t, h, fdc->sc_reg_fifo, 1355 *fdc->sc_data); 1356 1357 fdc->sc_data++; 1358 if (--fdc->sc_tc == 0) { 1359 fdc->sc_istatus = FDC_ISTATUS_DONE; 1360 FTC_FLIP; 1361 fdcresult(fdc); 1362 FD_SET_SWINTR; 1363 break; 1364 } 1365 } 1366 return (1); 1367 } 1368 #endif 1369 1370 int 1371 fdcswintr(arg) 1372 void *arg; 1373 { 1374 struct fdc_softc *fdc = arg; 1375 int s; 1376 1377 if (fdc->sc_istatus == FDC_ISTATUS_NONE) 1378 /* This (software) interrupt is not for us */ 1379 return (0); 1380 1381 switch (fdc->sc_istatus) { 1382 case FDC_ISTATUS_ERROR: 1383 printf("fdc: ierror status: state %d\n", fdc->sc_state); 1384 break; 1385 case FDC_ISTATUS_SPURIOUS: 1386 printf("fdc: spurious interrupt: state %d\n", fdc->sc_state); 1387 break; 1388 } 1389 1390 s = splbio(); 1391 fdcstate(fdc); 1392 splx(s); 1393 return (1); 1394 } 1395 1396 int 1397 fdcstate(fdc) 1398 struct fdc_softc *fdc; 1399 { 1400 #define st0 fdc->sc_status[0] 1401 #define st1 fdc->sc_status[1] 1402 #define cyl fdc->sc_status[1] 1403 #define FDC_WRFIFO(fdc, c) do { \ 1404 if (fdc_wrfifo(fdc, (c))) { \ 1405 goto xxx; \ 1406 } \ 1407 } while(0) 1408 1409 struct fd_softc *fd; 1410 struct buf *bp; 1411 int read, head, sec, nblks; 1412 struct fd_type *type; 1413 struct ne7_fd_formb *finfo = NULL; 1414 1415 if (fdc->sc_istatus == FDC_ISTATUS_ERROR) 1416 fdc->sc_state = DORESET; 1417 1418 /* Clear I task/status field */ 1419 fdc->sc_istatus = FDC_ISTATUS_NONE; 1420 fdc->sc_itask = FDC_ITASK_NONE; 1421 1422 loop: 1423 /* Is there a drive for the controller to do a transfer with? */ 1424 fd = fdc->sc_drives.tqh_first; 1425 if (fd == NULL) { 1426 fdc->sc_state = DEVIDLE; 1427 return (0); 1428 } 1429 1430 /* Is there a transfer to this drive? If not, deactivate drive. */ 1431 bp = BUFQ_FIRST(&fd->sc_q); 1432 if (bp == NULL) { 1433 fd->sc_ops = 0; 1434 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); 1435 fd->sc_active = 0; 1436 goto loop; 1437 } 1438 1439 if (bp->b_flags & B_FORMAT) 1440 finfo = (struct ne7_fd_formb *)bp->b_data; 1441 1442 switch (fdc->sc_state) { 1443 case DEVIDLE: 1444 fdc->sc_errors = 0; 1445 fd->sc_skip = 0; 1446 fd->sc_bcount = bp->b_bcount; 1447 fd->sc_blkno = (bp->b_blkno * DEV_BSIZE) / FD_BSIZE(fd); 1448 callout_stop(&fd->sc_motoroff_ch); 1449 if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) { 1450 fdc->sc_state = MOTORWAIT; 1451 return (1); 1452 } 1453 if ((fd->sc_flags & FD_MOTOR) == 0) { 1454 /* Turn on the motor, being careful about pairing. */ 1455 struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1]; 1456 if (ofd && ofd->sc_flags & FD_MOTOR) { 1457 callout_stop(&ofd->sc_motoroff_ch); 1458 ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); 1459 } 1460 fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT; 1461 fd_set_motor(fdc); 1462 fdc->sc_state = MOTORWAIT; 1463 if ((fdc->sc_flags & FDC_NEEDMOTORWAIT) != 0) { /*XXX*/ 1464 /* Allow .25s for motor to stabilize. */ 1465 callout_reset(&fd->sc_motoron_ch, hz / 4, 1466 fd_motor_on, fd); 1467 } else { 1468 fd->sc_flags &= ~FD_MOTOR_WAIT; 1469 goto loop; 1470 } 1471 return (1); 1472 } 1473 /* Make sure the right drive is selected. */ 1474 fd_set_motor(fdc); 1475 1476 /*FALLTHROUGH*/ 1477 case DOSEEK: 1478 doseek: 1479 if ((fdc->sc_flags & FDC_EIS) && 1480 (bp->b_flags & B_FORMAT) == 0) { 1481 fd->sc_cylin = bp->b_cylinder; 1482 /* We use implied seek */ 1483 goto doio; 1484 } 1485 1486 if (fd->sc_cylin == bp->b_cylinder) 1487 goto doio; 1488 1489 fd->sc_cylin = -1; 1490 fdc->sc_state = SEEKWAIT; 1491 fdc->sc_nstat = 0; 1492 1493 fd->sc_dk.dk_seek++; 1494 1495 disk_busy(&fd->sc_dk); 1496 callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc); 1497 1498 /* specify command */ 1499 FDC_WRFIFO(fdc, NE7CMD_SPECIFY); 1500 FDC_WRFIFO(fdc, fd->sc_type->steprate); 1501 /* XXX head load time == 6ms */ 1502 FDC_WRFIFO(fdc, 6 | NE7_SPECIFY_NODMA); 1503 1504 fdc->sc_itask = FDC_ITASK_SENSEI; 1505 /* seek function */ 1506 FDC_WRFIFO(fdc, NE7CMD_SEEK); 1507 FDC_WRFIFO(fdc, fd->sc_drive); /* drive number */ 1508 FDC_WRFIFO(fdc, bp->b_cylinder * fd->sc_type->step); 1509 return (1); 1510 1511 case DOIO: 1512 doio: 1513 if (finfo != NULL) 1514 fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) - 1515 (char *)finfo; 1516 type = fd->sc_type; 1517 sec = fd->sc_blkno % type->seccyl; 1518 nblks = type->seccyl - sec; 1519 nblks = min(nblks, fd->sc_bcount / FD_BSIZE(fd)); 1520 nblks = min(nblks, FDC_MAXIOSIZE / FD_BSIZE(fd)); 1521 fd->sc_nblks = nblks; 1522 fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FD_BSIZE(fd); 1523 head = sec / type->sectrac; 1524 sec -= head * type->sectrac; 1525 #ifdef DIAGNOSTIC 1526 {int block; 1527 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec; 1528 if (block != fd->sc_blkno) { 1529 printf("fdcintr: block %d != blkno %d\n", block, fd->sc_blkno); 1530 #ifdef DDB 1531 Debugger(); 1532 #endif 1533 }} 1534 #endif 1535 read = bp->b_flags & B_READ; 1536 1537 /* Setup for pseudo DMA */ 1538 fdc->sc_data = bp->b_data + fd->sc_skip; 1539 fdc->sc_tc = fd->sc_nbytes; 1540 1541 bus_space_write_1(fdc->sc_bustag, fdc->sc_handle, 1542 fdc->sc_reg_drs, type->rate); 1543 #ifdef FD_DEBUG 1544 if (fdc_debug > 1) 1545 printf("fdcstate: doio: %s drive %d " 1546 "track %d head %d sec %d nblks %d\n", 1547 finfo ? "format" : 1548 (read ? "read" : "write"), 1549 fd->sc_drive, fd->sc_cylin, head, sec, nblks); 1550 #endif 1551 fdc->sc_state = IOCOMPLETE; 1552 fdc->sc_itask = FDC_ITASK_DMA; 1553 fdc->sc_nstat = 0; 1554 1555 disk_busy(&fd->sc_dk); 1556 1557 /* allow 3 seconds for operation */ 1558 callout_reset(&fdc->sc_timo_ch, 3 * hz, fdctimeout, fdc); 1559 1560 if (finfo != NULL) { 1561 /* formatting */ 1562 FDC_WRFIFO(fdc, NE7CMD_FORMAT); 1563 FDC_WRFIFO(fdc, (head << 2) | fd->sc_drive); 1564 FDC_WRFIFO(fdc, finfo->fd_formb_secshift); 1565 FDC_WRFIFO(fdc, finfo->fd_formb_nsecs); 1566 FDC_WRFIFO(fdc, finfo->fd_formb_gaplen); 1567 FDC_WRFIFO(fdc, finfo->fd_formb_fillbyte); 1568 } else { 1569 if (read) 1570 FDC_WRFIFO(fdc, NE7CMD_READ); 1571 else 1572 FDC_WRFIFO(fdc, NE7CMD_WRITE); 1573 FDC_WRFIFO(fdc, (head << 2) | fd->sc_drive); 1574 FDC_WRFIFO(fdc, fd->sc_cylin); /*track*/ 1575 FDC_WRFIFO(fdc, head); 1576 FDC_WRFIFO(fdc, sec + 1); /*sector+1*/ 1577 FDC_WRFIFO(fdc, type->secsize);/*sector size*/ 1578 FDC_WRFIFO(fdc, type->sectrac);/*secs/track*/ 1579 FDC_WRFIFO(fdc, type->gap1); /*gap1 size*/ 1580 FDC_WRFIFO(fdc, type->datalen);/*data length*/ 1581 } 1582 1583 return (1); /* will return later */ 1584 1585 case SEEKWAIT: 1586 callout_stop(&fdc->sc_timo_ch); 1587 fdc->sc_state = SEEKCOMPLETE; 1588 if (fdc->sc_flags & FDC_NEEDHEADSETTLE) { 1589 /* allow 1/50 second for heads to settle */ 1590 callout_reset(&fdc->sc_intr_ch, hz / 50, 1591 fdcpseudointr, fdc); 1592 return (1); /* will return later */ 1593 } 1594 /*FALLTHROUGH*/ 1595 case SEEKCOMPLETE: 1596 disk_unbusy(&fd->sc_dk, 0); /* no data on seek */ 1597 1598 /* Make sure seek really happened. */ 1599 if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 || 1600 cyl != bp->b_cylinder * fd->sc_type->step) { 1601 #ifdef FD_DEBUG 1602 if (fdc_debug) 1603 fdcstatus(fdc, "seek failed"); 1604 #endif 1605 fdcretry(fdc); 1606 goto loop; 1607 } 1608 fd->sc_cylin = bp->b_cylinder; 1609 goto doio; 1610 1611 case IOTIMEDOUT: 1612 /* 1613 * Try to abort the I/O operation without resetting 1614 * the chip first. Poke TC and arrange to pick up 1615 * the timed out I/O command's status. 1616 */ 1617 fdc->sc_itask = FDC_ITASK_RESULT; 1618 fdc->sc_state = IOCLEANUPWAIT; 1619 fdc->sc_nstat = 0; 1620 /* 1/10 second should be enough */ 1621 callout_reset(&fdc->sc_timo_ch, hz / 10, fdctimeout, fdc); 1622 FTC_FLIP; 1623 return (1); 1624 1625 case IOCLEANUPTIMEDOUT: 1626 case SEEKTIMEDOUT: 1627 case RECALTIMEDOUT: 1628 case RESETTIMEDOUT: 1629 fdcstatus(fdc, "timeout"); 1630 1631 /* All other timeouts always roll through to a chip reset */ 1632 fdcretry(fdc); 1633 1634 /* Force reset, no matter what fdcretry() says */ 1635 fdc->sc_state = DORESET; 1636 goto loop; 1637 1638 case IOCLEANUPWAIT: /* IO FAILED, cleanup succeeded */ 1639 callout_stop(&fdc->sc_timo_ch); 1640 disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid)); 1641 fdcretry(fdc); 1642 goto loop; 1643 1644 case IOCOMPLETE: /* IO DONE, post-analyze */ 1645 callout_stop(&fdc->sc_timo_ch); 1646 1647 disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid)); 1648 1649 if (fdc->sc_nstat != 7 || st1 != 0 || 1650 ((st0 & 0xf8) != 0 && 1651 ((st0 & 0xf8) != 0x20 || (fdc->sc_cfg & CFG_EIS) == 0))) { 1652 #ifdef FD_DEBUG 1653 if (fdc_debug) { 1654 fdcstatus(fdc, 1655 bp->b_flags & B_READ 1656 ? "read failed" : "write failed"); 1657 printf("blkno %d nblks %d nstat %d tc %d\n", 1658 fd->sc_blkno, fd->sc_nblks, 1659 fdc->sc_nstat, fdc->sc_tc); 1660 } 1661 #endif 1662 if (fdc->sc_nstat == 7 && 1663 (st1 & ST1_OVERRUN) == ST1_OVERRUN) { 1664 1665 /* 1666 * Silently retry overruns if no other 1667 * error bit is set. Adjust threshold. 1668 */ 1669 int thr = fdc->sc_cfg & CFG_THRHLD_MASK; 1670 if (thr < 15) { 1671 thr++; 1672 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 1673 fdc->sc_cfg |= (thr & CFG_THRHLD_MASK); 1674 #ifdef FD_DEBUG 1675 if (fdc_debug) 1676 printf("fdc: %d -> threshold\n", thr); 1677 #endif 1678 fdconf(fdc); 1679 fdc->sc_overruns = 0; 1680 } 1681 if (++fdc->sc_overruns < 3) { 1682 fdc->sc_state = DOIO; 1683 goto loop; 1684 } 1685 } 1686 fdcretry(fdc); 1687 goto loop; 1688 } 1689 if (fdc->sc_errors) { 1690 diskerr(bp, "fd", "soft error", LOG_PRINTF, 1691 fd->sc_skip / FD_BSIZE(fd), 1692 (struct disklabel *)NULL); 1693 printf("\n"); 1694 fdc->sc_errors = 0; 1695 } else { 1696 if (--fdc->sc_overruns < -20) { 1697 int thr = fdc->sc_cfg & CFG_THRHLD_MASK; 1698 if (thr > 0) { 1699 thr--; 1700 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 1701 fdc->sc_cfg |= (thr & CFG_THRHLD_MASK); 1702 #ifdef FD_DEBUG 1703 if (fdc_debug) 1704 printf("fdc: %d -> threshold\n", thr); 1705 #endif 1706 fdconf(fdc); 1707 } 1708 fdc->sc_overruns = 0; 1709 } 1710 } 1711 fd->sc_blkno += fd->sc_nblks; 1712 fd->sc_skip += fd->sc_nbytes; 1713 fd->sc_bcount -= fd->sc_nbytes; 1714 if (finfo == NULL && fd->sc_bcount > 0) { 1715 bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl; 1716 goto doseek; 1717 } 1718 fdfinish(fd, bp); 1719 goto loop; 1720 1721 case DORESET: 1722 /* try a reset, keep motor on */ 1723 fd_set_motor(fdc); 1724 delay(100); 1725 fdc->sc_nstat = 0; 1726 fdc->sc_itask = FDC_ITASK_SENSEI; 1727 fdc->sc_state = RESETCOMPLETE; 1728 callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc); 1729 fdc_reset(fdc); 1730 return (1); /* will return later */ 1731 1732 case RESETCOMPLETE: 1733 callout_stop(&fdc->sc_timo_ch); 1734 fdconf(fdc); 1735 1736 /* FALLTHROUGH */ 1737 case DORECAL: 1738 fdc->sc_state = RECALWAIT; 1739 fdc->sc_itask = FDC_ITASK_SENSEI; 1740 fdc->sc_nstat = 0; 1741 callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc); 1742 /* recalibrate function */ 1743 FDC_WRFIFO(fdc, NE7CMD_RECAL); 1744 FDC_WRFIFO(fdc, fd->sc_drive); 1745 return (1); /* will return later */ 1746 1747 case RECALWAIT: 1748 callout_stop(&fdc->sc_timo_ch); 1749 fdc->sc_state = RECALCOMPLETE; 1750 if (fdc->sc_flags & FDC_NEEDHEADSETTLE) { 1751 /* allow 1/30 second for heads to settle */ 1752 callout_reset(&fdc->sc_intr_ch, hz / 30, 1753 fdcpseudointr, fdc); 1754 return (1); /* will return later */ 1755 } 1756 1757 case RECALCOMPLETE: 1758 if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) { 1759 #ifdef FD_DEBUG 1760 if (fdc_debug) 1761 fdcstatus(fdc, "recalibrate failed"); 1762 #endif 1763 fdcretry(fdc); 1764 goto loop; 1765 } 1766 fd->sc_cylin = 0; 1767 goto doseek; 1768 1769 case MOTORWAIT: 1770 if (fd->sc_flags & FD_MOTOR_WAIT) 1771 return (1); /* time's not up yet */ 1772 goto doseek; 1773 1774 default: 1775 fdcstatus(fdc, "stray interrupt"); 1776 return (1); 1777 } 1778 #ifdef DIAGNOSTIC 1779 panic("fdcintr: impossible"); 1780 #endif 1781 1782 xxx: 1783 /* 1784 * We get here if the chip locks up in FDC_WRFIFO() 1785 * Cancel any operation and schedule a reset 1786 */ 1787 callout_stop(&fdc->sc_timo_ch); 1788 fdcretry(fdc); 1789 (fdc)->sc_state = DORESET; 1790 goto loop; 1791 1792 #undef st0 1793 #undef st1 1794 #undef cyl 1795 } 1796 1797 void 1798 fdcretry(fdc) 1799 struct fdc_softc *fdc; 1800 { 1801 struct fd_softc *fd; 1802 struct buf *bp; 1803 int error = EIO; 1804 1805 fd = fdc->sc_drives.tqh_first; 1806 bp = BUFQ_FIRST(&fd->sc_q); 1807 1808 fdc->sc_overruns = 0; 1809 if (fd->sc_opts & FDOPT_NORETRY) 1810 goto fail; 1811 1812 switch (fdc->sc_errors) { 1813 case 0: 1814 if (fdc->sc_nstat == 7 && 1815 (fdc->sc_status[0] & 0xd8) == 0x40 && 1816 (fdc->sc_status[1] & 0x2) == 0x2) { 1817 printf("%s: read-only medium\n", fd->sc_dv.dv_xname); 1818 error = EROFS; 1819 goto failsilent; 1820 } 1821 /* try again */ 1822 fdc->sc_state = 1823 (fdc->sc_flags & FDC_EIS) ? DOIO : DOSEEK; 1824 break; 1825 1826 case 1: case 2: case 3: 1827 /* didn't work; try recalibrating */ 1828 fdc->sc_state = DORECAL; 1829 break; 1830 1831 case 4: 1832 if (fdc->sc_nstat == 7 && 1833 fdc->sc_status[0] == 0 && 1834 fdc->sc_status[1] == 0 && 1835 fdc->sc_status[2] == 0) { 1836 /* 1837 * We've retried a few times and we've got 1838 * valid status and all three status bytes 1839 * are zero. Assume this condition is the 1840 * result of no disk loaded into the drive. 1841 */ 1842 printf("%s: no medium?\n", fd->sc_dv.dv_xname); 1843 error = ENODEV; 1844 goto failsilent; 1845 } 1846 1847 /* still no go; reset the bastard */ 1848 fdc->sc_state = DORESET; 1849 break; 1850 1851 default: 1852 fail: 1853 if ((fd->sc_opts & FDOPT_SILENT) == 0) { 1854 diskerr(bp, "fd", "hard error", LOG_PRINTF, 1855 fd->sc_skip / FD_BSIZE(fd), 1856 (struct disklabel *)NULL); 1857 printf("\n"); 1858 fdcstatus(fdc, "controller status"); 1859 } 1860 1861 failsilent: 1862 bp->b_flags |= B_ERROR; 1863 bp->b_error = error; 1864 fdfinish(fd, bp); 1865 } 1866 fdc->sc_errors++; 1867 } 1868 1869 int 1870 fdsize(dev) 1871 dev_t dev; 1872 { 1873 1874 /* Swapping to floppies would not make sense. */ 1875 return (-1); 1876 } 1877 1878 int 1879 fddump(dev, blkno, va, size) 1880 dev_t dev; 1881 daddr_t blkno; 1882 caddr_t va; 1883 size_t size; 1884 { 1885 1886 /* Not implemented. */ 1887 return (EINVAL); 1888 } 1889 1890 int 1891 fdioctl(dev, cmd, addr, flag, p) 1892 dev_t dev; 1893 u_long cmd; 1894 caddr_t addr; 1895 int flag; 1896 struct proc *p; 1897 { 1898 struct fd_softc *fd; 1899 struct fdc_softc *fdc; 1900 struct fdformat_parms *form_parms; 1901 struct fdformat_cmd *form_cmd; 1902 struct ne7_fd_formb fd_formb; 1903 int il[FD_MAX_NSEC + 1]; 1904 int unit; 1905 int i, j; 1906 int error; 1907 1908 unit = FDUNIT(dev); 1909 if (unit >= fd_cd.cd_ndevs) 1910 return (ENXIO); 1911 1912 fd = fd_cd.cd_devs[FDUNIT(dev)]; 1913 fdc = (struct fdc_softc *)fd->sc_dv.dv_parent; 1914 1915 switch (cmd) { 1916 case DIOCGDINFO: 1917 *(struct disklabel *)addr = *(fd->sc_dk.dk_label); 1918 return 0; 1919 1920 case DIOCWLABEL: 1921 if ((flag & FWRITE) == 0) 1922 return EBADF; 1923 /* XXX do something */ 1924 return (0); 1925 1926 case DIOCWDINFO: 1927 if ((flag & FWRITE) == 0) 1928 return (EBADF); 1929 1930 error = setdisklabel(fd->sc_dk.dk_label, 1931 (struct disklabel *)addr, 0, 1932 fd->sc_dk.dk_cpulabel); 1933 if (error) 1934 return (error); 1935 1936 error = writedisklabel(dev, fdstrategy, 1937 fd->sc_dk.dk_label, 1938 fd->sc_dk.dk_cpulabel); 1939 return (error); 1940 1941 case DIOCLOCK: 1942 /* 1943 * Nothing to do here, really. 1944 */ 1945 return (0); 1946 1947 case DIOCEJECT: 1948 if (*(int *)addr == 0) { 1949 int part = DISKPART(dev); 1950 /* 1951 * Don't force eject: check that we are the only 1952 * partition open. If so, unlock it. 1953 */ 1954 if ((fd->sc_dk.dk_openmask & ~(1 << part)) != 0 || 1955 fd->sc_dk.dk_bopenmask + fd->sc_dk.dk_copenmask != 1956 fd->sc_dk.dk_openmask) { 1957 return (EBUSY); 1958 } 1959 } 1960 /* FALLTHROUGH */ 1961 case ODIOCEJECT: 1962 fd_do_eject(fd); 1963 return (0); 1964 1965 case FDIOCGETFORMAT: 1966 form_parms = (struct fdformat_parms *)addr; 1967 form_parms->fdformat_version = FDFORMAT_VERSION; 1968 form_parms->nbps = 128 * (1 << fd->sc_type->secsize); 1969 form_parms->ncyl = fd->sc_type->cylinders; 1970 form_parms->nspt = fd->sc_type->sectrac; 1971 form_parms->ntrk = fd->sc_type->heads; 1972 form_parms->stepspercyl = fd->sc_type->step; 1973 form_parms->gaplen = fd->sc_type->gap2; 1974 form_parms->fillbyte = fd->sc_type->fillbyte; 1975 form_parms->interleave = fd->sc_type->interleave; 1976 switch (fd->sc_type->rate) { 1977 case FDC_500KBPS: 1978 form_parms->xfer_rate = 500 * 1024; 1979 break; 1980 case FDC_300KBPS: 1981 form_parms->xfer_rate = 300 * 1024; 1982 break; 1983 case FDC_250KBPS: 1984 form_parms->xfer_rate = 250 * 1024; 1985 break; 1986 default: 1987 return (EINVAL); 1988 } 1989 return (0); 1990 1991 case FDIOCSETFORMAT: 1992 if ((flag & FWRITE) == 0) 1993 return (EBADF); /* must be opened for writing */ 1994 1995 form_parms = (struct fdformat_parms *)addr; 1996 if (form_parms->fdformat_version != FDFORMAT_VERSION) 1997 return (EINVAL);/* wrong version of formatting prog */ 1998 1999 i = form_parms->nbps >> 7; 2000 if ((form_parms->nbps & 0x7f) || ffs(i) == 0 || 2001 i & ~(1 << (ffs(i)-1))) 2002 /* not a power-of-two multiple of 128 */ 2003 return (EINVAL); 2004 2005 switch (form_parms->xfer_rate) { 2006 case 500 * 1024: 2007 fd->sc_type->rate = FDC_500KBPS; 2008 break; 2009 case 300 * 1024: 2010 fd->sc_type->rate = FDC_300KBPS; 2011 break; 2012 case 250 * 1024: 2013 fd->sc_type->rate = FDC_250KBPS; 2014 break; 2015 default: 2016 return (EINVAL); 2017 } 2018 2019 if (form_parms->nspt > FD_MAX_NSEC || 2020 form_parms->fillbyte > 0xff || 2021 form_parms->interleave > 0xff) 2022 return EINVAL; 2023 fd->sc_type->sectrac = form_parms->nspt; 2024 if (form_parms->ntrk != 2 && form_parms->ntrk != 1) 2025 return EINVAL; 2026 fd->sc_type->heads = form_parms->ntrk; 2027 fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk; 2028 fd->sc_type->secsize = ffs(i)-1; 2029 fd->sc_type->gap2 = form_parms->gaplen; 2030 fd->sc_type->cylinders = form_parms->ncyl; 2031 fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl * 2032 form_parms->nbps / DEV_BSIZE; 2033 fd->sc_type->step = form_parms->stepspercyl; 2034 fd->sc_type->fillbyte = form_parms->fillbyte; 2035 fd->sc_type->interleave = form_parms->interleave; 2036 return (0); 2037 2038 case FDIOCFORMAT_TRACK: 2039 if((flag & FWRITE) == 0) 2040 /* must be opened for writing */ 2041 return (EBADF); 2042 form_cmd = (struct fdformat_cmd *)addr; 2043 if (form_cmd->formatcmd_version != FDFORMAT_VERSION) 2044 /* wrong version of formatting prog */ 2045 return (EINVAL); 2046 2047 if (form_cmd->head >= fd->sc_type->heads || 2048 form_cmd->cylinder >= fd->sc_type->cylinders) { 2049 return (EINVAL); 2050 } 2051 2052 fd_formb.head = form_cmd->head; 2053 fd_formb.cyl = form_cmd->cylinder; 2054 fd_formb.transfer_rate = fd->sc_type->rate; 2055 fd_formb.fd_formb_secshift = fd->sc_type->secsize; 2056 fd_formb.fd_formb_nsecs = fd->sc_type->sectrac; 2057 fd_formb.fd_formb_gaplen = fd->sc_type->gap2; 2058 fd_formb.fd_formb_fillbyte = fd->sc_type->fillbyte; 2059 2060 bzero(il, sizeof il); 2061 for (j = 0, i = 1; i <= fd_formb.fd_formb_nsecs; i++) { 2062 while (il[(j%fd_formb.fd_formb_nsecs) + 1]) 2063 j++; 2064 il[(j%fd_formb.fd_formb_nsecs) + 1] = i; 2065 j += fd->sc_type->interleave; 2066 } 2067 for (i = 0; i < fd_formb.fd_formb_nsecs; i++) { 2068 fd_formb.fd_formb_cylno(i) = form_cmd->cylinder; 2069 fd_formb.fd_formb_headno(i) = form_cmd->head; 2070 fd_formb.fd_formb_secno(i) = il[i+1]; 2071 fd_formb.fd_formb_secsize(i) = fd->sc_type->secsize; 2072 } 2073 2074 return fdformat(dev, &fd_formb, p); 2075 2076 case FDIOCGETOPTS: /* get drive options */ 2077 *(int *)addr = fd->sc_opts; 2078 return (0); 2079 2080 case FDIOCSETOPTS: /* set drive options */ 2081 fd->sc_opts = *(int *)addr; 2082 return (0); 2083 2084 #ifdef FD_DEBUG 2085 case _IO('f', 100): 2086 fdc_wrfifo(fdc, NE7CMD_DUMPREG); 2087 fdcresult(fdc); 2088 printf("fdc: dumpreg(%d regs): <", fdc->sc_nstat); 2089 for (i = 0; i < fdc->sc_nstat; i++) 2090 printf(" 0x%x", fdc->sc_status[i]); 2091 printf(">\n"); 2092 return (0); 2093 2094 case _IOW('f', 101, int): 2095 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 2096 fdc->sc_cfg |= (*(int *)addr & CFG_THRHLD_MASK); 2097 fdconf(fdc); 2098 return (0); 2099 2100 case _IO('f', 102): 2101 fdc_wrfifo(fdc, NE7CMD_SENSEI); 2102 fdcresult(fdc); 2103 printf("fdc: sensei(%d regs): <", fdc->sc_nstat); 2104 for (i=0; i< fdc->sc_nstat; i++) 2105 printf(" 0x%x", fdc->sc_status[i]); 2106 printf(">\n"); 2107 return (0); 2108 #endif 2109 default: 2110 return (ENOTTY); 2111 } 2112 2113 #ifdef DIAGNOSTIC 2114 panic("fdioctl: impossible"); 2115 #endif 2116 } 2117 2118 int 2119 fdformat(dev, finfo, p) 2120 dev_t dev; 2121 struct ne7_fd_formb *finfo; 2122 struct proc *p; 2123 { 2124 int rv = 0, s; 2125 struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)]; 2126 struct fd_type *type = fd->sc_type; 2127 struct buf *bp; 2128 2129 /* set up a buffer header for fdstrategy() */ 2130 bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 2131 if (bp == 0) 2132 return (ENOBUFS); 2133 2134 PHOLD(p); 2135 bzero((void *)bp, sizeof(struct buf)); 2136 bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 2137 bp->b_proc = p; 2138 bp->b_dev = dev; 2139 2140 /* 2141 * Calculate a fake blkno, so fdstrategy() would initiate a 2142 * seek to the requested cylinder. 2143 */ 2144 bp->b_blkno = ((finfo->cyl * (type->sectrac * type->heads) 2145 + finfo->head * type->sectrac) * FD_BSIZE(fd)) 2146 / DEV_BSIZE; 2147 2148 bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 2149 bp->b_data = (caddr_t)finfo; 2150 2151 #ifdef FD_DEBUG 2152 if (fdc_debug) { 2153 int i; 2154 2155 printf("fdformat: blkno 0x%x count %ld\n", 2156 bp->b_blkno, bp->b_bcount); 2157 2158 printf("\tcyl:\t%d\n", finfo->cyl); 2159 printf("\thead:\t%d\n", finfo->head); 2160 printf("\tnsecs:\t%d\n", finfo->fd_formb_nsecs); 2161 printf("\tsshft:\t%d\n", finfo->fd_formb_secshift); 2162 printf("\tgaplen:\t%d\n", finfo->fd_formb_gaplen); 2163 printf("\ttrack data:"); 2164 for (i = 0; i < finfo->fd_formb_nsecs; i++) { 2165 printf(" [c%d h%d s%d]", 2166 finfo->fd_formb_cylno(i), 2167 finfo->fd_formb_headno(i), 2168 finfo->fd_formb_secno(i) ); 2169 if (finfo->fd_formb_secsize(i) != 2) 2170 printf("<sz:%d>", finfo->fd_formb_secsize(i)); 2171 } 2172 printf("\n"); 2173 } 2174 #endif 2175 2176 /* now do the format */ 2177 fdstrategy(bp); 2178 2179 /* ...and wait for it to complete */ 2180 s = splbio(); 2181 while (!(bp->b_flags & B_DONE)) { 2182 rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 2183 if (rv == EWOULDBLOCK) 2184 break; 2185 } 2186 splx(s); 2187 2188 if (rv == EWOULDBLOCK) { 2189 /* timed out */ 2190 rv = EIO; 2191 biodone(bp); 2192 } 2193 if (bp->b_flags & B_ERROR) { 2194 rv = bp->b_error; 2195 } 2196 PRELE(p); 2197 free(bp, M_TEMP); 2198 return (rv); 2199 } 2200 2201 void 2202 fdgetdisklabel(dev) 2203 dev_t dev; 2204 { 2205 int unit = FDUNIT(dev), i; 2206 struct fd_softc *fd = fd_cd.cd_devs[unit]; 2207 struct disklabel *lp = fd->sc_dk.dk_label; 2208 struct cpu_disklabel *clp = fd->sc_dk.dk_cpulabel; 2209 2210 bzero(lp, sizeof(struct disklabel)); 2211 bzero(lp, sizeof(struct cpu_disklabel)); 2212 2213 lp->d_type = DTYPE_FLOPPY; 2214 lp->d_secsize = FD_BSIZE(fd); 2215 lp->d_secpercyl = fd->sc_type->seccyl; 2216 lp->d_nsectors = fd->sc_type->sectrac; 2217 lp->d_ncylinders = fd->sc_type->cylinders; 2218 lp->d_ntracks = fd->sc_type->heads; /* Go figure... */ 2219 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 2220 lp->d_rpm = 3600; /* XXX like it matters... */ 2221 2222 strncpy(lp->d_typename, "floppy", sizeof(lp->d_typename)); 2223 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 2224 lp->d_interleave = 1; 2225 2226 lp->d_partitions[RAW_PART].p_offset = 0; 2227 lp->d_partitions[RAW_PART].p_size = lp->d_secpercyl * lp->d_ncylinders; 2228 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 2229 lp->d_npartitions = RAW_PART + 1; 2230 2231 lp->d_magic = DISKMAGIC; 2232 lp->d_magic2 = DISKMAGIC; 2233 lp->d_checksum = dkcksum(lp); 2234 2235 /* 2236 * Call the generic disklabel extraction routine. If there's 2237 * not a label there, fake it. 2238 */ 2239 if (readdisklabel(dev, fdstrategy, lp, clp) != NULL) { 2240 strncpy(lp->d_packname, "default label", 2241 sizeof(lp->d_packname)); 2242 /* 2243 * Reset the partition info; it might have gotten 2244 * trashed in readdisklabel(). 2245 * 2246 * XXX Why do we have to do this? readdisklabel() 2247 * should be safe... 2248 */ 2249 for (i = 0; i < MAXPARTITIONS; ++i) { 2250 lp->d_partitions[i].p_offset = 0; 2251 if (i == RAW_PART) { 2252 lp->d_partitions[i].p_size = 2253 lp->d_secpercyl * lp->d_ncylinders; 2254 lp->d_partitions[i].p_fstype = FS_BSDFFS; 2255 } else { 2256 lp->d_partitions[i].p_size = 0; 2257 lp->d_partitions[i].p_fstype = FS_UNUSED; 2258 } 2259 } 2260 lp->d_npartitions = RAW_PART + 1; 2261 } 2262 } 2263 2264 void 2265 fd_do_eject(fd) 2266 struct fd_softc *fd; 2267 { 2268 struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent; 2269 2270 if (CPU_ISSUN4C) { 2271 auxregbisc(AUXIO4C_FDS, AUXIO4C_FEJ); 2272 delay(10); 2273 auxregbisc(AUXIO4C_FEJ, AUXIO4C_FDS); 2274 return; 2275 } 2276 if (CPU_ISSUN4M && (fdc->sc_flags & FDC_82077) != 0) { 2277 bus_space_tag_t t = fdc->sc_bustag; 2278 bus_space_handle_t h = fdc->sc_handle; 2279 u_int8_t dor = FDO_FRST | FDO_FDMAEN | FDO_MOEN(0); 2280 2281 bus_space_write_1(t, h, fdc->sc_reg_dor, dor | FDO_EJ); 2282 delay(10); 2283 bus_space_write_1(t, h, fdc->sc_reg_dor, FDO_FRST | FDO_DS); 2284 return; 2285 } 2286 } 2287 2288 #ifdef MEMORY_DISK_HOOKS 2289 int fd_read_md_image __P((size_t *, caddr_t *)); 2290 #endif 2291 2292 /* ARGSUSED */ 2293 void 2294 fd_mountroot_hook(dev) 2295 struct device *dev; 2296 { 2297 int c; 2298 2299 fd_do_eject((struct fd_softc *)dev); 2300 printf("Insert filesystem floppy and press return."); 2301 for (;;) { 2302 c = cngetc(); 2303 if ((c == '\r') || (c == '\n')) { 2304 printf("\n"); 2305 break; 2306 } 2307 } 2308 } 2309 2310 #ifdef MEMORY_DISK_HOOKS 2311 2312 #define FDMICROROOTSIZE ((2*18*80) << DEV_BSHIFT) 2313 2314 int 2315 fd_read_md_image(sizep, addrp) 2316 size_t *sizep; 2317 caddr_t *addrp; 2318 { 2319 struct buf buf, *bp = &buf; 2320 dev_t dev; 2321 off_t offset; 2322 caddr_t addr; 2323 2324 dev = makedev(54,0); /* XXX */ 2325 2326 MALLOC(addr, caddr_t, FDMICROROOTSIZE, M_DEVBUF, M_WAITOK); 2327 *addrp = addr; 2328 2329 if (fdopen(dev, 0, S_IFCHR, NULL)) 2330 panic("fd: mountroot: fdopen"); 2331 2332 offset = 0; 2333 2334 for (;;) { 2335 bp->b_dev = dev; 2336 bp->b_error = 0; 2337 bp->b_resid = 0; 2338 bp->b_proc = NULL; 2339 bp->b_flags = B_BUSY | B_PHYS | B_RAW | B_READ; 2340 bp->b_blkno = btodb(offset); 2341 bp->b_bcount = DEV_BSIZE; 2342 bp->b_data = addr; 2343 fdstrategy(bp); 2344 while ((bp->b_flags & B_DONE) == 0) { 2345 tsleep((caddr_t)bp, PRIBIO + 1, "physio", 0); 2346 } 2347 if (bp->b_error) 2348 panic("fd: mountroot: fdread error %d", bp->b_error); 2349 2350 if (bp->b_resid != 0) 2351 break; 2352 2353 addr += DEV_BSIZE; 2354 offset += DEV_BSIZE; 2355 if (offset + DEV_BSIZE > FDMICROROOTSIZE) 2356 break; 2357 } 2358 (void)fdclose(dev, 0, S_IFCHR, NULL); 2359 *sizep = offset; 2360 fd_do_eject(fd_cd.cd_devs[FDUNIT(dev)]); 2361 return (0); 2362 } 2363 #endif 2364