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