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