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