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