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