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