1 /* $NetBSD: fd.c,v 1.71 2009/09/26 16:07:51 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Don Ahn. 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. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)fd.c 7.4 (Berkeley) 5/25/91 35 */ 36 37 /*- 38 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. 39 * 40 * This code is derived from software contributed to Berkeley by 41 * Don Ahn. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the University of 54 * California, Berkeley and its contributors. 55 * 4. Neither the name of the University nor the names of its contributors 56 * may be used to endorse or promote products derived from this software 57 * without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 * 71 * @(#)fd.c 7.4 (Berkeley) 5/25/91 72 */ 73 74 #include <sys/cdefs.h> 75 __KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.71 2009/09/26 16:07:51 tsutsui Exp $"); 76 77 #include "opt_ddb.h" 78 79 #include <sys/param.h> 80 #include <sys/systm.h> 81 #include <sys/callout.h> 82 #include <sys/kernel.h> 83 #include <sys/file.h> 84 #include <sys/ioctl.h> 85 #include <sys/device.h> 86 #include <sys/disklabel.h> 87 #include <sys/disk.h> 88 #include <sys/fdio.h> 89 #include <sys/buf.h> 90 #include <sys/bufq.h> 91 #include <sys/malloc.h> 92 #include <sys/proc.h> 93 #include <sys/uio.h> 94 #include <sys/stat.h> 95 #include <sys/syslog.h> 96 #include <sys/queue.h> 97 #include <sys/conf.h> 98 99 #include <dev/cons.h> 100 101 #include <uvm/uvm_extern.h> 102 103 #include <machine/cpu.h> 104 #include <machine/autoconf.h> 105 106 #include <sun3/dev/fdreg.h> 107 #include <sun3/dev/fdvar.h> 108 109 #include "ioconf.h" 110 111 /* 112 * Print a complaint when no fd children were specified 113 * in the config file. Better than a link error... 114 * 115 * XXX: Some folks say this driver should be split in two, 116 * but that seems pointless with ONLY one type of child. 117 * (Thankfully, no 3/80 boxes have floppy tapes!:) 118 */ 119 #include "fdc.h" 120 #if NFD == 0 121 #error "fdc but no fd?" 122 #endif 123 124 #define FDUNIT(dev) (minor(dev) / 8) 125 #define FDTYPE(dev) (minor(dev) % 8) 126 127 /* (mis)use device use flag to identify format operation */ 128 #define B_FORMAT B_DEVPRIVATE 129 130 #ifdef FD_DEBUG 131 int fdc_debug = 0; 132 #endif 133 134 enum fdc_state { 135 DEVIDLE = 0, 136 MOTORWAIT, 137 DOSEEK, 138 SEEKWAIT, 139 SEEKTIMEDOUT, 140 SEEKCOMPLETE, 141 DOIO, 142 IOCOMPLETE, 143 IOTIMEDOUT, 144 DORESET, 145 RESETCOMPLETE, 146 RESETTIMEDOUT, 147 DORECAL, 148 RECALWAIT, 149 RECALTIMEDOUT, 150 RECALCOMPLETE, 151 }; 152 153 /* software state, per controller */ 154 struct fdc_softc { 155 device_t sc_dev; /* boilerplate */ 156 void * sc_reg; 157 158 struct callout sc_timo_ch; /* timeout callout */ 159 struct callout sc_intr_ch; /* pseudo-intr callout */ 160 161 struct fd_softc *sc_fd[4]; /* pointers to children */ 162 TAILQ_HEAD(drivehead, fd_softc) sc_drives; 163 enum fdc_state sc_state; 164 int sc_flags; 165 #define FDC_82077 0x01 166 #define FDC_NEEDHEADSETTLE 0x02 167 #define FDC_EIS 0x04 168 int sc_errors; /* number of retries so far */ 169 int sc_overruns; /* number of DMA overruns */ 170 int sc_cfg; /* current configuration */ 171 int sc_fcr; /* current image of floppy ctrlr reg. */ 172 struct fdcio sc_io; 173 #define sc_reg_msr sc_io.fdcio_reg_msr 174 #define sc_reg_fifo sc_io.fdcio_reg_fifo 175 #define sc_reg_fcr sc_io.fdcio_reg_fcr 176 #define sc_reg_fvr sc_io.fdcio_reg_fvr 177 #define sc_reg_drs sc_io.fdcio_reg_msr 178 #define sc_istate sc_io.fdcio_istate 179 #define sc_data sc_io.fdcio_data 180 #define sc_tc sc_io.fdcio_tc 181 #define sc_nstat sc_io.fdcio_nstat 182 #define sc_status sc_io.fdcio_status 183 #define sc_intrcnt sc_io.fdcio_intrcnt 184 void *sc_si; /* softintr cookie */ 185 }; 186 187 /* controller driver configuration */ 188 static int fdcmatch(device_t, cfdata_t, void *); 189 static void fdcattach(device_t, device_t, void *); 190 191 CFATTACH_DECL_NEW(fdc, sizeof(struct fdc_softc), 192 fdcmatch, fdcattach, NULL, NULL); 193 194 static inline struct fd_type *fd_dev_to_type(struct fd_softc *, dev_t); 195 196 /* 197 * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how 198 * we tell them apart. 199 */ 200 struct fd_type { 201 int sectrac; /* sectors per track */ 202 int heads; /* number of heads */ 203 int seccyl; /* sectors per cylinder */ 204 int secsize; /* size code for sectors */ 205 int datalen; /* data len when secsize = 0 */ 206 int steprate; /* step rate and head unload time */ 207 int gap1; /* gap len between sectors */ 208 int gap2; /* formatting gap */ 209 int tracks; /* total num of tracks */ 210 int size; /* size of disk in sectors */ 211 int step; /* steps per cylinder */ 212 int rate; /* transfer speed code */ 213 int fillbyte; /* format fill byte */ 214 int interleave; /* interleave factor (formatting) */ 215 const char *name; 216 }; 217 218 /* The order of entries in the following table is important -- BEWARE! */ 219 static struct fd_type fd_types[] = { 220 { 18, 2, 36, 2, 0xff, 0xcf, 0x18, 0x50, 80, 2880, 1, 221 FDC_500KBPS, 0xf6, 1, "1.44MB" }, /* 1.44MB diskette */ 222 { 15, 2, 30, 2, 0xff, 0xdf, 0x1b, 0x54, 80, 2400, 1, 223 FDC_500KBPS, 0xf6, 1, "1.2MB" }, /* 1.2 MB AT-diskettes */ 224 { 9, 2, 18, 2, 0xff, 0xdf, 0x23, 0x50, 40, 720, 2, 225 FDC_300KBPS, 0xf6, 1, "360KB/AT" }, /* 360kB in 1.2MB drive */ 226 { 9, 2, 18, 2, 0xff, 0xdf, 0x2a, 0x50, 40, 720, 1, 227 FDC_250KBPS, 0xf6, 1, "360KB/PC" }, /* 360kB PC diskettes */ 228 { 9, 2, 18, 2, 0xff, 0xdf, 0x2a, 0x50, 80, 1440, 1, 229 FDC_250KBPS, 0xf6, 1, "720KB" }, /* 3.5" 720kB diskette */ 230 { 9, 2, 18, 2, 0xff, 0xdf, 0x23, 0x50, 80, 1440, 1, 231 FDC_300KBPS, 0xf6, 1, "720KB/x" }, /* 720kB in 1.2MB drive */ 232 { 9, 2, 18, 2, 0xff, 0xdf, 0x2a, 0x50, 40, 720, 2, 233 FDC_250KBPS,0xf6,1, "360KB/x" }, /* 360kB in 720kB drive */ 234 }; 235 236 /* software state, per disk (with up to 4 disks per ctlr) */ 237 struct fd_softc { 238 device_t sc_dv; /* generic device info */ 239 struct disk sc_dk; /* generic disk info */ 240 241 struct fd_type *sc_deftype; /* default type descriptor */ 242 struct fd_type *sc_type; /* current type descriptor */ 243 244 struct callout sc_motoron_ch; 245 struct callout sc_motoroff_ch; 246 247 daddr_t sc_blkno; /* starting block number */ 248 int sc_bcount; /* byte count left */ 249 int sc_skip; /* bytes already transferred */ 250 int sc_nblks; /* number of blocks currently transferring */ 251 int sc_nbytes; /* number of bytes currently transferring */ 252 253 int sc_drive; /* physical unit number */ 254 int sc_flags; 255 #define FD_OPEN 0x01 /* it's open */ 256 #define FD_MOTOR 0x02 /* motor should be on */ 257 #define FD_MOTOR_WAIT 0x04 /* motor coming up */ 258 int sc_cylin; /* where we think the head is */ 259 int sc_opts; /* user-set options */ 260 261 TAILQ_ENTRY(fd_softc) sc_drivechain; 262 int sc_ops; /* I/O ops since last switch */ 263 struct bufq_state *sc_q;/* pending I/O requests */ 264 int sc_active; /* number of active I/O operations */ 265 }; 266 267 /* floppy driver configuration */ 268 static int fdmatch(device_t, cfdata_t, void *); 269 static void fdattach(device_t, device_t, void *); 270 271 CFATTACH_DECL_NEW(fd, sizeof(struct fd_softc), 272 fdmatch, fdattach, NULL, NULL); 273 274 dev_type_open(fdopen); 275 dev_type_close(fdclose); 276 dev_type_read(fdread); 277 dev_type_write(fdwrite); 278 dev_type_ioctl(fdioctl); 279 dev_type_strategy(fdstrategy); 280 281 const struct bdevsw fd_bdevsw = { 282 fdopen, fdclose, fdstrategy, fdioctl, nodump, nosize, D_DISK 283 }; 284 285 const struct cdevsw fd_cdevsw = { 286 fdopen, fdclose, fdread, fdwrite, fdioctl, 287 nostop, notty, nopoll, nommap, nokqfilter, D_DISK 288 }; 289 290 static bool fd_shutdown(device_t, int); 291 static void fdgetdisklabel(dev_t); 292 static void fdstart(struct fd_softc *); 293 static int fdprint(void *, const char *); 294 295 struct dkdriver fddkdriver = { fdstrategy }; 296 297 static void fd_set_motor(struct fdc_softc *); 298 static void fd_motor_off(void *); 299 static void fd_motor_on(void *); 300 static int fdcresult(struct fdc_softc *); 301 static int out_fdc(struct fdc_softc *, u_char); 302 static void fdcstart(struct fdc_softc *); 303 static void fdcstatus(device_t, int, const char *); 304 static void fdc_reset(struct fdc_softc *); 305 static void fdctimeout(void *); 306 static void fdcpseudointr(void *); 307 static int fdchwintr(void *); 308 static void fdcswintr(void *); 309 static int fdcstate(struct fdc_softc *); 310 static void fdcretry(struct fdc_softc *); 311 static void fdfinish(struct fd_softc *, struct buf *); 312 static int fdformat(dev_t, struct ne7_fd_formb *, struct proc *); 313 static void fd_do_eject(struct fdc_softc *, int); 314 static void fd_mountroot_hook(device_t); 315 static void fdconf(struct fdc_softc *); 316 317 #define IPL_SOFTFD IPL_BIO 318 #define FDC_SOFTPRI 2 319 #define FD_SET_SWINTR() softint_schedule(fdc->sc_si); 320 321 /* 322 * The Floppy Control Register on the sun3x, not to be confused with the 323 * Floppy ControllER Registers that this driver mostly insterfaces with, 324 * controls some of the auxillary functions of the floppy drive. These 325 * include asserting the floppy eject and terminal data count (or TC) pins 326 * of the floppy drive and controller chip respectively. 327 * 328 * Often it is necessary to toggle individual bits within this register 329 * while keeping the others untouched. However, the register does not 330 * present its latched data to the processor when read. This prevents the 331 * use of a read-modify-write cycle that would normally be used to modify 332 * individual bits. To get around this we must keep a copy of register's 333 * current value and always insure that when we wish to modify the register, 334 * we actually modify the copy and synchronize the register to it. 335 */ 336 #define FCR_REG_SYNC() (*fdc->sc_reg_fcr = fdc->sc_fcr) 337 338 int 339 fdcmatch(device_t parent, cfdata_t cf, void *aux) 340 { 341 struct confargs *ca = aux; 342 343 if (bus_peek(ca->ca_bustype, ca->ca_paddr, sizeof(uint8_t)) == -1) 344 return 0; 345 346 return 1; 347 } 348 349 /* 350 * Arguments passed between fdcattach and fdprobe. 351 */ 352 struct fdc_attach_args { 353 int fa_drive; 354 struct bootpath *fa_bootpath; 355 struct fd_type *fa_deftype; 356 }; 357 358 /* 359 * Print the location of a disk drive (called just before attaching the 360 * the drive). If `fdc' is not NULL, the drive was found but was not 361 * in the system config file; print the drive name as well. 362 * Return QUIET (config_find ignores this if the device was configured) to 363 * avoid printing `fdN not configured' messages. 364 */ 365 int 366 fdprint(void *aux, const char *fdc) 367 { 368 struct fdc_attach_args *fa = aux; 369 370 if (fdc == NULL) 371 aprint_normal(" drive %d", fa->fa_drive); 372 return QUIET; 373 } 374 375 static void 376 fdconf(struct fdc_softc *fdc) 377 { 378 int vroom; 379 380 if (out_fdc(fdc, NE7CMD_DUMPREG) || fdcresult(fdc) != 10) 381 return; 382 383 /* 384 * dumpreg[7] seems to be a motor-off timeout; set it to whatever 385 * the PROM thinks is appropriate. 386 */ 387 if ((vroom = fdc->sc_status[7]) == 0) 388 vroom = 0x64; 389 390 /* Configure controller to use FIFO and Implied Seek */ 391 out_fdc(fdc, NE7CMD_CFG); 392 out_fdc(fdc, vroom); 393 out_fdc(fdc, fdc->sc_cfg); 394 out_fdc(fdc, 0); /* PRETRK */ 395 /* No result phase */ 396 } 397 398 void 399 fdcattach(struct device *parent, struct device *self, void *aux) 400 { 401 struct confargs *ca = aux; 402 struct fdc_softc *fdc = device_private(self); 403 struct fdc_attach_args fa; 404 int pri, vec; 405 char code; 406 407 fdc->sc_dev = self; 408 409 fdc->sc_reg = (void *)bus_mapin(ca->ca_bustype, ca->ca_paddr, 410 sizeof(union fdreg)); 411 412 callout_init(&fdc->sc_timo_ch, 0); 413 callout_init(&fdc->sc_intr_ch, 0); 414 415 fdc->sc_state = DEVIDLE; 416 fdc->sc_istate = ISTATE_IDLE; 417 fdc->sc_flags |= FDC_EIS; 418 TAILQ_INIT(&fdc->sc_drives); 419 420 /* Assume a 82072 */ 421 code = '2'; 422 423 if (code == '7') { 424 panic("no 82077 fdc in this kernel"); 425 /* NOTREACHED */ 426 } else { 427 fdc->sc_reg_msr = &((struct fdreg_72 *)fdc->sc_reg)->fd_msr; 428 fdc->sc_reg_fifo = &((struct fdreg_72 *)fdc->sc_reg)->fd_fifo; 429 430 fdc->sc_reg_fcr = ((volatile uint8_t *)fdc->sc_reg) 431 + FDC_FCR_OFFSET; 432 fdc->sc_reg_fvr = ((volatile uint8_t *)fdc->sc_reg) 433 + FDC_FVR_OFFSET; 434 } 435 436 pri = ca->ca_intpri; 437 vec = ca->ca_intvec; 438 if (vec == -1) { 439 /* Tell the FDC to fake an autovector. */ 440 vec = 0x18 + pri; /* XXX */ 441 isr_add_autovect(fdchwintr, fdc, pri); 442 } else { 443 /* An OBIO bus with vectors? Weird exception. */ 444 isr_add_vectored(fdchwintr, fdc, pri, vec); 445 } 446 *fdc->sc_reg_fvr = vec; /* Program controller w/ interrupt vector */ 447 448 fdc->sc_si = softint_establish(SOFTINT_BIO, fdcswintr, fdc); 449 #if 0 450 aprint_normal(": (softpri %d) chip 8207%c\n", FDC_SOFTPRI, code); 451 #else 452 aprint_normal(": chip 8207%c\n", code); 453 #endif 454 455 #ifdef FD_DEBUG 456 if (out_fdc(fdc, NE7CMD_VERSION) == 0 && 457 fdcresult(fdc) == 1 && fdc->sc_status[0] == 0x90) { 458 if (fdc_debug) 459 aprint_debug("[version cmd]"); 460 } 461 #endif 462 463 fdc_reset(fdc); 464 /* 465 * Configure controller; enable FIFO, Implied seek, no POLL mode?. 466 * Note: CFG_EFIFO is active-low, initial threshold value: 8 467 */ 468 fdc->sc_cfg = CFG_EIS|/*CFG_EFIFO|*/CFG_POLL|(8 & CFG_THRHLD_MASK); 469 fdconf(fdc); 470 471 evcnt_attach_dynamic(&fdc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 472 device_xname(self), "intr"); 473 474 /* physical limit: four drives per controller. */ 475 for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) { 476 fa.fa_deftype = NULL; /* unknown */ 477 fa.fa_deftype = &fd_types[0]; /* XXX */ 478 (void)config_found(self, (void *)&fa, fdprint); 479 } 480 } 481 482 int 483 fdmatch(device_t parent, cfdata_t cf, void *aux) 484 { 485 struct fdc_softc *fdc = device_private(parent); 486 struct fdc_attach_args *fa = aux; 487 int drive = fa->fa_drive; 488 int n, ok; 489 490 if (drive > 0) 491 /* XXX - for now, punt > 1 drives */ 492 return 0; 493 494 /* select drive and turn on motor */ 495 fdc->sc_fcr |= FCR_DSEL(drive) | FCR_MTRON; 496 FCR_REG_SYNC(); 497 /* wait for motor to spin up */ 498 delay(250000); 499 500 fdc->sc_nstat = 0; 501 out_fdc(fdc, NE7CMD_RECAL); 502 out_fdc(fdc, drive); 503 /* wait for recalibrate */ 504 for (n = 0; n < 10000; n++) { 505 delay(1000); 506 if ((*fdc->sc_reg_msr & (NE7_RQM|NE7_DIO|NE7_CB)) == NE7_RQM) { 507 /* wait a bit longer till device *really* is ready */ 508 delay(100000); 509 if (out_fdc(fdc, NE7CMD_SENSEI)) 510 break; 511 if (fdcresult(fdc) == 1 && fdc->sc_status[0] == 0x80) 512 /* 513 * Got `invalid command'; we interpret it 514 * to mean that the re-calibrate hasn't in 515 * fact finished yet 516 */ 517 continue; 518 break; 519 } 520 } 521 n = fdc->sc_nstat; 522 #ifdef FD_DEBUG 523 if (fdc_debug) { 524 int i; 525 aprint_debug("%s: %d stati:", __func__, n); 526 for (i = 0; i < n; i++) 527 aprint_debug(" %x", fdc->sc_status[i]); 528 aprint_debug("\n"); 529 } 530 #endif 531 ok = (n == 2 && (fdc->sc_status[0] & 0xf8) == 0x20) ? 1 : 0; 532 533 /* turn off motor */ 534 fdc->sc_fcr &= ~(FCR_DSEL(drive)|FCR_MTRON); 535 FCR_REG_SYNC(); 536 537 return ok; 538 } 539 540 /* 541 * Controller is working, and drive responded. Attach it. 542 */ 543 void 544 fdattach(device_t parent, device_t self, void *aux) 545 { 546 struct fdc_softc *fdc = device_private(parent); 547 struct fd_softc *fd = device_private(self); 548 struct fdc_attach_args *fa = aux; 549 struct fd_type *type = fa->fa_deftype; 550 int drive = fa->fa_drive; 551 552 fd->sc_dv = self; 553 554 callout_init(&fd->sc_motoron_ch, 0); 555 callout_init(&fd->sc_motoroff_ch, 0); 556 557 /* XXX Allow `flags' to override device type? */ 558 559 if (type) 560 aprint_normal(": %s %d cyl, %d head, %d sec\n", type->name, 561 type->tracks, type->heads, type->sectrac); 562 else 563 aprint_normal(": density unknown\n"); 564 565 bufq_alloc(&fd->sc_q, "disksort", BUFQ_SORT_CYLINDER); 566 fd->sc_cylin = -1; 567 fd->sc_drive = drive; 568 fd->sc_deftype = type; 569 fdc->sc_fd[drive] = fd; 570 571 /* 572 * Initialize and attach the disk structure. 573 */ 574 disk_init(&fd->sc_dk, device_xname(self), &fddkdriver); 575 disk_attach(&fd->sc_dk); 576 577 #ifdef sparc 578 /* 579 * We're told if we're the boot device in fdcattach(). 580 */ 581 if (fa->fa_bootpath) 582 fa->fa_bootpath->dev = self; 583 #endif 584 #define OUT_FDC(sc, c) do { \ 585 if (out_fdc((sc), (c)) != 0) \ 586 printf("fdc: specify command failed.\n"); \ 587 } while (/* CONSTCOND */ 0) 588 589 /* specify command */ 590 OUT_FDC(fdc, NE7CMD_SPECIFY); 591 OUT_FDC(fdc, type->steprate); 592 /* 593 * The '|1' in the following statement turns on the 'Non-DMA' bit 594 * specifier in the last byte of the SPECIFY command as described in the 595 * datasheet I have. This is necessary for the driver to work on the 596 * sun3x, because the system will not respond to the chip's requests 597 * for DMA; there is no hardware on the motherboard to support it. 598 * By enabling this bit, we will force the chip to interrupt when its 599 * FIFO is full, at which point the interrupt handler will empty it and 600 * continue. This is ``pseudo-DMA''. 601 * -J 602 */ 603 OUT_FDC(fdc, 6|1); /* XXX head load time == 6ms */ 604 #undef OUT_FDC 605 606 /* 607 * Establish a mountroot_hook anyway in case we booted 608 * with RB_ASKNAME and get selected as the boot device. 609 */ 610 mountroothook_establish(fd_mountroot_hook, self); 611 612 /* Make sure the drive motor gets turned off at shutdown time. */ 613 if (!pmf_device_register1(self, NULL, NULL, fd_shutdown)) 614 aprint_error_dev(self, "couldn't establish power handler\n"); 615 } 616 617 bool 618 fd_shutdown(device_t self, int howto) 619 { 620 struct fd_softc *fd; 621 622 fd = device_private(self); 623 fd_motor_off(fd); 624 625 return true; 626 } 627 628 inline struct fd_type * 629 fd_dev_to_type(struct fd_softc *fd, dev_t dev) 630 { 631 int type = FDTYPE(dev); 632 633 if (type > (sizeof(fd_types) / sizeof(fd_types[0]))) 634 return NULL; 635 return type ? &fd_types[type - 1] : fd->sc_deftype; 636 } 637 638 void 639 fdstrategy(struct buf *bp) 640 { 641 struct fd_softc *fd; 642 int unit = FDUNIT(bp->b_dev); 643 int sz; 644 int s; 645 646 /* Valid unit, controller, and request? */ 647 if ((fd = device_lookup_private(&fd_cd, unit)) == 0 || 648 bp->b_blkno < 0 || 649 ((bp->b_bcount % FDC_BSIZE) != 0 && 650 (bp->b_flags & B_FORMAT) == 0)) { 651 bp->b_error = EINVAL; 652 goto done; 653 } 654 655 /* If it's a null transfer, return immediately. */ 656 if (bp->b_bcount == 0) 657 goto done; 658 659 sz = howmany(bp->b_bcount, FDC_BSIZE); 660 661 if (bp->b_blkno + sz > fd->sc_type->size) { 662 sz = fd->sc_type->size - bp->b_blkno; 663 if (sz == 0) { 664 /* If exactly at end of disk, return EOF. */ 665 bp->b_resid = bp->b_bcount; 666 goto done; 667 } 668 if (sz < 0) { 669 /* If past end of disk, return EINVAL. */ 670 bp->b_error = EINVAL; 671 goto done; 672 } 673 /* Otherwise, truncate request. */ 674 bp->b_bcount = sz << DEV_BSHIFT; 675 } 676 677 bp->b_rawblkno = bp->b_blkno; 678 bp->b_cylinder = 679 bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl; 680 681 #ifdef FD_DEBUG 682 if (fdc_debug > 1) 683 printf("%s: b_blkno %d b_bcount %d blkno %d cylin %d\n", 684 __func__, (int)bp->b_blkno, bp->b_bcount, 685 (int)fd->sc_blkno, bp->b_cylinder); 686 #endif 687 688 /* Queue transfer on drive, activate drive and controller if idle. */ 689 s = splbio(); 690 bufq_put(fd->sc_q, bp); 691 callout_stop(&fd->sc_motoroff_ch); /* a good idea */ 692 if (fd->sc_active == 0) 693 fdstart(fd); 694 #ifdef DIAGNOSTIC 695 else { 696 struct fdc_softc *fdc; 697 698 fdc = device_private(device_parent(fd->sc_dv)); 699 if (fdc->sc_state == DEVIDLE) { 700 printf("%s: controller inactive\n", __func__); 701 fdcstart(fdc); 702 } 703 } 704 #endif 705 splx(s); 706 return; 707 708 done: 709 /* Toss transfer; we're done early. */ 710 biodone(bp); 711 } 712 713 void 714 fdstart(struct fd_softc *fd) 715 { 716 struct fdc_softc *fdc = device_private(device_parent(fd->sc_dv)); 717 bool active = fdc->sc_drives.tqh_first != 0; 718 719 /* Link into controller queue. */ 720 fd->sc_active = 1; 721 TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); 722 723 /* If controller not already active, start it. */ 724 if (!active) 725 fdcstart(fdc); 726 } 727 728 void 729 fdfinish(struct fd_softc *fd, struct buf *bp) 730 { 731 struct fdc_softc *fdc = device_private(device_parent(fd->sc_dv)); 732 733 /* 734 * Move this drive to the end of the queue to give others a `fair' 735 * chance. We only force a switch if N operations are completed while 736 * another drive is waiting to be serviced, since there is a long motor 737 * startup delay whenever we switch. 738 */ 739 (void)bufq_get(fd->sc_q); 740 if (TAILQ_NEXT(fd, sc_drivechain) && ++fd->sc_ops >= 8) { 741 fd->sc_ops = 0; 742 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); 743 if (bufq_peek(fd->sc_q) != NULL) { 744 TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); 745 } else 746 fd->sc_active = 0; 747 } 748 bp->b_resid = fd->sc_bcount; 749 fd->sc_skip = 0; 750 751 biodone(bp); 752 /* turn off motor 5s from now */ 753 callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd); 754 fdc->sc_state = DEVIDLE; 755 } 756 757 void 758 fdc_reset(struct fdc_softc *fdc) 759 { 760 761 fdc->sc_fcr = 0; 762 FCR_REG_SYNC(); 763 764 *fdc->sc_reg_drs = DRS_RESET; 765 delay(10); 766 *fdc->sc_reg_drs = 0; 767 768 #ifdef FD_DEBUG 769 if (fdc_debug) 770 printf("fdc reset\n"); 771 #endif 772 } 773 774 void 775 fd_set_motor(struct fdc_softc *fdc) 776 { 777 struct fd_softc *fd; 778 int n; 779 780 int on = 0; 781 782 for (n = 0; n < 4; n++) 783 if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR)) 784 on = 1; 785 if (on) { 786 fdc->sc_fcr |= FCR_DSEL(0)|FCR_MTRON; /* XXX */ 787 } else { 788 fdc->sc_fcr &= ~(FCR_DSEL(0)|FCR_MTRON); /* XXX */ 789 } 790 FCR_REG_SYNC(); 791 } 792 793 void 794 fd_motor_off(void *arg) 795 { 796 struct fd_softc *fd = arg; 797 int s; 798 799 s = splbio(); 800 fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); 801 fd_set_motor(device_private(device_parent(fd->sc_dv))); 802 splx(s); 803 } 804 805 void 806 fd_motor_on(void *arg) 807 { 808 struct fd_softc *fd = arg; 809 struct fdc_softc *fdc = device_private(device_parent(fd->sc_dv)); 810 int s; 811 812 s = splbio(); 813 fd->sc_flags &= ~FD_MOTOR_WAIT; 814 if ((TAILQ_FIRST(&fdc->sc_drives) == fd) && 815 (fdc->sc_state == MOTORWAIT)) 816 (void)fdcstate(fdc); 817 splx(s); 818 } 819 820 int 821 fdcresult(struct fdc_softc *fdc) 822 { 823 uint8_t i; 824 int j, n = 0; 825 826 for (j = 100000; j; j--) { 827 i = *fdc->sc_reg_msr & (NE7_DIO | NE7_RQM | NE7_CB); 828 if (i == NE7_RQM) { 829 fdc->sc_nstat = n; 830 return n; 831 } 832 if (i == (NE7_DIO | NE7_RQM | NE7_CB)) { 833 if (n >= sizeof(fdc->sc_status)) { 834 log(LOG_ERR, "fdcresult: overrun\n"); 835 return -1; 836 } 837 fdc->sc_status[n++] = *fdc->sc_reg_fifo; 838 } else 839 delay(10); 840 } 841 log(LOG_ERR, "fdcresult: timeout\n"); 842 fdc->sc_nstat = -1; 843 return -1; 844 } 845 846 int 847 out_fdc(struct fdc_softc *fdc, u_char x) 848 { 849 int i = 100000; 850 851 while (((*fdc->sc_reg_msr & (NE7_DIO|NE7_RQM)) != NE7_RQM) && i-- > 0) 852 delay(1); 853 if (i <= 0) 854 return -1; 855 856 *fdc->sc_reg_fifo = x; 857 return 0; 858 } 859 860 int 861 fdopen(dev_t dev, int flags, int fmt, struct lwp *l) 862 { 863 int unit, pmask; 864 struct fd_softc *fd; 865 struct fd_type *type; 866 867 unit = FDUNIT(dev); 868 fd = device_lookup_private(&fd_cd, unit); 869 if (fd == NULL) 870 return ENXIO; 871 type = fd_dev_to_type(fd, dev); 872 if (type == NULL) 873 return ENXIO; 874 875 if ((fd->sc_flags & FD_OPEN) != 0 && 876 fd->sc_type != type) 877 return EBUSY; 878 879 fd->sc_type = type; 880 fd->sc_cylin = -1; 881 fd->sc_flags |= FD_OPEN; 882 883 /* 884 * Only update the disklabel if we're not open anywhere else. 885 */ 886 if (fd->sc_dk.dk_openmask == 0) 887 fdgetdisklabel(dev); 888 889 pmask = (1 << DISKPART(dev)); 890 891 switch (fmt) { 892 case S_IFCHR: 893 fd->sc_dk.dk_copenmask |= pmask; 894 break; 895 896 case S_IFBLK: 897 fd->sc_dk.dk_bopenmask |= pmask; 898 break; 899 } 900 fd->sc_dk.dk_openmask = 901 fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask; 902 903 return 0; 904 } 905 906 int 907 fdclose(dev_t dev, int flags, int fmt, struct lwp *l) 908 { 909 struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev)); 910 int pmask = (1 << DISKPART(dev)); 911 912 fd->sc_flags &= ~FD_OPEN; 913 fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT); 914 915 switch (fmt) { 916 case S_IFCHR: 917 fd->sc_dk.dk_copenmask &= ~pmask; 918 break; 919 920 case S_IFBLK: 921 fd->sc_dk.dk_bopenmask &= ~pmask; 922 break; 923 } 924 fd->sc_dk.dk_openmask = 925 fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask; 926 927 return 0; 928 } 929 930 int 931 fdread(dev_t dev, struct uio *uio, int flag) 932 { 933 934 return physio(fdstrategy, NULL, dev, B_READ, minphys, uio); 935 } 936 937 int 938 fdwrite(dev_t dev, struct uio *uio, int flag) 939 { 940 941 return physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio); 942 } 943 944 void 945 fdcstart(struct fdc_softc *fdc) 946 { 947 948 #ifdef DIAGNOSTIC 949 /* only got here if controller's drive queue was inactive; should 950 be in idle state */ 951 if (fdc->sc_state != DEVIDLE) { 952 printf("%s: not idle\n", __func__); 953 return; 954 } 955 #endif 956 (void)fdcstate(fdc); 957 } 958 959 static void 960 fdcpstatus(int n, struct fdc_softc *fdc) 961 { 962 char bits[64]; 963 964 switch (n) { 965 case 0: 966 printf("\n"); 967 break; 968 case 2: 969 snprintb(bits, sizeof(bits), NE7_ST0BITS, fdc->sc_status[0]); 970 printf(" (st0 %s cyl %d)\n", bits, fdc->sc_status[1]); 971 break; 972 case 7: 973 snprintb(bits, sizeof(bits), NE7_ST0BITS, fdc->sc_status[0]); 974 printf(" (st0 %s", bits); 975 snprintb(bits, sizeof(bits), NE7_ST1BITS, fdc->sc_status[1]); 976 printf(" st1 %s", bits); 977 snprintb(bits, sizeof(bits), NE7_ST2BITS, fdc->sc_status[2]); 978 printf(" st2 %s", bits); 979 printf(" cyl %d head %d sec %d)\n", 980 fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]); 981 break; 982 #ifdef DIAGNOSTIC 983 default: 984 printf("\nfdcstatus: weird size"); 985 break; 986 #endif 987 } 988 } 989 990 void 991 fdcstatus(device_t dv, int n, const char *s) 992 { 993 struct fdc_softc *fdc = device_private(device_parent(dv)); 994 #if 0 995 /* 996 * A 82072 seems to return <invalid command> on 997 * gratuitous Sense Interrupt commands. 998 */ 999 if (n == 0 && (fdc->sc_flags & FDC_82077)) { 1000 out_fdc(fdc, NE7CMD_SENSEI); 1001 (void)fdcresult(fdc); 1002 n = 2; 1003 } 1004 #endif 1005 1006 /* Just print last status */ 1007 n = fdc->sc_nstat; 1008 1009 printf("%s: %s: state %d", device_xname(dv), s, fdc->sc_state); 1010 1011 fdcpstatus(n, fdc); 1012 } 1013 1014 void 1015 fdctimeout(void *arg) 1016 { 1017 struct fdc_softc *fdc = arg; 1018 struct fd_softc *fd = TAILQ_FIRST(&fdc->sc_drives); 1019 int s; 1020 1021 s = splbio(); 1022 fdcstatus(fd->sc_dv, 0, "timeout"); 1023 1024 if (bufq_peek(fd->sc_q) != NULL) 1025 fdc->sc_state++; 1026 else 1027 fdc->sc_state = DEVIDLE; 1028 1029 (void)fdcstate(fdc); 1030 splx(s); 1031 } 1032 1033 void 1034 fdcpseudointr(void *arg) 1035 { 1036 struct fdc_softc *fdc = arg; 1037 int s; 1038 1039 /* Just ensure it has the right spl. */ 1040 s = splbio(); 1041 (void)fdcstate(fdc); 1042 splx(s); 1043 } 1044 1045 1046 /* 1047 * hardware interrupt entry point: must be converted to `fast' 1048 * (in-window) handler. 1049 */ 1050 int 1051 fdchwintr(void *arg) 1052 { 1053 struct fdc_softc *fdc = arg; 1054 1055 /* 1056 * This code was reverse engineered from the SPARC bsd_fdintr.s. 1057 */ 1058 switch (fdc->sc_istate) { 1059 case ISTATE_IDLE: 1060 return 0; 1061 case ISTATE_SENSEI: 1062 out_fdc(fdc, NE7CMD_SENSEI); 1063 fdcresult(fdc); 1064 fdc->sc_istate = ISTATE_DONE; 1065 FD_SET_SWINTR(); 1066 return 1; 1067 case ISTATE_DMA: 1068 break; 1069 default: 1070 log(LOG_ERR, "fdc: stray hard interrupt.\n"); 1071 fdc->sc_fcr &= ~(FCR_DSEL(0)); /* Does this help? */ 1072 fdc->sc_istate = ISTATE_SPURIOUS; 1073 FD_SET_SWINTR(); 1074 return 1; 1075 } 1076 1077 for (;;) { 1078 int msr; 1079 1080 msr = *fdc->sc_reg_msr; 1081 1082 if ((msr & NE7_RQM) == 0) 1083 break; 1084 1085 if ((msr & NE7_NDM) == 0) { 1086 /* Execution phase finished, get result. */ 1087 fdcresult(fdc); 1088 fdc->sc_istate = ISTATE_DONE; 1089 FD_SET_SWINTR(); 1090 #ifdef FD_DEBUG 1091 if (fdc_debug) 1092 log(LOG_ERR, "fdc: overrun: tc = %d\n", 1093 fdc->sc_tc); 1094 #endif 1095 break; 1096 } 1097 1098 if (msr & NE7_DIO) { 1099 *fdc->sc_data++ = *fdc->sc_reg_fifo; 1100 } else { 1101 *fdc->sc_reg_fifo = *fdc->sc_data++; 1102 } 1103 if (--fdc->sc_tc == 0) { 1104 fdc->sc_fcr |= FCR_TC; 1105 FCR_REG_SYNC(); 1106 delay(10); 1107 fdc->sc_fcr &= ~FCR_TC; 1108 FCR_REG_SYNC(); 1109 break; 1110 } 1111 } 1112 return 1; 1113 } 1114 1115 void 1116 fdcswintr(void *arg) 1117 { 1118 struct fdc_softc *fdc = arg; 1119 int s; 1120 1121 if (fdc->sc_istate != ISTATE_DONE) 1122 return; 1123 1124 fdc->sc_istate = ISTATE_IDLE; 1125 s = splbio(); 1126 fdcstate(fdc); 1127 splx(s); 1128 } 1129 1130 int 1131 fdcstate(struct fdc_softc *fdc) 1132 { 1133 #define st0 fdc->sc_status[0] 1134 #define st1 fdc->sc_status[1] 1135 #define cyl fdc->sc_status[1] 1136 #define OUT_FDC(fdc, c, s) \ 1137 do { \ 1138 if (out_fdc(fdc, (c))) { \ 1139 (fdc)->sc_state = (s); \ 1140 goto loop; \ 1141 } \ 1142 } while (/* CONSTCOND */ 0) 1143 1144 struct fd_softc *fd; 1145 struct buf *bp; 1146 int read, head, sec, nblks; 1147 struct fd_type *type; 1148 struct ne7_fd_formb *finfo = NULL; 1149 1150 1151 if (fdc->sc_istate != ISTATE_IDLE) { 1152 /* Trouble... */ 1153 printf("fdc: spurious interrupt: state %d, istate=%d\n", 1154 fdc->sc_state, fdc->sc_istate); 1155 fdc->sc_istate = ISTATE_IDLE; 1156 if (fdc->sc_state == RESETCOMPLETE || 1157 fdc->sc_state == RESETTIMEDOUT) { 1158 panic("%s: spurious interrupt can't be cleared", 1159 __func__); 1160 } 1161 goto doreset; 1162 } 1163 1164 loop: 1165 /* Is there a drive for the controller to do a transfer with? */ 1166 fd = TAILQ_FIRST(&fdc->sc_drives); 1167 if (fd == NULL) { 1168 fdc->sc_state = DEVIDLE; 1169 return 0; 1170 } 1171 1172 /* Is there a transfer to this drive? If not, deactivate drive. */ 1173 bp = bufq_peek(fd->sc_q); 1174 if (bp == NULL) { 1175 fd->sc_ops = 0; 1176 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); 1177 fd->sc_active = 0; 1178 goto loop; 1179 } 1180 1181 if (bp->b_flags & B_FORMAT) 1182 finfo = (struct ne7_fd_formb *)bp->b_data; 1183 1184 switch (fdc->sc_state) { 1185 case DEVIDLE: 1186 fdc->sc_errors = 0; 1187 fd->sc_skip = 0; 1188 fd->sc_bcount = bp->b_bcount; 1189 fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE); 1190 callout_stop(&fd->sc_motoroff_ch); 1191 if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) { 1192 fdc->sc_state = MOTORWAIT; 1193 return 1; 1194 } 1195 if ((fd->sc_flags & FD_MOTOR) == 0) { 1196 /* Turn on the motor, being careful about pairing. */ 1197 struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1]; 1198 if (ofd && ofd->sc_flags & FD_MOTOR) { 1199 callout_stop(&ofd->sc_motoroff_ch); 1200 ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); 1201 } 1202 fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT; 1203 fd_set_motor(fdc); 1204 fdc->sc_state = MOTORWAIT; 1205 if (fdc->sc_flags & FDC_82077) { /* XXX */ 1206 /* Allow .25s for motor to stabilize. */ 1207 callout_reset(&fd->sc_motoron_ch, hz / 4, 1208 fd_motor_on, fd); 1209 } else { 1210 fd->sc_flags &= ~FD_MOTOR_WAIT; 1211 goto loop; 1212 } 1213 return 1; 1214 } 1215 /* Make sure the right drive is selected. */ 1216 fd_set_motor(fdc); 1217 1218 /*FALLTHROUGH*/ 1219 case DOSEEK: 1220 doseek: 1221 if ((fdc->sc_flags & FDC_EIS) && 1222 (bp->b_flags & B_FORMAT) == 0) { 1223 fd->sc_cylin = bp->b_cylinder; 1224 /* We use implied seek */ 1225 goto doio; 1226 } 1227 1228 if (fd->sc_cylin == bp->b_cylinder) 1229 goto doio; 1230 1231 /* specify command */ 1232 OUT_FDC(fdc, NE7CMD_SPECIFY, SEEKTIMEDOUT); 1233 OUT_FDC(fdc, fd->sc_type->steprate, SEEKTIMEDOUT); 1234 OUT_FDC(fdc, 6|1, SEEKTIMEDOUT); /* XXX head load time == 6ms */ 1235 1236 fdc->sc_istate = ISTATE_SENSEI; 1237 /* seek function */ 1238 OUT_FDC(fdc, NE7CMD_SEEK, SEEKTIMEDOUT); 1239 OUT_FDC(fdc, fd->sc_drive, SEEKTIMEDOUT); /* drive number */ 1240 OUT_FDC(fdc, bp->b_cylinder * fd->sc_type->step, SEEKTIMEDOUT); 1241 1242 fd->sc_cylin = -1; 1243 fdc->sc_state = SEEKWAIT; 1244 fdc->sc_nstat = 0; 1245 1246 iostat_seek(fd->sc_dk.dk_stats); 1247 disk_busy(&fd->sc_dk); 1248 1249 callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc); 1250 return 1; 1251 1252 case DOIO: 1253 doio: 1254 #ifdef NOTYET 1255 /* Check to see if the disk has changed */ 1256 if (fdc->sc_reg_dir & FDI_DCHG) { 1257 /* 1258 * The disk in the drive has changed since 1259 * the last transfer. We need to see if its geometry 1260 * has changed. 1261 */ 1262 } 1263 #endif /* NOTYET */ 1264 1265 if (finfo) 1266 fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) - 1267 (char *)finfo; 1268 type = fd->sc_type; 1269 sec = fd->sc_blkno % type->seccyl; 1270 nblks = type->seccyl - sec; 1271 nblks = min(nblks, fd->sc_bcount / FDC_BSIZE); 1272 nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE); 1273 fd->sc_nblks = nblks; 1274 fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE; 1275 head = sec / type->sectrac; 1276 sec -= head * type->sectrac; 1277 #ifdef DIAGNOSTIC 1278 { 1279 int block; 1280 1281 block = (fd->sc_cylin * type->heads + head) * 1282 type->sectrac + sec; 1283 if (block != fd->sc_blkno) { 1284 printf("%s: block %d != blkno %" PRIu64 "\n", 1285 device_xname(fdc->sc_dev), block, 1286 fd->sc_blkno); 1287 #ifdef DDB 1288 Debugger(); 1289 #endif 1290 } 1291 } 1292 #endif 1293 read = bp->b_flags & B_READ; 1294 1295 /* Setup for pseudo DMA */ 1296 fdc->sc_data = (char *)bp->b_data + fd->sc_skip; 1297 fdc->sc_tc = fd->sc_nbytes; 1298 1299 *fdc->sc_reg_drs = type->rate; 1300 #ifdef FD_DEBUG 1301 if (fdc_debug > 1) 1302 printf("%s: %s drive %d track %d head %d sec %d " 1303 "nblks %d\n", __func__, 1304 read ? "read" : "write", fd->sc_drive, 1305 fd->sc_cylin, head, sec, nblks); 1306 #endif 1307 fdc->sc_state = IOCOMPLETE; 1308 fdc->sc_istate = ISTATE_DMA; 1309 fdc->sc_nstat = 0; 1310 if (finfo) { 1311 /* formatting */ 1312 OUT_FDC(fdc, NE7CMD_FORMAT, IOTIMEDOUT); 1313 OUT_FDC(fdc, (head << 2) | fd->sc_drive, IOTIMEDOUT); 1314 OUT_FDC(fdc, finfo->fd_formb_secshift, IOTIMEDOUT); 1315 OUT_FDC(fdc, finfo->fd_formb_nsecs, IOTIMEDOUT); 1316 OUT_FDC(fdc, finfo->fd_formb_gaplen, IOTIMEDOUT); 1317 OUT_FDC(fdc, finfo->fd_formb_fillbyte, IOTIMEDOUT); 1318 } else { 1319 if (read) 1320 OUT_FDC(fdc, NE7CMD_READ, IOTIMEDOUT); 1321 else 1322 OUT_FDC(fdc, NE7CMD_WRITE, IOTIMEDOUT); 1323 OUT_FDC(fdc, (head << 2) | fd->sc_drive, IOTIMEDOUT); 1324 OUT_FDC(fdc, fd->sc_cylin, IOTIMEDOUT); /*track*/ 1325 OUT_FDC(fdc, head, IOTIMEDOUT); 1326 OUT_FDC(fdc, sec + 1, IOTIMEDOUT); /*sector+1*/ 1327 OUT_FDC(fdc, type->secsize, IOTIMEDOUT);/*sector size*/ 1328 OUT_FDC(fdc, type->sectrac, IOTIMEDOUT);/*secs/track*/ 1329 OUT_FDC(fdc, type->gap1, IOTIMEDOUT); /*gap1 size*/ 1330 OUT_FDC(fdc, type->datalen, IOTIMEDOUT);/*data length*/ 1331 } 1332 1333 disk_busy(&fd->sc_dk); 1334 1335 /* allow 2 seconds for operation */ 1336 callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc); 1337 return 1; /* will return later */ 1338 1339 case SEEKWAIT: 1340 callout_stop(&fdc->sc_timo_ch); 1341 fdc->sc_state = SEEKCOMPLETE; 1342 if (fdc->sc_flags & FDC_NEEDHEADSETTLE) { 1343 /* allow 1/50 second for heads to settle */ 1344 callout_reset(&fdc->sc_intr_ch, hz / 50, 1345 fdcpseudointr, fdc); 1346 return 1; /* will return later */ 1347 } 1348 /*FALLTHROUGH*/ 1349 case SEEKCOMPLETE: 1350 /* no data on seek */ 1351 disk_unbusy(&fd->sc_dk, 0, 0); 1352 1353 /* Make sure seek really happened. */ 1354 if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 || 1355 cyl != bp->b_cylinder * fd->sc_type->step) { 1356 #ifdef FD_DEBUG 1357 if (fdc_debug) 1358 fdcstatus(fd->sc_dv, 2, "seek failed"); 1359 #endif 1360 fdcretry(fdc); 1361 goto loop; 1362 } 1363 fd->sc_cylin = bp->b_cylinder; 1364 goto doio; 1365 1366 case IOTIMEDOUT: 1367 fdc->sc_fcr |= FCR_TC; 1368 FCR_REG_SYNC(); 1369 delay(10); 1370 fdc->sc_fcr &= ~FCR_TC; 1371 FCR_REG_SYNC(); 1372 (void)fdcresult(fdc); 1373 /* FALLTHROUGH */ 1374 case SEEKTIMEDOUT: 1375 case RECALTIMEDOUT: 1376 case RESETTIMEDOUT: 1377 fdcretry(fdc); 1378 goto loop; 1379 1380 case IOCOMPLETE: /* IO DONE, post-analyze */ 1381 callout_stop(&fdc->sc_timo_ch); 1382 1383 disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid), 1384 (bp->b_flags & B_READ)); 1385 1386 if (fdc->sc_nstat != 7 || (st0 & 0xf8) != 0 || st1 != 0) { 1387 #ifdef FD_DEBUG 1388 if (fdc_debug) { 1389 fdcstatus(fd->sc_dv, 7, 1390 bp->b_flags & B_READ 1391 ? "read failed" : "write failed"); 1392 printf("blkno %d nblks %d tc %d\n", 1393 (int)fd->sc_blkno, fd->sc_nblks, 1394 fdc->sc_tc); 1395 } 1396 #endif 1397 if (fdc->sc_nstat == 7 && 1398 (st1 & ST1_OVERRUN) == ST1_OVERRUN) { 1399 1400 /* 1401 * Silently retry overruns if no other 1402 * error bit is set. Adjust threshold. 1403 */ 1404 int thr = fdc->sc_cfg & CFG_THRHLD_MASK; 1405 if (thr < 15) { 1406 thr++; 1407 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 1408 fdc->sc_cfg |= (thr & CFG_THRHLD_MASK); 1409 #ifdef FD_DEBUG 1410 if (fdc_debug) 1411 printf("fdc: %d -> threshold\n", 1412 thr); 1413 #endif 1414 fdconf(fdc); 1415 fdc->sc_overruns = 0; 1416 } 1417 if (++fdc->sc_overruns < 3) { 1418 fdc->sc_state = DOIO; 1419 goto loop; 1420 } 1421 } 1422 fdcretry(fdc); 1423 goto loop; 1424 } 1425 if (fdc->sc_errors) { 1426 diskerr(bp, "fd", "soft error", LOG_PRINTF, 1427 fd->sc_skip / FDC_BSIZE, NULL); 1428 printf("\n"); 1429 fdc->sc_errors = 0; 1430 } else { 1431 if (--fdc->sc_overruns < -20) { 1432 int thr = fdc->sc_cfg & CFG_THRHLD_MASK; 1433 if (thr > 0) { 1434 thr--; 1435 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 1436 fdc->sc_cfg |= (thr & CFG_THRHLD_MASK); 1437 #ifdef FD_DEBUG 1438 if (fdc_debug) 1439 printf("fdc: %d -> threshold\n", 1440 thr); 1441 #endif 1442 fdconf(fdc); 1443 } 1444 fdc->sc_overruns = 0; 1445 } 1446 } 1447 fd->sc_blkno += fd->sc_nblks; 1448 fd->sc_skip += fd->sc_nbytes; 1449 fd->sc_bcount -= fd->sc_nbytes; 1450 if (!finfo && fd->sc_bcount > 0) { 1451 bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl; 1452 goto doseek; 1453 } 1454 fdfinish(fd, bp); 1455 goto loop; 1456 1457 case DORESET: 1458 doreset: 1459 /* try a reset, keep motor on */ 1460 fd_set_motor(fdc); 1461 delay(100); 1462 fdc_reset(fdc); 1463 fdc->sc_nstat = 0; 1464 fdc->sc_istate = ISTATE_SENSEI; 1465 fdc->sc_state = RESETCOMPLETE; 1466 callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc); 1467 return 1; /* will return later */ 1468 1469 case RESETCOMPLETE: 1470 callout_stop(&fdc->sc_timo_ch); 1471 fdconf(fdc); 1472 1473 /* FALLTHROUGH */ 1474 case DORECAL: 1475 fdc->sc_state = RECALWAIT; 1476 fdc->sc_istate = ISTATE_SENSEI; 1477 fdc->sc_nstat = 0; 1478 /* recalibrate function */ 1479 OUT_FDC(fdc, NE7CMD_RECAL, RECALTIMEDOUT); 1480 OUT_FDC(fdc, fd->sc_drive, RECALTIMEDOUT); 1481 callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc); 1482 return 1; /* will return later */ 1483 1484 case RECALWAIT: 1485 callout_stop(&fdc->sc_timo_ch); 1486 fdc->sc_state = RECALCOMPLETE; 1487 if (fdc->sc_flags & FDC_NEEDHEADSETTLE) { 1488 /* allow 1/30 second for heads to settle */ 1489 callout_reset(&fdc->sc_intr_ch, hz / 30, 1490 fdcpseudointr, fdc); 1491 return 1; /* will return later */ 1492 } 1493 1494 case RECALCOMPLETE: 1495 if (fdc->sc_nstat != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) { 1496 #ifdef FD_DEBUG 1497 if (fdc_debug) 1498 fdcstatus(fd->sc_dv, 2, "recalibrate failed"); 1499 #endif 1500 fdcretry(fdc); 1501 goto loop; 1502 } 1503 fd->sc_cylin = 0; 1504 goto doseek; 1505 1506 case MOTORWAIT: 1507 if (fd->sc_flags & FD_MOTOR_WAIT) 1508 return 1; /* time's not up yet */ 1509 goto doseek; 1510 1511 default: 1512 fdcstatus(fd->sc_dv, 0, "stray interrupt"); 1513 return 1; 1514 } 1515 #ifdef DIAGNOSTIC 1516 panic("%s: impossible", __func__); 1517 #endif 1518 #undef st0 1519 #undef st1 1520 #undef cyl 1521 } 1522 1523 void 1524 fdcretry(struct fdc_softc *fdc) 1525 { 1526 struct fd_softc *fd; 1527 struct buf *bp; 1528 1529 fd = fdc->sc_drives.tqh_first; 1530 bp = bufq_peek(fd->sc_q); 1531 1532 fdc->sc_overruns = 0; 1533 if (fd->sc_opts & FDOPT_NORETRY) 1534 goto fail; 1535 1536 switch (fdc->sc_errors) { 1537 case 0: 1538 /* try again */ 1539 fdc->sc_state = 1540 (fdc->sc_flags & FDC_EIS) ? DOIO : DOSEEK; 1541 break; 1542 1543 case 1: 1544 case 2: 1545 case 3: 1546 /* didn't work; try recalibrating */ 1547 fdc->sc_state = DORECAL; 1548 break; 1549 1550 case 4: 1551 /* still no go; reset the bastard */ 1552 fdc->sc_state = DORESET; 1553 break; 1554 1555 default: 1556 fail: 1557 if ((fd->sc_opts & FDOPT_SILENT) == 0) { 1558 diskerr(bp, "fd", "hard error", LOG_PRINTF, 1559 fd->sc_skip / FDC_BSIZE, NULL); 1560 1561 fdcpstatus(7, fdc); 1562 } 1563 1564 bp->b_error = EIO; 1565 fdfinish(fd, bp); 1566 } 1567 fdc->sc_errors++; 1568 } 1569 1570 int 1571 fdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 1572 { 1573 struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev)); 1574 struct fdformat_parms *form_parms; 1575 struct fdformat_cmd *form_cmd; 1576 struct ne7_fd_formb *fd_formb; 1577 int il[FD_MAX_NSEC + 1]; 1578 int i, j; 1579 int error; 1580 1581 switch (cmd) { 1582 case DIOCGDINFO: 1583 *(struct disklabel *)addr = *(fd->sc_dk.dk_label); 1584 return 0; 1585 1586 case DIOCWLABEL: 1587 if ((flag & FWRITE) == 0) 1588 return EBADF; 1589 /* XXX do something */ 1590 return 0; 1591 1592 case DIOCWDINFO: 1593 if ((flag & FWRITE) == 0) 1594 return EBADF; 1595 1596 error = setdisklabel(fd->sc_dk.dk_label, 1597 (struct disklabel *)addr, 0, fd->sc_dk.dk_cpulabel); 1598 if (error) 1599 return error; 1600 1601 error = writedisklabel(dev, fdstrategy, fd->sc_dk.dk_label, 1602 fd->sc_dk.dk_cpulabel); 1603 return error; 1604 1605 case DIOCLOCK: 1606 /* 1607 * Nothing to do here, really. 1608 */ 1609 return 0; 1610 1611 case DIOCEJECT: 1612 if (*(int *)addr == 0) { 1613 int part = DISKPART(dev); 1614 /* 1615 * Don't force eject: check that we are the only 1616 * partition open. If so, unlock it. 1617 */ 1618 if ((fd->sc_dk.dk_openmask & ~(1 << part)) != 0 || 1619 fd->sc_dk.dk_bopenmask + fd->sc_dk.dk_copenmask != 1620 fd->sc_dk.dk_openmask) { 1621 return EBUSY; 1622 } 1623 } 1624 /* FALLTHROUGH */ 1625 case ODIOCEJECT: 1626 fd_do_eject(device_private(device_parent(fd->sc_dv)), 1627 fd->sc_drive); 1628 return 0; 1629 1630 case FDIOCGETFORMAT: 1631 form_parms = (struct fdformat_parms *)addr; 1632 form_parms->fdformat_version = FDFORMAT_VERSION; 1633 form_parms->nbps = 128 * (1 << fd->sc_type->secsize); 1634 form_parms->ncyl = fd->sc_type->tracks; 1635 form_parms->nspt = fd->sc_type->sectrac; 1636 form_parms->ntrk = fd->sc_type->heads; 1637 form_parms->stepspercyl = fd->sc_type->step; 1638 form_parms->gaplen = fd->sc_type->gap2; 1639 form_parms->fillbyte = fd->sc_type->fillbyte; 1640 form_parms->interleave = fd->sc_type->interleave; 1641 switch (fd->sc_type->rate) { 1642 case FDC_500KBPS: 1643 form_parms->xfer_rate = 500 * 1024; 1644 break; 1645 case FDC_300KBPS: 1646 form_parms->xfer_rate = 300 * 1024; 1647 break; 1648 case FDC_250KBPS: 1649 form_parms->xfer_rate = 250 * 1024; 1650 break; 1651 default: 1652 return EINVAL; 1653 } 1654 return 0; 1655 1656 case FDIOCSETFORMAT: 1657 if ((flag & FWRITE) == 0) 1658 return EBADF; /* must be opened for writing */ 1659 1660 form_parms = (struct fdformat_parms *)addr; 1661 if (form_parms->fdformat_version != FDFORMAT_VERSION) 1662 return EINVAL; /* wrong version of formatting prog */ 1663 1664 i = form_parms->nbps >> 7; 1665 if ((form_parms->nbps & 0x7f) || ffs(i) == 0 || 1666 i & ~(1 << (ffs(i) - 1))) 1667 /* not a power-of-two multiple of 128 */ 1668 return EINVAL; 1669 1670 switch (form_parms->xfer_rate) { 1671 case 500 * 1024: 1672 fd->sc_type->rate = FDC_500KBPS; 1673 break; 1674 case 300 * 1024: 1675 fd->sc_type->rate = FDC_300KBPS; 1676 break; 1677 case 250 * 1024: 1678 fd->sc_type->rate = FDC_250KBPS; 1679 break; 1680 default: 1681 return EINVAL; 1682 } 1683 1684 if (form_parms->nspt > FD_MAX_NSEC || 1685 form_parms->fillbyte > 0xff || 1686 form_parms->interleave > 0xff) 1687 return EINVAL; 1688 fd->sc_type->sectrac = form_parms->nspt; 1689 if (form_parms->ntrk != 2 && form_parms->ntrk != 1) 1690 return EINVAL; 1691 fd->sc_type->heads = form_parms->ntrk; 1692 fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk; 1693 fd->sc_type->secsize = ffs(i) - 1; 1694 fd->sc_type->gap2 = form_parms->gaplen; 1695 fd->sc_type->tracks = form_parms->ncyl; 1696 fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl * 1697 form_parms->nbps / DEV_BSIZE; 1698 fd->sc_type->step = form_parms->stepspercyl; 1699 fd->sc_type->fillbyte = form_parms->fillbyte; 1700 fd->sc_type->interleave = form_parms->interleave; 1701 return 0; 1702 1703 case FDIOCFORMAT_TRACK: 1704 if((flag & FWRITE) == 0) 1705 /* must be opened for writing */ 1706 return EBADF; 1707 form_cmd = (struct fdformat_cmd *)addr; 1708 if (form_cmd->formatcmd_version != FDFORMAT_VERSION) 1709 /* wrong version of formatting prog */ 1710 return EINVAL; 1711 1712 if (form_cmd->head >= fd->sc_type->heads || 1713 form_cmd->cylinder >= fd->sc_type->tracks) { 1714 return EINVAL; 1715 } 1716 1717 fd_formb = malloc(sizeof(struct ne7_fd_formb), 1718 M_TEMP, M_NOWAIT); 1719 if (fd_formb == 0) 1720 return ENOMEM; 1721 1722 fd_formb->head = form_cmd->head; 1723 fd_formb->cyl = form_cmd->cylinder; 1724 fd_formb->transfer_rate = fd->sc_type->rate; 1725 fd_formb->fd_formb_secshift = fd->sc_type->secsize; 1726 fd_formb->fd_formb_nsecs = fd->sc_type->sectrac; 1727 fd_formb->fd_formb_gaplen = fd->sc_type->gap2; 1728 fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte; 1729 1730 memset(il, 0, sizeof(il)); 1731 for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) { 1732 while (il[(j%fd_formb->fd_formb_nsecs) + 1]) 1733 j++; 1734 il[(j % fd_formb->fd_formb_nsecs) + 1] = i; 1735 j += fd->sc_type->interleave; 1736 } 1737 for (i = 0; i < fd_formb->fd_formb_nsecs; i++) { 1738 fd_formb->fd_formb_cylno(i) = form_cmd->cylinder; 1739 fd_formb->fd_formb_headno(i) = form_cmd->head; 1740 fd_formb->fd_formb_secno(i) = il[i+1]; 1741 fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize; 1742 } 1743 1744 error = fdformat(dev, fd_formb, l->l_proc); 1745 free(fd_formb, M_TEMP); 1746 return error; 1747 1748 case FDIOCGETOPTS: /* get drive options */ 1749 *(int *)addr = fd->sc_opts; 1750 return 0; 1751 1752 case FDIOCSETOPTS: /* set drive options */ 1753 fd->sc_opts = *(int *)addr; 1754 return 0; 1755 1756 #ifdef DEBUG 1757 case _IO('f', 100): 1758 { 1759 int k; 1760 struct fdc_softc *fdc = 1761 device_private(device_parent(fd->sc_dv)); 1762 1763 out_fdc(fdc, NE7CMD_DUMPREG); 1764 fdcresult(fdc); 1765 printf("dumpreg(%d regs): <", fdc->sc_nstat); 1766 for (k = 0; k < fdc->sc_nstat; k++) 1767 printf(" %x", fdc->sc_status[k]); 1768 printf(">\n"); 1769 } 1770 return 0; 1771 1772 case _IOW('f', 101, int): 1773 struct fdc_softc *fdc = 1774 device_private(device_parent(fd->sc_dv)); 1775 1776 fdc->sc_cfg &= ~CFG_THRHLD_MASK; 1777 fdc->sc_cfg |= (*(int *)addr & CFG_THRHLD_MASK); 1778 fdconf(fdc); 1779 return 0; 1780 1781 case _IO('f', 102): 1782 { 1783 int k; 1784 struct fdc_softc *fdc = 1785 device_private(device_parent(fd->sc_dv)); 1786 1787 out_fdc(fdc, NE7CMD_SENSEI); 1788 fdcresult(fdc); 1789 printf("sensei(%d regs): <", fdc->sc_nstat); 1790 for (k=0; k < fdc->sc_nstat; k++) 1791 printf(" 0x%x", fdc->sc_status[k]); 1792 } 1793 printf(">\n"); 1794 return 0; 1795 #endif 1796 default: 1797 return ENOTTY; 1798 } 1799 1800 #ifdef DIAGNOSTIC 1801 panic("%s: impossible", __func__); 1802 #endif 1803 } 1804 1805 int 1806 fdformat(dev_t dev, struct ne7_fd_formb *finfo, struct proc *p) 1807 { 1808 int rv = 0; 1809 struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev)); 1810 struct fd_type *type = fd->sc_type; 1811 struct buf *bp; 1812 1813 /* set up a buffer header for fdstrategy() */ 1814 bp = getiobuf(NULL, false); 1815 if (bp == NULL) 1816 return ENOBUFS; 1817 1818 bp->b_vp = NULL; 1819 bp->b_cflags = BC_BUSY; 1820 bp->b_flags = B_PHYS | B_FORMAT; 1821 bp->b_proc = p; 1822 bp->b_dev = dev; 1823 1824 /* 1825 * Calculate a fake blkno, so fdstrategy() would initiate a 1826 * seek to the requested cylinder. 1827 */ 1828 bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads) 1829 + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE; 1830 1831 bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 1832 bp->b_data = (void *)finfo; 1833 1834 #ifdef FD_DEBUG 1835 if (fdc_debug) 1836 printf("%s: blkno %x count %d\n", 1837 __func__, (int)bp->b_blkno, bp->b_bcount); 1838 #endif 1839 1840 /* now do the format */ 1841 fdstrategy(bp); 1842 1843 /* ...and wait for it to complete */ 1844 rv = biowait(bp); 1845 putiobuf(bp); 1846 return rv; 1847 } 1848 1849 void 1850 fdgetdisklabel(dev_t dev) 1851 { 1852 int unit = FDUNIT(dev), i; 1853 struct fd_softc *fd = device_lookup_private(&fd_cd, unit); 1854 struct disklabel *lp = fd->sc_dk.dk_label; 1855 struct cpu_disklabel *clp = fd->sc_dk.dk_cpulabel; 1856 1857 memset(lp, 0, sizeof(struct disklabel)); 1858 memset(lp, 0, sizeof(struct cpu_disklabel)); 1859 1860 lp->d_type = DTYPE_FLOPPY; 1861 lp->d_secsize = FDC_BSIZE; 1862 lp->d_secpercyl = fd->sc_type->seccyl; 1863 lp->d_nsectors = fd->sc_type->sectrac; 1864 lp->d_ncylinders = fd->sc_type->tracks; 1865 lp->d_ntracks = fd->sc_type->heads; /* Go figure... */ 1866 lp->d_rpm = 3600; /* XXX like it matters... */ 1867 1868 strncpy(lp->d_typename, "floppy", sizeof(lp->d_typename)); 1869 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 1870 lp->d_interleave = 1; 1871 1872 lp->d_partitions[RAW_PART].p_offset = 0; 1873 lp->d_partitions[RAW_PART].p_size = lp->d_secpercyl * lp->d_ncylinders; 1874 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 1875 lp->d_npartitions = RAW_PART + 1; 1876 1877 lp->d_magic = DISKMAGIC; 1878 lp->d_magic2 = DISKMAGIC; 1879 lp->d_checksum = dkcksum(lp); 1880 1881 /* 1882 * Call the generic disklabel extraction routine. If there's 1883 * not a label there, fake it. 1884 */ 1885 if (readdisklabel(dev, fdstrategy, lp, clp) != NULL) { 1886 strncpy(lp->d_packname, "default label", 1887 sizeof(lp->d_packname)); 1888 /* 1889 * Reset the partition info; it might have gotten 1890 * trashed in readdisklabel(). 1891 * 1892 * XXX Why do we have to do this? readdisklabel() 1893 * should be safe... 1894 */ 1895 for (i = 0; i < MAXPARTITIONS; ++i) { 1896 lp->d_partitions[i].p_offset = 0; 1897 if (i == RAW_PART) { 1898 lp->d_partitions[i].p_size = 1899 lp->d_secpercyl * lp->d_ncylinders; 1900 lp->d_partitions[i].p_fstype = FS_BSDFFS; 1901 } else { 1902 lp->d_partitions[i].p_size = 0; 1903 lp->d_partitions[i].p_fstype = FS_UNUSED; 1904 } 1905 } 1906 lp->d_npartitions = RAW_PART + 1; 1907 } 1908 } 1909 1910 void 1911 fd_do_eject(struct fdc_softc *fdc, int unit) 1912 { 1913 1914 fdc->sc_fcr |= FCR_DSEL(unit)|FCR_EJECT; 1915 FCR_REG_SYNC(); 1916 delay(10); 1917 fdc->sc_fcr &= ~(FCR_DSEL(unit)|FCR_EJECT); 1918 FCR_REG_SYNC(); 1919 } 1920 1921 #ifdef MEMORY_DISK_HOOKS_sun3x_not_yet 1922 int fd_read_md_image(size_t *, void **); 1923 #endif 1924 1925 /* ARGSUSED */ 1926 void 1927 fd_mountroot_hook(device_t dev) 1928 { 1929 struct fd_softc *fd; 1930 struct fdc_softc *fdc; 1931 int c; 1932 1933 fd = device_private(dev); 1934 fdc = device_private(device_parent(dev)); 1935 fd_do_eject(fdc, fd->sc_drive); 1936 printf("Insert filesystem floppy and press return."); 1937 for (;;) { 1938 c = cngetc(); 1939 if ((c == '\r') || (c == '\n')) { 1940 printf("\n"); 1941 break; 1942 } 1943 } 1944 #ifdef MEMORY_DISK_HOOKS_sun3x_not_yet 1945 { 1946 extern int (*md_read_image)(size_t *, void **); 1947 1948 md_read_image = fd_read_md_image; 1949 } 1950 #endif 1951 } 1952 1953 #ifdef MEMORY_DISK_HOOKS_sun3x_not_yet 1954 1955 #define FDMICROROOTSIZE ((2*18*80) << DEV_BSHIFT) 1956 1957 int 1958 fd_read_md_image(size_t *sizep, void **addrp) 1959 { 1960 struct fdc_softc *fdc; 1961 struct fd_softc *fd; 1962 struct buf buf, *bp = &buf; 1963 dev_t dev; 1964 off_t offset; 1965 void *addr; 1966 1967 dev = makedev(cdevsw_lookup_major(&fd_cdevsw), 0); /* XXX */ 1968 1969 addr = malloc(FDMICROROOTSIZE, M_DEVBUF, M_WAITOK); 1970 *addrp = addr; 1971 1972 if (fdopen(dev, 0, S_IFCHR, NULL)) 1973 panic("fd: mountroot: fdopen"); 1974 1975 offset = 0; 1976 1977 for (;;) { 1978 bp->b_dev = dev; 1979 bp->b_error = 0; 1980 bp->b_resid = 0; 1981 bp->b_proc = NULL; 1982 bp->b_flags = B_PHYS | B_RAW | B_READ; 1983 bp->b_cflags = BC_BUSY; 1984 bp->b_blkno = btodb(offset); 1985 bp->b_bcount = DEV_BSIZE; 1986 bp->b_data = addr; 1987 fdstrategy(bp); 1988 biowait(bp); 1989 if (bp->b_error) 1990 panic("fd: mountroot: fdread error %d", bp->b_error); 1991 1992 if (bp->b_resid != 0) 1993 break; 1994 1995 addr += DEV_BSIZE; 1996 offset += DEV_BSIZE; 1997 if (offset + DEV_BSIZE > FDMICROROOTSIZE) 1998 break; 1999 } 2000 (void)fdclose(dev, 0, S_IFCHR, NULL); 2001 *sizep = offset; 2002 fd = device_lookup_private(&fd_cd, 0); 2003 fdc = device_private(device_parent(fd->sc_dv)); 2004 fd_do_eject(fdc, 0); /* XXX */ 2005 return 0; 2006 } 2007 #endif 2008