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