1 /* $NetBSD: fd.c,v 1.88 2001/09/26 20:53:05 eeh 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 <uvm/uvm_extern.h> 105 106 #include <machine/autoconf.h> 107 #include <machine/intr.h> 108 #include <machine/conf.h> 109 110 #include <sparc/sparc/auxreg.h> 111 #include <sparc/dev/fdreg.h> 112 #include <sparc/dev/fdvar.h> 113 114 #define FDUNIT(dev) (minor(dev) / 8) 115 #define FDTYPE(dev) (minor(dev) % 8) 116 117 /* XXX misuse a flag to identify format operation */ 118 #define B_FORMAT B_XXX 119 120 #define FD_DEBUG 121 #ifdef FD_DEBUG 122 int fdc_debug = 0; 123 #endif 124 125 enum fdc_state { 126 DEVIDLE = 0, 127 MOTORWAIT, /* 1 */ 128 DOSEEK, /* 2 */ 129 SEEKWAIT, /* 3 */ 130 SEEKTIMEDOUT, /* 4 */ 131 SEEKCOMPLETE, /* 5 */ 132 DOIO, /* 6 */ 133 IOCOMPLETE, /* 7 */ 134 IOTIMEDOUT, /* 8 */ 135 IOCLEANUPWAIT, /* 9 */ 136 IOCLEANUPTIMEDOUT,/*10 */ 137 DORESET, /* 11 */ 138 RESETCOMPLETE, /* 12 */ 139 RESETTIMEDOUT, /* 13 */ 140 DORECAL, /* 14 */ 141 RECALWAIT, /* 15 */ 142 RECALTIMEDOUT, /* 16 */ 143 RECALCOMPLETE, /* 17 */ 144 }; 145 146 /* software state, per controller */ 147 struct fdc_softc { 148 struct device sc_dev; /* boilerplate */ 149 bus_space_tag_t sc_bustag; 150 151 struct callout sc_timo_ch; /* timeout callout */ 152 struct callout sc_intr_ch; /* pseudo-intr callout */ 153 154 struct fd_softc *sc_fd[4]; /* pointers to children */ 155 TAILQ_HEAD(drivehead, fd_softc) sc_drives; 156 enum fdc_state sc_state; 157 int sc_flags; 158 #define FDC_82077 0x01 159 #define FDC_NEEDHEADSETTLE 0x02 160 #define FDC_EIS 0x04 161 #define FDC_NEEDMOTORWAIT 0x08 162 int sc_errors; /* number of retries so far */ 163 int sc_overruns; /* number of DMA overruns */ 164 int sc_cfg; /* current configuration */ 165 struct fdcio sc_io; 166 #define sc_handle sc_io.fdcio_handle 167 #define sc_reg_msr sc_io.fdcio_reg_msr 168 #define sc_reg_fifo sc_io.fdcio_reg_fifo 169 #define sc_reg_dor sc_io.fdcio_reg_dor 170 #define sc_reg_drs sc_io.fdcio_reg_msr 171 #define sc_itask sc_io.fdcio_itask 172 #define sc_istatus sc_io.fdcio_istatus 173 #define sc_data sc_io.fdcio_data 174 #define sc_tc sc_io.fdcio_tc 175 #define sc_nstat sc_io.fdcio_nstat 176 #define sc_status sc_io.fdcio_status 177 #define sc_intrcnt sc_io.fdcio_intrcnt 178 }; 179 180 extern struct fdcio *fdciop; /* I/O descriptor used in fdintr.s */ 181 182 /* controller driver configuration */ 183 int fdcmatch_mainbus __P((struct device *, struct cfdata *, void *)); 184 int fdcmatch_obio __P((struct device *, struct cfdata *, void *)); 185 void fdcattach_mainbus __P((struct device *, struct device *, void *)); 186 void fdcattach_obio __P((struct device *, struct device *, void *)); 187 188 int fdcattach __P((struct fdc_softc *, int)); 189 190 struct cfattach fdc_mainbus_ca = { 191 sizeof(struct fdc_softc), fdcmatch_mainbus, fdcattach_mainbus 192 }; 193 struct cfattach fdc_obio_ca = { 194 sizeof(struct fdc_softc), fdcmatch_obio, fdcattach_obio 195 }; 196 197 __inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t)); 198 199 /* 200 * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how 201 * we tell them apart. 202 */ 203 struct fd_type { 204 int sectrac; /* sectors per track */ 205 int heads; /* number of heads */ 206 int seccyl; /* sectors per cylinder */ 207 int secsize; /* size code for sectors */ 208 int datalen; /* data len when secsize = 0 */ 209 int steprate; /* step rate and head unload time */ 210 int gap1; /* gap len between sectors */ 211 int gap2; /* formatting gap */ 212 int cylinders; /* total num of cylinders */ 213 int size; /* size of disk in sectors */ 214 int step; /* steps per cylinder */ 215 int rate; /* transfer speed code */ 216 int fillbyte; /* format fill byte */ 217 int interleave; /* interleave factor (formatting) */ 218 char *name; 219 }; 220 221 /* The order of entries in the following table is important -- BEWARE! */ 222 struct fd_type fd_types[] = { 223 { 18,2,36,2,0xff,0xcf,0x1b,0x54,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB" }, /* 1.44MB diskette */ 224 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB" }, /* 3.5" 720kB diskette */ 225 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,0xf6,1, "360KB/x" }, /* 360kB in 720kB drive */ 226 { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS,0xf6,1, "1.2MB/NEC" } /* 1.2 MB japanese format */ 227 }; 228 229 /* software state, per disk (with up to 4 disks per ctlr) */ 230 struct fd_softc { 231 struct device sc_dv; /* generic device info */ 232 struct disk sc_dk; /* generic disk info */ 233 234 struct fd_type *sc_deftype; /* default type descriptor */ 235 struct fd_type *sc_type; /* current type descriptor */ 236 237 struct callout sc_motoron_ch; 238 struct callout sc_motoroff_ch; 239 240 daddr_t sc_blkno; /* starting block number */ 241 int sc_bcount; /* byte count left */ 242 int sc_skip; /* bytes already transferred */ 243 int sc_nblks; /* number of blocks currently transferring */ 244 int sc_nbytes; /* number of bytes currently transferring */ 245 246 int sc_drive; /* physical unit number */ 247 int sc_flags; 248 #define FD_OPEN 0x01 /* it's open */ 249 #define FD_MOTOR 0x02 /* motor should be on */ 250 #define FD_MOTOR_WAIT 0x04 /* motor coming up */ 251 int sc_cylin; /* where we think the head is */ 252 int sc_opts; /* user-set options */ 253 254 void *sc_sdhook; /* shutdownhook cookie */ 255 256 TAILQ_ENTRY(fd_softc) sc_drivechain; 257 int sc_ops; /* I/O ops since last switch */ 258 struct buf_queue sc_q; /* pending I/O requests */ 259 int sc_active; /* number of active I/O requests */ 260 }; 261 262 /* floppy driver configuration */ 263 int fdmatch __P((struct device *, struct cfdata *, void *)); 264 void fdattach __P((struct device *, struct device *, void *)); 265 266 struct cfattach fd_ca = { 267 sizeof(struct fd_softc), fdmatch, fdattach 268 }; 269 270 extern struct cfdriver fd_cd; 271 272 void fdgetdisklabel __P((dev_t)); 273 int fd_get_parms __P((struct fd_softc *)); 274 void fdstrategy __P((struct buf *)); 275 void fdstart __P((struct fd_softc *)); 276 int fdprint __P((void *, const char *)); 277 278 struct dkdriver fddkdriver = { fdstrategy }; 279 280 struct fd_type *fd_nvtotype __P((char *, int, int)); 281 void fd_set_motor __P((struct fdc_softc *fdc)); 282 void fd_motor_off __P((void *arg)); 283 void fd_motor_on __P((void *arg)); 284 int fdcresult __P((struct fdc_softc *fdc)); 285 int fdc_wrfifo __P((struct fdc_softc *fdc, u_char x)); 286 void fdcstart __P((struct fdc_softc *fdc)); 287 void fdcstatus __P((struct fdc_softc *fdc, char *s)); 288 void fdc_reset __P((struct fdc_softc *fdc)); 289 void fdctimeout __P((void *arg)); 290 void fdcpseudointr __P((void *arg)); 291 int fdc_c_hwintr __P((void *)); 292 void fdchwintr __P((void)); 293 int fdcswintr __P((void *)); 294 int fdcstate __P((struct fdc_softc *)); 295 void fdcretry __P((struct fdc_softc *fdc)); 296 void fdfinish __P((struct fd_softc *fd, struct buf *bp)); 297 int fdformat __P((dev_t, struct ne7_fd_formb *, struct proc *)); 298 void fd_do_eject __P((struct fd_softc *)); 299 void fd_mountroot_hook __P((struct device *)); 300 static int fdconf __P((struct fdc_softc *)); 301 static void establish_chip_type __P(( 302 struct fdc_softc *, 303 bus_space_tag_t, 304 bus_type_t, 305 bus_addr_t, 306 bus_size_t, 307 bus_space_handle_t)); 308 309 310 #if PIL_FDSOFT == 4 311 #define IE_FDSOFT IE_L4 312 #else 313 #error 4 314 #endif 315 316 #if defined(SUN4M) 317 #define FD_SET_SWINTR do { \ 318 if (CPU_ISSUN4M) \ 319 raise(0, PIL_FDSOFT); \ 320 else \ 321 ienab_bis(IE_L4); \ 322 } while(0) 323 #else 324 #define FD_SET_SWINTR ienab_bis(IE_FDSOFT) 325 #endif /* defined(SUN4M) */ 326 327 #define OBP_FDNAME (CPU_ISSUN4M ? "SUNW,fdtwo" : "fd") 328 329 int 330 fdcmatch_mainbus(parent, match, aux) 331 struct device *parent; 332 struct cfdata *match; 333 void *aux; 334 { 335 struct mainbus_attach_args *ma = aux; 336 337 /* 338 * Floppy controller is on mainbus on sun4c. 339 */ 340 if (!CPU_ISSUN4C) 341 return (0); 342 343 /* sun4c PROMs call the controller "fd" */ 344 if (strcmp("fd", ma->ma_name) != 0) 345 return (0); 346 347 return (bus_space_probe(ma->ma_bustag, 348 ma->ma_iospace, 349 ma->ma_paddr, 350 1, /* probe size */ 351 0, /* offset */ 352 0, /* flags */ 353 NULL, NULL)); 354 } 355 356 int 357 fdcmatch_obio(parent, match, aux) 358 struct device *parent; 359 struct cfdata *match; 360 void *aux; 361 { 362 union obio_attach_args *uoba = aux; 363 struct sbus_attach_args *sa; 364 365 /* 366 * Floppy controller is on obio on sun4m. 367 */ 368 if (uoba->uoba_isobio4 != 0) 369 return (0); 370 371 sa = &uoba->uoba_sbus; 372 373 /* sun4m PROMs call the controller "SUNW,fdtwo" */ 374 if (strcmp("SUNW,fdtwo", sa->sa_name) != 0) 375 return (0); 376 377 return (bus_space_probe(sa->sa_bustag, sa->sa_slot, sa->sa_offset, 378 1, /* probe size */ 379 0, /* offset */ 380 0, /* flags */ 381 NULL, NULL)); 382 } 383 384 static void 385 establish_chip_type(fdc, tag, type, addr, size, handle) 386 struct fdc_softc *fdc; 387 bus_space_tag_t tag; 388 bus_type_t type; 389 bus_addr_t addr; 390 bus_size_t size; 391 bus_space_handle_t handle; 392 { 393 u_int8_t v; 394 395 /* 396 * This hack from Chris Torek: apparently DOR really 397 * addresses MSR/DRS on a 82072. 398 * We used to rely on the VERSION command to tell the 399 * difference (which did not work). 400 */ 401 402 /* First, check the size of the register bank */ 403 if (size < 8) 404 /* It isn't a 82077 */ 405 return; 406 407 /* Then probe the DOR register offset */ 408 if (bus_space_probe(tag, type, addr, 409 1, /* probe size */ 410 FDREG77_DOR, /* offset */ 411 0, /* flags */ 412 NULL, NULL) == 0) { 413 414 /* It isn't a 82077 */ 415 return; 416 } 417 418 v = bus_space_read_1(tag, handle, FDREG77_DOR); 419 if (v == NE7_RQM) { 420 /* 421 * Value in DOR looks like it's really MSR 422 */ 423 bus_space_write_1(tag, handle, FDREG77_DOR, FDC_250KBPS); 424 v = bus_space_read_1(tag, handle, FDREG77_DOR); 425 if (v == NE7_RQM) { 426 /* 427 * The value in the DOR didn't stick; 428 * it isn't a 82077 429 */ 430 return; 431 } 432 } 433 434 fdc->sc_flags |= FDC_82077; 435 } 436 437 /* 438 * Arguments passed between fdcattach and fdprobe. 439 */ 440 struct fdc_attach_args { 441 int fa_drive; 442 struct fd_type *fa_deftype; 443 }; 444 445 /* 446 * Print the location of a disk drive (called just before attaching the 447 * the drive). If `fdc' is not NULL, the drive was found but was not 448 * in the system config file; print the drive name as well. 449 * Return QUIET (config_find ignores this if the device was configured) to 450 * avoid printing `fdN not configured' messages. 451 */ 452 int 453 fdprint(aux, fdc) 454 void *aux; 455 const char *fdc; 456 { 457 register struct fdc_attach_args *fa = aux; 458 459 if (!fdc) 460 printf(" drive %d", fa->fa_drive); 461 return (QUIET); 462 } 463 464 /* 465 * Configure several parameters and features on the FDC. 466 * Return 0 on success. 467 */ 468 static int 469 fdconf(fdc) 470 struct fdc_softc *fdc; 471 { 472 int vroom; 473 474 if (fdc_wrfifo(fdc, NE7CMD_DUMPREG) || fdcresult(fdc) != 10) 475 return (-1); 476 477 /* 478 * dumpreg[7] seems to be a motor-off timeout; set it to whatever 479 * the PROM thinks is appropriate. 480 */ 481 if ((vroom = fdc->sc_status[7]) == 0) 482 vroom = 0x64; 483 484 /* Configure controller to use FIFO and Implied Seek */ 485 if (fdc_wrfifo(fdc, NE7CMD_CFG) != 0) 486 return (-1); 487 if (fdc_wrfifo(fdc, vroom) != 0) 488 return (-1); 489 if (fdc_wrfifo(fdc, fdc->sc_cfg) != 0) 490 return (-1); 491 if (fdc_wrfifo(fdc, 0) != 0) /* PRETRK */ 492 return (-1); 493 /* No result phase for the NE7CMD_CFG command */ 494 495 if ((fdc->sc_flags & FDC_82077) != 0) { 496 /* Lock configuration across soft resets. */ 497 if (fdc_wrfifo(fdc, NE7CMD_LOCK | CFG_LOCK) != 0 || 498 fdcresult(fdc) != 1) { 499 #ifdef DEBUG 500 printf("fdconf: CFGLOCK failed"); 501 #endif 502 return (-1); 503 } 504 } 505 506 return (0); 507 #if 0 508 if (fdc_wrfifo(fdc, NE7CMD_VERSION) == 0 && 509 fdcresult(fdc) == 1 && fdc->sc_status[0] == 0x90) { 510 if (fdc_debug) 511 printf("[version cmd]"); 512 } 513 #endif 514 } 515 516 void 517 fdcattach_mainbus(parent, self, aux) 518 struct device *parent, *self; 519 void *aux; 520 { 521 struct fdc_softc *fdc = (void *)self; 522 struct mainbus_attach_args *ma = aux; 523 524 fdc->sc_bustag = ma->ma_bustag; 525 526 if (bus_space_map2( 527 ma->ma_bustag, 528 ma->ma_iospace, 529 ma->ma_paddr, 530 ma->ma_size, 531 BUS_SPACE_MAP_LINEAR, 532 0, 533 &fdc->sc_handle) != 0) { 534 printf("%s: cannot map registers\n", self->dv_xname); 535 return; 536 } 537 538 establish_chip_type(fdc, 539 ma->ma_bustag, 540 ma->ma_iospace, 541 ma->ma_paddr, 542 ma->ma_size, 543 fdc->sc_handle); 544 545 if (fdcattach(fdc, ma->ma_pri) != 0) 546 bus_space_unmap(ma->ma_bustag, fdc->sc_handle, ma->ma_size); 547 } 548 549 void 550 fdcattach_obio(parent, self, aux) 551 struct device *parent, *self; 552 void *aux; 553 { 554 struct fdc_softc *fdc = (void *)self; 555 union obio_attach_args *uoba = aux; 556 struct sbus_attach_args *sa = &uoba->uoba_sbus; 557 558 if (sa->sa_nintr == 0) { 559 printf(": no interrupt line configured\n"); 560 return; 561 } 562 563 fdc->sc_bustag = sa->sa_bustag; 564 565 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 566 sa->sa_offset, 567 sa->sa_size, 568 BUS_SPACE_MAP_LINEAR, 569 0, 570 &fdc->sc_handle) != 0) { 571 printf("%s: cannot map control registers\n", 572 self->dv_xname); 573 return; 574 } 575 576 establish_chip_type(fdc, 577 sa->sa_bustag, 578 sa->sa_slot, 579 sa->sa_offset, 580 sa->sa_size, 581 fdc->sc_handle); 582 583 if (strcmp(PROM_getpropstring(sa->sa_node, "status"), "disabled") == 0) { 584 printf(": no drives attached\n"); 585 return; 586 } 587 588 if (fdcattach(fdc, sa->sa_pri) != 0) 589 bus_space_unmap(sa->sa_bustag, fdc->sc_handle, sa->sa_size); 590 } 591 592 int 593 fdcattach(fdc, pri) 594 struct fdc_softc *fdc; 595 int pri; 596 { 597 struct fdc_attach_args fa; 598 int drive_attached; 599 char code; 600 601 callout_init(&fdc->sc_timo_ch); 602 callout_init(&fdc->sc_intr_ch); 603 604 fdc->sc_state = DEVIDLE; 605 fdc->sc_itask = FDC_ITASK_NONE; 606 fdc->sc_istatus = FDC_ISTATUS_NONE; 607 fdc->sc_flags |= FDC_EIS; 608 TAILQ_INIT(&fdc->sc_drives); 609 610 if ((fdc->sc_flags & FDC_82077) != 0) { 611 fdc->sc_reg_msr = FDREG77_MSR; 612 fdc->sc_reg_fifo = FDREG77_FIFO; 613 fdc->sc_reg_dor = FDREG77_DOR; 614 code = '7'; 615 fdc->sc_flags |= FDC_NEEDMOTORWAIT; 616 } else { 617 fdc->sc_reg_msr = FDREG72_MSR; 618 fdc->sc_reg_fifo = FDREG72_FIFO; 619 fdc->sc_reg_dor = 0; 620 code = '2'; 621 } 622 623 printf(" softpri %d: chip 8207%c\n", PIL_FDSOFT, code); 624 625 /* 626 * Configure controller; enable FIFO, Implied seek, no POLL mode?. 627 * Note: CFG_EFIFO is active-low, initial threshold value: 8 628 */ 629 fdc->sc_cfg = CFG_EIS|/*CFG_EFIFO|*/CFG_POLL|(8 & CFG_THRHLD_MASK); 630 if (fdconf(fdc) != 0) { 631 printf("%s: no drives attached\n", fdc->sc_dev.dv_xname); 632 return (-1); 633 } 634 635 fdciop = &fdc->sc_io; 636 if (bus_intr_establish(fdc->sc_bustag, pri, IPL_BIO, 637 BUS_INTR_ESTABLISH_FASTTRAP, 638 (int (*) __P((void *)))fdchwintr, NULL) == NULL) { 639 640 printf("%s: notice: no fast trap handler slot available\n", 641 fdc->sc_dev.dv_xname); 642 if (bus_intr_establish(fdc->sc_bustag, pri, IPL_BIO, 0, 643 fdc_c_hwintr, fdc) == NULL) { 644 printf("%s: cannot register interrupt handler\n", 645 fdc->sc_dev.dv_xname); 646 return (-1); 647 } 648 } 649 650 if (bus_intr_establish(fdc->sc_bustag, PIL_FDSOFT, IPL_BIO, 651 BUS_INTR_ESTABLISH_SOFTINTR, 652 fdcswintr, fdc) == NULL) { 653 printf("%s: cannot register interrupt handler\n", 654 fdc->sc_dev.dv_xname); 655 return (-1); 656 } 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 /* 1297 * hardware interrupt entry point: used only if no `fast trap' * (in-window) 1298 * handler is available. Unfortunately, we have no reliable way to 1299 * determine that the interrupt really came from the floppy controller; 1300 * just hope that the other devices that share this interrupt level 1301 * can do better.. 1302 */ 1303 int 1304 fdc_c_hwintr(arg) 1305 void *arg; 1306 { 1307 struct fdc_softc *fdc = arg; 1308 bus_space_tag_t t = fdc->sc_bustag; 1309 bus_space_handle_t h = fdc->sc_handle; 1310 1311 switch (fdc->sc_itask) { 1312 case FDC_ITASK_NONE: 1313 return (0); 1314 case FDC_ITASK_SENSEI: 1315 if (fdc_wrfifo(fdc, NE7CMD_SENSEI) != 0 || fdcresult(fdc) == -1) 1316 fdc->sc_istatus = FDC_ISTATUS_ERROR; 1317 else 1318 fdc->sc_istatus = FDC_ISTATUS_DONE; 1319 FD_SET_SWINTR; 1320 return (1); 1321 case FDC_ITASK_DMA: 1322 /* Proceed with pseudo-dma below */ 1323 break; 1324 default: 1325 printf("fdc: stray hard interrupt: itask=%d\n", fdc->sc_itask); 1326 fdc->sc_istatus = FDC_ISTATUS_SPURIOUS; 1327 FD_SET_SWINTR; 1328 return (1); 1329 } 1330 1331 /* 1332 * Pseudo DMA in progress 1333 */ 1334 for (;;) { 1335 u_int8_t msr; 1336 1337 msr = bus_space_read_1(t, h, fdc->sc_reg_msr); 1338 1339 if ((msr & NE7_RQM) == 0) 1340 /* That's all this round */ 1341 break; 1342 1343 if ((msr & NE7_NDM) == 0) { 1344 fdcresult(fdc); 1345 fdc->sc_istatus = FDC_ISTATUS_DONE; 1346 FD_SET_SWINTR; 1347 #ifdef FD_DEBUG 1348 if (fdc_debug > 1) 1349 printf("fdc: overrun: tc = %d\n", fdc->sc_tc); 1350 #endif 1351 break; 1352 } 1353 1354 /* Another byte can be transferred */ 1355 if ((msr & NE7_DIO) != 0) 1356 *fdc->sc_data = 1357 bus_space_read_1(t, h, fdc->sc_reg_fifo); 1358 else 1359 bus_space_write_1(t, h, fdc->sc_reg_fifo, 1360 *fdc->sc_data); 1361 1362 fdc->sc_data++; 1363 if (--fdc->sc_tc == 0) { 1364 fdc->sc_istatus = FDC_ISTATUS_DONE; 1365 FTC_FLIP; 1366 fdcresult(fdc); 1367 FD_SET_SWINTR; 1368 break; 1369 } 1370 } 1371 return (1); 1372 } 1373 1374 int 1375 fdcswintr(arg) 1376 void *arg; 1377 { 1378 struct fdc_softc *fdc = arg; 1379 int s; 1380 1381 if (fdc->sc_istatus == FDC_ISTATUS_NONE) 1382 /* This (software) interrupt is not for us */ 1383 return (0); 1384 1385 switch (fdc->sc_istatus) { 1386 case FDC_ISTATUS_ERROR: 1387 printf("fdc: ierror status: state %d\n", fdc->sc_state); 1388 break; 1389 case FDC_ISTATUS_SPURIOUS: 1390 printf("fdc: spurious interrupt: state %d\n", fdc->sc_state); 1391 break; 1392 } 1393 1394 s = splbio(); 1395 fdcstate(fdc); 1396 splx(s); 1397 return (1); 1398 } 1399 1400 int 1401 fdcstate(fdc) 1402 struct fdc_softc *fdc; 1403 { 1404 #define st0 fdc->sc_status[0] 1405 #define st1 fdc->sc_status[1] 1406 #define cyl fdc->sc_status[1] 1407 #define FDC_WRFIFO(fdc, c) do { \ 1408 if (fdc_wrfifo(fdc, (c))) { \ 1409 goto xxx; \ 1410 } \ 1411 } while(0) 1412 1413 struct fd_softc *fd; 1414 struct buf *bp; 1415 int read, head, sec, nblks; 1416 struct fd_type *type; 1417 struct ne7_fd_formb *finfo = NULL; 1418 1419 if (fdc->sc_istatus == FDC_ISTATUS_ERROR) { 1420 /* Prevent loop if the reset sequence produces errors */ 1421 if (fdc->sc_state != RESETCOMPLETE && 1422 fdc->sc_state != RECALWAIT && 1423 fdc->sc_state != RECALCOMPLETE) 1424 fdc->sc_state = DORESET; 1425 } 1426 1427 /* Clear I task/status field */ 1428 fdc->sc_istatus = FDC_ISTATUS_NONE; 1429 fdc->sc_itask = FDC_ITASK_NONE; 1430 1431 loop: 1432 /* Is there a drive for the controller to do a transfer with? */ 1433 fd = fdc->sc_drives.tqh_first; 1434 if (fd == NULL) { 1435 fdc->sc_state = DEVIDLE; 1436 return (0); 1437 } 1438 1439 /* Is there a transfer to this drive? If not, deactivate drive. */ 1440 bp = BUFQ_FIRST(&fd->sc_q); 1441 if (bp == NULL) { 1442 fd->sc_ops = 0; 1443 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); 1444 fd->sc_active = 0; 1445 goto loop; 1446 } 1447 1448 if (bp->b_flags & B_FORMAT) 1449 finfo = (struct ne7_fd_formb *)bp->b_data; 1450 1451 switch (fdc->sc_state) { 1452 case DEVIDLE: 1453 fdc->sc_errors = 0; 1454 fd->sc_skip = 0; 1455 fd->sc_bcount = bp->b_bcount; 1456 fd->sc_blkno = (bp->b_blkno * DEV_BSIZE) / FD_BSIZE(fd); 1457 callout_stop(&fd->sc_motoroff_ch); 1458 if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) { 1459 fdc->sc_state = MOTORWAIT; 1460 return (1); 1461 } 1462 if ((fd->sc_flags & FD_MOTOR) == 0) { 1463 /* Turn on the motor, being careful about pairing. */ 1464 struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1]; 1465 if (ofd && ofd->sc_flags & FD_MOTOR) { 1466 callout_stop(&ofd->sc_motoroff_ch); 1467 ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); 1468 } 1469 fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT; 1470 fd_set_motor(fdc); 1471 fdc->sc_state = MOTORWAIT; 1472 if ((fdc->sc_flags & FDC_NEEDMOTORWAIT) != 0) { /*XXX*/ 1473 /* Allow .25s for motor to stabilize. */ 1474 callout_reset(&fd->sc_motoron_ch, hz / 4, 1475 fd_motor_on, fd); 1476 } else { 1477 fd->sc_flags &= ~FD_MOTOR_WAIT; 1478 goto loop; 1479 } 1480 return (1); 1481 } 1482 /* Make sure the right drive is selected. */ 1483 fd_set_motor(fdc); 1484 1485 /*FALLTHROUGH*/ 1486 case DOSEEK: 1487 doseek: 1488 if ((fdc->sc_flags & FDC_EIS) && 1489 (bp->b_flags & B_FORMAT) == 0) { 1490 fd->sc_cylin = bp->b_cylinder; 1491 /* We use implied seek */ 1492 goto doio; 1493 } 1494 1495 if (fd->sc_cylin == bp->b_cylinder) 1496 goto doio; 1497 1498 fd->sc_cylin = -1; 1499 fdc->sc_state = SEEKWAIT; 1500 fdc->sc_nstat = 0; 1501 1502 fd->sc_dk.dk_seek++; 1503 1504 disk_busy(&fd->sc_dk); 1505 callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc); 1506 1507 /* specify command */ 1508 FDC_WRFIFO(fdc, NE7CMD_SPECIFY); 1509 FDC_WRFIFO(fdc, fd->sc_type->steprate); 1510 /* XXX head load time == 6ms */ 1511 FDC_WRFIFO(fdc, 6 | NE7_SPECIFY_NODMA); 1512 1513 fdc->sc_itask = FDC_ITASK_SENSEI; 1514 /* seek function */ 1515 FDC_WRFIFO(fdc, NE7CMD_SEEK); 1516 FDC_WRFIFO(fdc, fd->sc_drive); /* drive number */ 1517 FDC_WRFIFO(fdc, bp->b_cylinder * fd->sc_type->step); 1518 return (1); 1519 1520 case DOIO: 1521 doio: 1522 if (finfo != NULL) 1523 fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) - 1524 (char *)finfo; 1525 type = fd->sc_type; 1526 sec = fd->sc_blkno % type->seccyl; 1527 nblks = type->seccyl - sec; 1528 nblks = min(nblks, fd->sc_bcount / FD_BSIZE(fd)); 1529 nblks = min(nblks, FDC_MAXIOSIZE / FD_BSIZE(fd)); 1530 fd->sc_nblks = nblks; 1531 fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FD_BSIZE(fd); 1532 head = sec / type->sectrac; 1533 sec -= head * type->sectrac; 1534 #ifdef DIAGNOSTIC 1535 {int block; 1536 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec; 1537 if (block != fd->sc_blkno) { 1538 printf("fdcintr: block %d != blkno %d\n", block, fd->sc_blkno); 1539 #ifdef DDB 1540 Debugger(); 1541 #endif 1542 }} 1543 #endif 1544 read = bp->b_flags & B_READ; 1545 1546 /* Setup for pseudo DMA */ 1547 fdc->sc_data = bp->b_data + fd->sc_skip; 1548 fdc->sc_tc = fd->sc_nbytes; 1549 1550 bus_space_write_1(fdc->sc_bustag, fdc->sc_handle, 1551 fdc->sc_reg_drs, type->rate); 1552 #ifdef FD_DEBUG 1553 if (fdc_debug > 1) 1554 printf("fdcstate: doio: %s drive %d " 1555 "track %d head %d sec %d nblks %d\n", 1556 finfo ? "format" : 1557 (read ? "read" : "write"), 1558 fd->sc_drive, fd->sc_cylin, head, sec, nblks); 1559 #endif 1560 fdc->sc_state = IOCOMPLETE; 1561 fdc->sc_itask = FDC_ITASK_DMA; 1562 fdc->sc_nstat = 0; 1563 1564 disk_busy(&fd->sc_dk); 1565 1566 /* allow 3 seconds for operation */ 1567 callout_reset(&fdc->sc_timo_ch, 3 * hz, fdctimeout, fdc); 1568 1569 if (finfo != NULL) { 1570 /* formatting */ 1571 FDC_WRFIFO(fdc, NE7CMD_FORMAT); 1572 FDC_WRFIFO(fdc, (head << 2) | fd->sc_drive); 1573 FDC_WRFIFO(fdc, finfo->fd_formb_secshift); 1574 FDC_WRFIFO(fdc, finfo->fd_formb_nsecs); 1575 FDC_WRFIFO(fdc, finfo->fd_formb_gaplen); 1576 FDC_WRFIFO(fdc, finfo->fd_formb_fillbyte); 1577 } else { 1578 if (read) 1579 FDC_WRFIFO(fdc, NE7CMD_READ); 1580 else 1581 FDC_WRFIFO(fdc, NE7CMD_WRITE); 1582 FDC_WRFIFO(fdc, (head << 2) | fd->sc_drive); 1583 FDC_WRFIFO(fdc, fd->sc_cylin); /*track*/ 1584 FDC_WRFIFO(fdc, head); 1585 FDC_WRFIFO(fdc, sec + 1); /*sector+1*/ 1586 FDC_WRFIFO(fdc, type->secsize);/*sector size*/ 1587 FDC_WRFIFO(fdc, type->sectrac);/*secs/track*/ 1588 FDC_WRFIFO(fdc, type->gap1); /*gap1 size*/ 1589 FDC_WRFIFO(fdc, type->datalen);/*data length*/ 1590 } 1591 1592 return (1); /* will return later */ 1593 1594 case SEEKWAIT: 1595 callout_stop(&fdc->sc_timo_ch); 1596 fdc->sc_state = SEEKCOMPLETE; 1597 if (fdc->sc_flags & FDC_NEEDHEADSETTLE) { 1598 /* allow 1/50 second for heads to settle */ 1599 callout_reset(&fdc->sc_intr_ch, hz / 50, 1600 fdcpseudointr, fdc); 1601 return (1); /* will return later */ 1602 } 1603 /*FALLTHROUGH*/ 1604 case SEEKCOMPLETE: 1605 disk_unbusy(&fd->sc_dk, 0); /* no data on seek */ 1606 1607 /* Make sure seek really happened. */ 1608 if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 || 1609 cyl != bp->b_cylinder * fd->sc_type->step) { 1610 #ifdef FD_DEBUG 1611 if (fdc_debug) 1612 fdcstatus(fdc, "seek failed"); 1613 #endif 1614 fdcretry(fdc); 1615 goto loop; 1616 } 1617 fd->sc_cylin = bp->b_cylinder; 1618 goto doio; 1619 1620 case IOTIMEDOUT: 1621 /* 1622 * Try to abort the I/O operation without resetting 1623 * the chip first. Poke TC and arrange to pick up 1624 * the timed out I/O command's status. 1625 */ 1626 fdc->sc_itask = FDC_ITASK_RESULT; 1627 fdc->sc_state = IOCLEANUPWAIT; 1628 fdc->sc_nstat = 0; 1629 /* 1/10 second should be enough */ 1630 callout_reset(&fdc->sc_timo_ch, hz / 10, fdctimeout, fdc); 1631 FTC_FLIP; 1632 return (1); 1633 1634 case IOCLEANUPTIMEDOUT: 1635 case SEEKTIMEDOUT: 1636 case RECALTIMEDOUT: 1637 case RESETTIMEDOUT: 1638 fdcstatus(fdc, "timeout"); 1639 1640 /* All other timeouts always roll through to a chip reset */ 1641 fdcretry(fdc); 1642 1643 /* Force reset, no matter what fdcretry() says */ 1644 fdc->sc_state = DORESET; 1645 goto loop; 1646 1647 case IOCLEANUPWAIT: /* IO FAILED, cleanup succeeded */ 1648 callout_stop(&fdc->sc_timo_ch); 1649 disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid)); 1650 fdcretry(fdc); 1651 goto loop; 1652 1653 case IOCOMPLETE: /* IO DONE, post-analyze */ 1654 callout_stop(&fdc->sc_timo_ch); 1655 1656 disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid)); 1657 1658 if (fdc->sc_nstat != 7 || st1 != 0 || 1659 ((st0 & 0xf8) != 0 && 1660 ((st0 & 0xf8) != 0x20 || (fdc->sc_cfg & CFG_EIS) == 0))) { 1661 #ifdef FD_DEBUG 1662 if (fdc_debug) { 1663 fdcstatus(fdc, 1664 bp->b_flags & B_READ 1665 ? "read failed" : "write failed"); 1666 printf("blkno %d nblks %d nstat %d tc %d\n", 1667 fd->sc_blkno, fd->sc_nblks, 1668 fdc->sc_nstat, fdc->sc_tc); 1669 } 1670 #endif 1671 if (fdc->sc_nstat == 7 && 1672 (st1 & ST1_OVERRUN) == ST1_OVERRUN) { 1673 1674 /* 1675 * Silently retry overruns if no other 1676 * error bit is set. Adjust threshold. 1677 */ 1678 int thr = fdc->sc_cfg & CFG_THRHLD_MASK; 1679 if (thr < 15) { 1680 thr++; 1681 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 1682 fdc->sc_cfg |= (thr & CFG_THRHLD_MASK); 1683 #ifdef FD_DEBUG 1684 if (fdc_debug) 1685 printf("fdc: %d -> threshold\n", thr); 1686 #endif 1687 fdconf(fdc); 1688 fdc->sc_overruns = 0; 1689 } 1690 if (++fdc->sc_overruns < 3) { 1691 fdc->sc_state = DOIO; 1692 goto loop; 1693 } 1694 } 1695 fdcretry(fdc); 1696 goto loop; 1697 } 1698 if (fdc->sc_errors) { 1699 diskerr(bp, "fd", "soft error", LOG_PRINTF, 1700 fd->sc_skip / FD_BSIZE(fd), 1701 (struct disklabel *)NULL); 1702 printf("\n"); 1703 fdc->sc_errors = 0; 1704 } else { 1705 if (--fdc->sc_overruns < -20) { 1706 int thr = fdc->sc_cfg & CFG_THRHLD_MASK; 1707 if (thr > 0) { 1708 thr--; 1709 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 1710 fdc->sc_cfg |= (thr & CFG_THRHLD_MASK); 1711 #ifdef FD_DEBUG 1712 if (fdc_debug) 1713 printf("fdc: %d -> threshold\n", thr); 1714 #endif 1715 fdconf(fdc); 1716 } 1717 fdc->sc_overruns = 0; 1718 } 1719 } 1720 fd->sc_blkno += fd->sc_nblks; 1721 fd->sc_skip += fd->sc_nbytes; 1722 fd->sc_bcount -= fd->sc_nbytes; 1723 if (finfo == NULL && fd->sc_bcount > 0) { 1724 bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl; 1725 goto doseek; 1726 } 1727 fdfinish(fd, bp); 1728 goto loop; 1729 1730 case DORESET: 1731 /* try a reset, keep motor on */ 1732 fd_set_motor(fdc); 1733 delay(100); 1734 fdc->sc_nstat = 0; 1735 fdc->sc_itask = FDC_ITASK_SENSEI; 1736 fdc->sc_state = RESETCOMPLETE; 1737 callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc); 1738 fdc_reset(fdc); 1739 return (1); /* will return later */ 1740 1741 case RESETCOMPLETE: 1742 callout_stop(&fdc->sc_timo_ch); 1743 fdconf(fdc); 1744 1745 /* FALLTHROUGH */ 1746 case DORECAL: 1747 fdc->sc_state = RECALWAIT; 1748 fdc->sc_itask = FDC_ITASK_SENSEI; 1749 fdc->sc_nstat = 0; 1750 callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc); 1751 /* recalibrate function */ 1752 FDC_WRFIFO(fdc, NE7CMD_RECAL); 1753 FDC_WRFIFO(fdc, fd->sc_drive); 1754 return (1); /* will return later */ 1755 1756 case RECALWAIT: 1757 callout_stop(&fdc->sc_timo_ch); 1758 fdc->sc_state = RECALCOMPLETE; 1759 if (fdc->sc_flags & FDC_NEEDHEADSETTLE) { 1760 /* allow 1/30 second for heads to settle */ 1761 callout_reset(&fdc->sc_intr_ch, hz / 30, 1762 fdcpseudointr, fdc); 1763 return (1); /* will return later */ 1764 } 1765 1766 case RECALCOMPLETE: 1767 if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) { 1768 #ifdef FD_DEBUG 1769 if (fdc_debug) 1770 fdcstatus(fdc, "recalibrate failed"); 1771 #endif 1772 fdcretry(fdc); 1773 goto loop; 1774 } 1775 fd->sc_cylin = 0; 1776 goto doseek; 1777 1778 case MOTORWAIT: 1779 if (fd->sc_flags & FD_MOTOR_WAIT) 1780 return (1); /* time's not up yet */ 1781 goto doseek; 1782 1783 default: 1784 fdcstatus(fdc, "stray interrupt"); 1785 return (1); 1786 } 1787 #ifdef DIAGNOSTIC 1788 panic("fdcintr: impossible"); 1789 #endif 1790 1791 xxx: 1792 /* 1793 * We get here if the chip locks up in FDC_WRFIFO() 1794 * Cancel any operation and schedule a reset 1795 */ 1796 callout_stop(&fdc->sc_timo_ch); 1797 fdcretry(fdc); 1798 (fdc)->sc_state = DORESET; 1799 goto loop; 1800 1801 #undef st0 1802 #undef st1 1803 #undef cyl 1804 } 1805 1806 void 1807 fdcretry(fdc) 1808 struct fdc_softc *fdc; 1809 { 1810 struct fd_softc *fd; 1811 struct buf *bp; 1812 int error = EIO; 1813 1814 fd = fdc->sc_drives.tqh_first; 1815 bp = BUFQ_FIRST(&fd->sc_q); 1816 1817 fdc->sc_overruns = 0; 1818 if (fd->sc_opts & FDOPT_NORETRY) 1819 goto fail; 1820 1821 switch (fdc->sc_errors) { 1822 case 0: 1823 if (fdc->sc_nstat == 7 && 1824 (fdc->sc_status[0] & 0xd8) == 0x40 && 1825 (fdc->sc_status[1] & 0x2) == 0x2) { 1826 printf("%s: read-only medium\n", fd->sc_dv.dv_xname); 1827 error = EROFS; 1828 goto failsilent; 1829 } 1830 /* try again */ 1831 fdc->sc_state = 1832 (fdc->sc_flags & FDC_EIS) ? DOIO : DOSEEK; 1833 break; 1834 1835 case 1: case 2: case 3: 1836 /* didn't work; try recalibrating */ 1837 fdc->sc_state = DORECAL; 1838 break; 1839 1840 case 4: 1841 if (fdc->sc_nstat == 7 && 1842 fdc->sc_status[0] == 0 && 1843 fdc->sc_status[1] == 0 && 1844 fdc->sc_status[2] == 0) { 1845 /* 1846 * We've retried a few times and we've got 1847 * valid status and all three status bytes 1848 * are zero. Assume this condition is the 1849 * result of no disk loaded into the drive. 1850 */ 1851 printf("%s: no medium?\n", fd->sc_dv.dv_xname); 1852 error = ENODEV; 1853 goto failsilent; 1854 } 1855 1856 /* still no go; reset the bastard */ 1857 fdc->sc_state = DORESET; 1858 break; 1859 1860 default: 1861 fail: 1862 if ((fd->sc_opts & FDOPT_SILENT) == 0) { 1863 diskerr(bp, "fd", "hard error", LOG_PRINTF, 1864 fd->sc_skip / FD_BSIZE(fd), 1865 (struct disklabel *)NULL); 1866 printf("\n"); 1867 fdcstatus(fdc, "controller status"); 1868 } 1869 1870 failsilent: 1871 bp->b_flags |= B_ERROR; 1872 bp->b_error = error; 1873 fdfinish(fd, bp); 1874 } 1875 fdc->sc_errors++; 1876 } 1877 1878 int 1879 fdsize(dev) 1880 dev_t dev; 1881 { 1882 1883 /* Swapping to floppies would not make sense. */ 1884 return (-1); 1885 } 1886 1887 int 1888 fddump(dev, blkno, va, size) 1889 dev_t dev; 1890 daddr_t blkno; 1891 caddr_t va; 1892 size_t size; 1893 { 1894 1895 /* Not implemented. */ 1896 return (EINVAL); 1897 } 1898 1899 int 1900 fdioctl(dev, cmd, addr, flag, p) 1901 dev_t dev; 1902 u_long cmd; 1903 caddr_t addr; 1904 int flag; 1905 struct proc *p; 1906 { 1907 struct fd_softc *fd; 1908 struct fdc_softc *fdc; 1909 struct fdformat_parms *form_parms; 1910 struct fdformat_cmd *form_cmd; 1911 struct ne7_fd_formb *fd_formb; 1912 int il[FD_MAX_NSEC + 1]; 1913 int unit; 1914 int i, j; 1915 int error; 1916 1917 unit = FDUNIT(dev); 1918 if (unit >= fd_cd.cd_ndevs) 1919 return (ENXIO); 1920 1921 fd = fd_cd.cd_devs[FDUNIT(dev)]; 1922 fdc = (struct fdc_softc *)fd->sc_dv.dv_parent; 1923 1924 switch (cmd) { 1925 case DIOCGDINFO: 1926 *(struct disklabel *)addr = *(fd->sc_dk.dk_label); 1927 return 0; 1928 1929 case DIOCWLABEL: 1930 if ((flag & FWRITE) == 0) 1931 return EBADF; 1932 /* XXX do something */ 1933 return (0); 1934 1935 case DIOCWDINFO: 1936 if ((flag & FWRITE) == 0) 1937 return (EBADF); 1938 1939 error = setdisklabel(fd->sc_dk.dk_label, 1940 (struct disklabel *)addr, 0, 1941 fd->sc_dk.dk_cpulabel); 1942 if (error) 1943 return (error); 1944 1945 error = writedisklabel(dev, fdstrategy, 1946 fd->sc_dk.dk_label, 1947 fd->sc_dk.dk_cpulabel); 1948 return (error); 1949 1950 case DIOCLOCK: 1951 /* 1952 * Nothing to do here, really. 1953 */ 1954 return (0); 1955 1956 case DIOCEJECT: 1957 if (*(int *)addr == 0) { 1958 int part = DISKPART(dev); 1959 /* 1960 * Don't force eject: check that we are the only 1961 * partition open. If so, unlock it. 1962 */ 1963 if ((fd->sc_dk.dk_openmask & ~(1 << part)) != 0 || 1964 fd->sc_dk.dk_bopenmask + fd->sc_dk.dk_copenmask != 1965 fd->sc_dk.dk_openmask) { 1966 return (EBUSY); 1967 } 1968 } 1969 /* FALLTHROUGH */ 1970 case ODIOCEJECT: 1971 fd_do_eject(fd); 1972 return (0); 1973 1974 case FDIOCGETFORMAT: 1975 form_parms = (struct fdformat_parms *)addr; 1976 form_parms->fdformat_version = FDFORMAT_VERSION; 1977 form_parms->nbps = 128 * (1 << fd->sc_type->secsize); 1978 form_parms->ncyl = fd->sc_type->cylinders; 1979 form_parms->nspt = fd->sc_type->sectrac; 1980 form_parms->ntrk = fd->sc_type->heads; 1981 form_parms->stepspercyl = fd->sc_type->step; 1982 form_parms->gaplen = fd->sc_type->gap2; 1983 form_parms->fillbyte = fd->sc_type->fillbyte; 1984 form_parms->interleave = fd->sc_type->interleave; 1985 switch (fd->sc_type->rate) { 1986 case FDC_500KBPS: 1987 form_parms->xfer_rate = 500 * 1024; 1988 break; 1989 case FDC_300KBPS: 1990 form_parms->xfer_rate = 300 * 1024; 1991 break; 1992 case FDC_250KBPS: 1993 form_parms->xfer_rate = 250 * 1024; 1994 break; 1995 default: 1996 return (EINVAL); 1997 } 1998 return (0); 1999 2000 case FDIOCSETFORMAT: 2001 if ((flag & FWRITE) == 0) 2002 return (EBADF); /* must be opened for writing */ 2003 2004 form_parms = (struct fdformat_parms *)addr; 2005 if (form_parms->fdformat_version != FDFORMAT_VERSION) 2006 return (EINVAL);/* wrong version of formatting prog */ 2007 2008 i = form_parms->nbps >> 7; 2009 if ((form_parms->nbps & 0x7f) || ffs(i) == 0 || 2010 i & ~(1 << (ffs(i)-1))) 2011 /* not a power-of-two multiple of 128 */ 2012 return (EINVAL); 2013 2014 switch (form_parms->xfer_rate) { 2015 case 500 * 1024: 2016 fd->sc_type->rate = FDC_500KBPS; 2017 break; 2018 case 300 * 1024: 2019 fd->sc_type->rate = FDC_300KBPS; 2020 break; 2021 case 250 * 1024: 2022 fd->sc_type->rate = FDC_250KBPS; 2023 break; 2024 default: 2025 return (EINVAL); 2026 } 2027 2028 if (form_parms->nspt > FD_MAX_NSEC || 2029 form_parms->fillbyte > 0xff || 2030 form_parms->interleave > 0xff) 2031 return EINVAL; 2032 fd->sc_type->sectrac = form_parms->nspt; 2033 if (form_parms->ntrk != 2 && form_parms->ntrk != 1) 2034 return EINVAL; 2035 fd->sc_type->heads = form_parms->ntrk; 2036 fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk; 2037 fd->sc_type->secsize = ffs(i)-1; 2038 fd->sc_type->gap2 = form_parms->gaplen; 2039 fd->sc_type->cylinders = form_parms->ncyl; 2040 fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl * 2041 form_parms->nbps / DEV_BSIZE; 2042 fd->sc_type->step = form_parms->stepspercyl; 2043 fd->sc_type->fillbyte = form_parms->fillbyte; 2044 fd->sc_type->interleave = form_parms->interleave; 2045 return (0); 2046 2047 case FDIOCFORMAT_TRACK: 2048 if((flag & FWRITE) == 0) 2049 /* must be opened for writing */ 2050 return (EBADF); 2051 form_cmd = (struct fdformat_cmd *)addr; 2052 if (form_cmd->formatcmd_version != FDFORMAT_VERSION) 2053 /* wrong version of formatting prog */ 2054 return (EINVAL); 2055 2056 if (form_cmd->head >= fd->sc_type->heads || 2057 form_cmd->cylinder >= fd->sc_type->cylinders) { 2058 return (EINVAL); 2059 } 2060 2061 fd_formb = malloc(sizeof(struct ne7_fd_formb), 2062 M_TEMP, M_NOWAIT); 2063 if (fd_formb == 0) 2064 return (ENOMEM); 2065 2066 fd_formb->head = form_cmd->head; 2067 fd_formb->cyl = form_cmd->cylinder; 2068 fd_formb->transfer_rate = fd->sc_type->rate; 2069 fd_formb->fd_formb_secshift = fd->sc_type->secsize; 2070 fd_formb->fd_formb_nsecs = fd->sc_type->sectrac; 2071 fd_formb->fd_formb_gaplen = fd->sc_type->gap2; 2072 fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte; 2073 2074 bzero(il, sizeof il); 2075 for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) { 2076 while (il[(j%fd_formb->fd_formb_nsecs) + 1]) 2077 j++; 2078 il[(j%fd_formb->fd_formb_nsecs) + 1] = i; 2079 j += fd->sc_type->interleave; 2080 } 2081 for (i = 0; i < fd_formb->fd_formb_nsecs; i++) { 2082 fd_formb->fd_formb_cylno(i) = form_cmd->cylinder; 2083 fd_formb->fd_formb_headno(i) = form_cmd->head; 2084 fd_formb->fd_formb_secno(i) = il[i+1]; 2085 fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize; 2086 } 2087 2088 error = fdformat(dev, fd_formb, p); 2089 free(fd_formb, M_TEMP); 2090 return error; 2091 2092 case FDIOCGETOPTS: /* get drive options */ 2093 *(int *)addr = fd->sc_opts; 2094 return (0); 2095 2096 case FDIOCSETOPTS: /* set drive options */ 2097 fd->sc_opts = *(int *)addr; 2098 return (0); 2099 2100 #ifdef FD_DEBUG 2101 case _IO('f', 100): 2102 fdc_wrfifo(fdc, NE7CMD_DUMPREG); 2103 fdcresult(fdc); 2104 printf("fdc: dumpreg(%d regs): <", fdc->sc_nstat); 2105 for (i = 0; i < fdc->sc_nstat; i++) 2106 printf(" 0x%x", fdc->sc_status[i]); 2107 printf(">\n"); 2108 return (0); 2109 2110 case _IOW('f', 101, int): 2111 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 2112 fdc->sc_cfg |= (*(int *)addr & CFG_THRHLD_MASK); 2113 fdconf(fdc); 2114 return (0); 2115 2116 case _IO('f', 102): 2117 fdc_wrfifo(fdc, NE7CMD_SENSEI); 2118 fdcresult(fdc); 2119 printf("fdc: sensei(%d regs): <", fdc->sc_nstat); 2120 for (i=0; i< fdc->sc_nstat; i++) 2121 printf(" 0x%x", fdc->sc_status[i]); 2122 printf(">\n"); 2123 return (0); 2124 #endif 2125 default: 2126 return (ENOTTY); 2127 } 2128 2129 #ifdef DIAGNOSTIC 2130 panic("fdioctl: impossible"); 2131 #endif 2132 } 2133 2134 int 2135 fdformat(dev, finfo, p) 2136 dev_t dev; 2137 struct ne7_fd_formb *finfo; 2138 struct proc *p; 2139 { 2140 int rv = 0, s; 2141 struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)]; 2142 struct fd_type *type = fd->sc_type; 2143 struct buf *bp; 2144 2145 /* set up a buffer header for fdstrategy() */ 2146 bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 2147 if (bp == 0) 2148 return (ENOBUFS); 2149 2150 memset((void *)bp, 0, sizeof(struct buf)); 2151 bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 2152 bp->b_proc = p; 2153 bp->b_dev = dev; 2154 2155 /* 2156 * Calculate a fake blkno, so fdstrategy() would initiate a 2157 * seek to the requested cylinder. 2158 */ 2159 bp->b_blkno = ((finfo->cyl * (type->sectrac * type->heads) 2160 + finfo->head * type->sectrac) * FD_BSIZE(fd)) 2161 / DEV_BSIZE; 2162 2163 bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 2164 bp->b_data = (caddr_t)finfo; 2165 2166 #ifdef FD_DEBUG 2167 if (fdc_debug) { 2168 int i; 2169 2170 printf("fdformat: blkno 0x%x count %ld\n", 2171 bp->b_blkno, bp->b_bcount); 2172 2173 printf("\tcyl:\t%d\n", finfo->cyl); 2174 printf("\thead:\t%d\n", finfo->head); 2175 printf("\tnsecs:\t%d\n", finfo->fd_formb_nsecs); 2176 printf("\tsshft:\t%d\n", finfo->fd_formb_secshift); 2177 printf("\tgaplen:\t%d\n", finfo->fd_formb_gaplen); 2178 printf("\ttrack data:"); 2179 for (i = 0; i < finfo->fd_formb_nsecs; i++) { 2180 printf(" [c%d h%d s%d]", 2181 finfo->fd_formb_cylno(i), 2182 finfo->fd_formb_headno(i), 2183 finfo->fd_formb_secno(i) ); 2184 if (finfo->fd_formb_secsize(i) != 2) 2185 printf("<sz:%d>", finfo->fd_formb_secsize(i)); 2186 } 2187 printf("\n"); 2188 } 2189 #endif 2190 2191 /* now do the format */ 2192 fdstrategy(bp); 2193 2194 /* ...and wait for it to complete */ 2195 s = splbio(); 2196 while (!(bp->b_flags & B_DONE)) { 2197 rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 2198 if (rv == EWOULDBLOCK) 2199 break; 2200 } 2201 splx(s); 2202 2203 if (rv == EWOULDBLOCK) { 2204 /* timed out */ 2205 rv = EIO; 2206 biodone(bp); 2207 } 2208 if (bp->b_flags & B_ERROR) { 2209 rv = bp->b_error; 2210 } 2211 free(bp, M_TEMP); 2212 return (rv); 2213 } 2214 2215 void 2216 fdgetdisklabel(dev) 2217 dev_t dev; 2218 { 2219 int unit = FDUNIT(dev), i; 2220 struct fd_softc *fd = fd_cd.cd_devs[unit]; 2221 struct disklabel *lp = fd->sc_dk.dk_label; 2222 struct cpu_disklabel *clp = fd->sc_dk.dk_cpulabel; 2223 2224 bzero(lp, sizeof(struct disklabel)); 2225 bzero(lp, sizeof(struct cpu_disklabel)); 2226 2227 lp->d_type = DTYPE_FLOPPY; 2228 lp->d_secsize = FD_BSIZE(fd); 2229 lp->d_secpercyl = fd->sc_type->seccyl; 2230 lp->d_nsectors = fd->sc_type->sectrac; 2231 lp->d_ncylinders = fd->sc_type->cylinders; 2232 lp->d_ntracks = fd->sc_type->heads; /* Go figure... */ 2233 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 2234 lp->d_rpm = 3600; /* XXX like it matters... */ 2235 2236 strncpy(lp->d_typename, "floppy", sizeof(lp->d_typename)); 2237 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 2238 lp->d_interleave = 1; 2239 2240 lp->d_partitions[RAW_PART].p_offset = 0; 2241 lp->d_partitions[RAW_PART].p_size = lp->d_secpercyl * lp->d_ncylinders; 2242 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 2243 lp->d_npartitions = RAW_PART + 1; 2244 2245 lp->d_magic = DISKMAGIC; 2246 lp->d_magic2 = DISKMAGIC; 2247 lp->d_checksum = dkcksum(lp); 2248 2249 /* 2250 * Call the generic disklabel extraction routine. If there's 2251 * not a label there, fake it. 2252 */ 2253 if (readdisklabel(dev, fdstrategy, lp, clp) != NULL) { 2254 strncpy(lp->d_packname, "default label", 2255 sizeof(lp->d_packname)); 2256 /* 2257 * Reset the partition info; it might have gotten 2258 * trashed in readdisklabel(). 2259 * 2260 * XXX Why do we have to do this? readdisklabel() 2261 * should be safe... 2262 */ 2263 for (i = 0; i < MAXPARTITIONS; ++i) { 2264 lp->d_partitions[i].p_offset = 0; 2265 if (i == RAW_PART) { 2266 lp->d_partitions[i].p_size = 2267 lp->d_secpercyl * lp->d_ncylinders; 2268 lp->d_partitions[i].p_fstype = FS_BSDFFS; 2269 } else { 2270 lp->d_partitions[i].p_size = 0; 2271 lp->d_partitions[i].p_fstype = FS_UNUSED; 2272 } 2273 } 2274 lp->d_npartitions = RAW_PART + 1; 2275 } 2276 } 2277 2278 void 2279 fd_do_eject(fd) 2280 struct fd_softc *fd; 2281 { 2282 struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent; 2283 2284 if (CPU_ISSUN4C) { 2285 auxregbisc(AUXIO4C_FDS, AUXIO4C_FEJ); 2286 delay(10); 2287 auxregbisc(AUXIO4C_FEJ, AUXIO4C_FDS); 2288 return; 2289 } 2290 if (CPU_ISSUN4M && (fdc->sc_flags & FDC_82077) != 0) { 2291 bus_space_tag_t t = fdc->sc_bustag; 2292 bus_space_handle_t h = fdc->sc_handle; 2293 u_int8_t dor = FDO_FRST | FDO_FDMAEN | FDO_MOEN(0); 2294 2295 bus_space_write_1(t, h, fdc->sc_reg_dor, dor | FDO_EJ); 2296 delay(10); 2297 bus_space_write_1(t, h, fdc->sc_reg_dor, FDO_FRST | FDO_DS); 2298 return; 2299 } 2300 } 2301 2302 #ifdef MEMORY_DISK_HOOKS 2303 int fd_read_md_image __P((size_t *, caddr_t *)); 2304 #endif 2305 2306 /* ARGSUSED */ 2307 void 2308 fd_mountroot_hook(dev) 2309 struct device *dev; 2310 { 2311 int c; 2312 2313 fd_do_eject((struct fd_softc *)dev); 2314 printf("Insert filesystem floppy and press return."); 2315 for (;;) { 2316 c = cngetc(); 2317 if ((c == '\r') || (c == '\n')) { 2318 printf("\n"); 2319 break; 2320 } 2321 } 2322 } 2323 2324 #ifdef MEMORY_DISK_HOOKS 2325 2326 #define FDMICROROOTSIZE ((2*18*80) << DEV_BSHIFT) 2327 2328 int 2329 fd_read_md_image(sizep, addrp) 2330 size_t *sizep; 2331 caddr_t *addrp; 2332 { 2333 struct buf buf, *bp = &buf; 2334 dev_t dev; 2335 off_t offset; 2336 caddr_t addr; 2337 2338 dev = makedev(54,0); /* XXX */ 2339 2340 MALLOC(addr, caddr_t, FDMICROROOTSIZE, M_DEVBUF, M_WAITOK); 2341 *addrp = addr; 2342 2343 if (fdopen(dev, 0, S_IFCHR, NULL)) 2344 panic("fd: mountroot: fdopen"); 2345 2346 offset = 0; 2347 2348 for (;;) { 2349 bp->b_dev = dev; 2350 bp->b_error = 0; 2351 bp->b_resid = 0; 2352 bp->b_proc = NULL; 2353 bp->b_flags = B_BUSY | B_PHYS | B_RAW | B_READ; 2354 bp->b_blkno = btodb(offset); 2355 bp->b_bcount = DEV_BSIZE; 2356 bp->b_data = addr; 2357 fdstrategy(bp); 2358 while ((bp->b_flags & B_DONE) == 0) { 2359 tsleep((caddr_t)bp, PRIBIO + 1, "physio", 0); 2360 } 2361 if (bp->b_error) 2362 panic("fd: mountroot: fdread error %d", bp->b_error); 2363 2364 if (bp->b_resid != 0) 2365 break; 2366 2367 addr += DEV_BSIZE; 2368 offset += DEV_BSIZE; 2369 if (offset + DEV_BSIZE > FDMICROROOTSIZE) 2370 break; 2371 } 2372 (void)fdclose(dev, 0, S_IFCHR, NULL); 2373 *sizep = offset; 2374 fd_do_eject(fd_cd.cd_devs[FDUNIT(dev)]); 2375 return (0); 2376 } 2377 #endif 2378