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