1 /* $NetBSD: fd.c,v 1.36 2003/01/25 23:18:46 kleink Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /*- 40 * Copyright (c) 1990 The Regents of the University of California. 41 * All rights reserved. 42 * 43 * This code is derived from software contributed to Berkeley by 44 * Don Ahn. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. All advertising materials mentioning features or use of this software 55 * must display the following acknowledgement: 56 * This product includes software developed by the University of 57 * California, Berkeley and its contributors. 58 * 4. Neither the name of the University nor the names of its contributors 59 * may be used to endorse or promote products derived from this software 60 * without specific prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72 * SUCH DAMAGE. 73 * 74 * @(#)fd.c 7.4 (Berkeley) 5/25/91 75 */ 76 77 /* 78 * Floppy formatting facilities merged from FreeBSD fd.c driver: 79 * Id: fd.c,v 1.53 1995/03/12 22:40:56 joerg Exp 80 * which carries the same copyright/redistribution notice as shown above with 81 * the addition of the following statement before the "Redistribution and 82 * use ..." clause: 83 * 84 * Copyright (c) 1993, 1994 by 85 * jc@irbs.UUCP (John Capo) 86 * vak@zebub.msk.su (Serge Vakulenko) 87 * ache@astral.msk.su (Andrew A. Chernov) 88 * 89 * Copyright (c) 1993, 1994, 1995 by 90 * joerg_wunsch@uriah.sax.de (Joerg Wunsch) 91 * dufault@hda.com (Peter Dufault) 92 */ 93 94 #include <sys/cdefs.h> 95 __KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.36 2003/01/25 23:18:46 kleink Exp $"); 96 97 #include "rnd.h" 98 #include "opt_ddb.h" 99 100 /* 101 * XXX This driver should be properly MI'd some day, but this allows us 102 * XXX to eliminate a lot of code duplication for now. 103 */ 104 #if !defined(alpha) && !defined(algor) && !defined(atari) && \ 105 !defined(bebox) && !defined(evbmips) && !defined(i386) && \ 106 !defined(prep) && !defined(sandpoint) && !defined(x86_64) 107 #error platform not supported by this driver, yet 108 #endif 109 110 #include <sys/param.h> 111 #include <sys/systm.h> 112 #include <sys/callout.h> 113 #include <sys/kernel.h> 114 #include <sys/file.h> 115 #include <sys/ioctl.h> 116 #include <sys/device.h> 117 #include <sys/disklabel.h> 118 #include <sys/dkstat.h> 119 #include <sys/disk.h> 120 #include <sys/buf.h> 121 #include <sys/malloc.h> 122 #include <sys/uio.h> 123 #include <sys/syslog.h> 124 #include <sys/queue.h> 125 #include <sys/proc.h> 126 #include <sys/fdio.h> 127 #include <sys/conf.h> 128 #if NRND > 0 129 #include <sys/rnd.h> 130 #endif 131 132 #include <uvm/uvm_extern.h> 133 134 #include <dev/cons.h> 135 136 #include <machine/cpu.h> 137 #include <machine/bus.h> 138 139 #if defined(atari) 140 /* 141 * On the atari, it is configured as fdcisa 142 */ 143 #define FDCCF_DRIVE FDCISACF_DRIVE 144 #define FDCCF_DRIVE_DEFAULT FDCISACF_DRIVE_DEFAULT 145 146 #define fd_cd fdisa_cd 147 #define fd_ca fdisa_ca 148 #endif /* atari */ 149 150 #include <machine/intr.h> 151 152 #include <dev/isa/isavar.h> 153 #include <dev/isa/isadmavar.h> 154 155 #include <dev/isa/fdreg.h> 156 #include <dev/isa/fdcvar.h> 157 158 #if defined(i386) 159 160 #include <dev/ic/mc146818reg.h> /* for NVRAM access */ 161 #include <i386/isa/nvram.h> 162 163 #include "mca.h" 164 #if NMCA > 0 165 #include <machine/mca_machdep.h> /* for MCA_system */ 166 #endif 167 168 #endif /* i386 */ 169 170 #include <dev/isa/fdvar.h> 171 172 #define FDUNIT(dev) (minor(dev) / 8) 173 #define FDTYPE(dev) (minor(dev) % 8) 174 175 /* XXX misuse a flag to identify format operation */ 176 #define B_FORMAT B_XXX 177 178 /* controller driver configuration */ 179 int fdprint __P((void *, const char *)); 180 181 #if NMCA > 0 182 /* MCA - specific entries */ 183 const struct fd_type mca_fd_types[] = { 184 { 18,2,36,2,0xff,0x0f,0x1b,0x6c,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB" }, /* 1.44MB diskette - XXX try 16ms step rate */ 185 { 9,2,18,2,0xff,0x4f,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB" }, /* 3.5 inch 720kB diskette - XXX try 24ms step rate */ 186 }; 187 #endif /* NMCA > 0 */ 188 189 /* The order of entries in the following table is important -- BEWARE! */ 190 191 #if defined(atari) 192 const struct fd_type fd_types[] = { 193 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS,0xf6,1, "360KB/PC" }, /* 360kB PC diskettes */ 194 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB" }, /* 3.5 inch 720kB diskette */ 195 { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB" }, /* 1.44MB diskette */ 196 }; 197 #else 198 const struct fd_type fd_types[] = { 199 { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB" }, /* 1.44MB diskette */ 200 { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS,0xf6,1, "1.2MB" }, /* 1.2 MB AT-diskettes */ 201 { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS,0xf6,1, "360KB/AT" }, /* 360kB in 1.2MB drive */ 202 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS,0xf6,1, "360KB/PC" }, /* 360kB PC diskettes */ 203 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB" }, /* 3.5 inch 720kB diskette */ 204 { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS,0xf6,1, "720KB/x" }, /* 720kB in 1.2MB drive */ 205 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,0xf6,1, "360KB/x" }, /* 360kB in 720kB drive */ 206 }; 207 #endif /* defined(atari) */ 208 209 int fdprobe __P((struct device *, struct cfdata *, void *)); 210 void fdattach __P((struct device *, struct device *, void *)); 211 212 extern struct cfdriver fd_cd; 213 214 CFATTACH_DECL(fd, sizeof(struct fd_softc), 215 fdprobe, fdattach, NULL, NULL); 216 217 dev_type_open(fdopen); 218 dev_type_close(fdclose); 219 dev_type_read(fdread); 220 dev_type_write(fdwrite); 221 dev_type_ioctl(fdioctl); 222 dev_type_strategy(fdstrategy); 223 224 const struct bdevsw fd_bdevsw = { 225 fdopen, fdclose, fdstrategy, fdioctl, nodump, nosize, D_DISK 226 }; 227 228 const struct cdevsw fd_cdevsw = { 229 fdopen, fdclose, fdread, fdwrite, fdioctl, 230 nostop, notty, nopoll, nommap, nokqfilter, D_DISK 231 }; 232 233 void fdgetdisklabel __P((struct fd_softc *)); 234 int fd_get_parms __P((struct fd_softc *)); 235 void fdstart __P((struct fd_softc *)); 236 237 struct dkdriver fddkdriver = { fdstrategy }; 238 239 #if defined(i386) 240 const struct fd_type *fd_nvtotype __P((char *, int, int)); 241 #endif /* i386 */ 242 void fd_set_motor __P((struct fdc_softc *fdc, int reset)); 243 void fd_motor_off __P((void *arg)); 244 void fd_motor_on __P((void *arg)); 245 int fdcresult __P((struct fdc_softc *fdc)); 246 void fdcstart __P((struct fdc_softc *fdc)); 247 void fdcstatus __P((struct device *dv, int n, char *s)); 248 void fdctimeout __P((void *arg)); 249 void fdcpseudointr __P((void *arg)); 250 void fdcretry __P((struct fdc_softc *fdc)); 251 void fdfinish __P((struct fd_softc *fd, struct buf *bp)); 252 __inline const struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t)); 253 int fdformat __P((dev_t, struct ne7_fd_formb *, struct proc *)); 254 255 void fd_mountroot_hook __P((struct device *)); 256 257 /* 258 * Arguments passed between fdcattach and fdprobe. 259 */ 260 struct fdc_attach_args { 261 int fa_drive; 262 const struct fd_type *fa_deftype; 263 }; 264 265 /* 266 * Print the location of a disk drive (called just before attaching the 267 * the drive). If `fdc' is not NULL, the drive was found but was not 268 * in the system config file; print the drive name as well. 269 * Return QUIET (config_find ignores this if the device was configured) to 270 * avoid printing `fdN not configured' messages. 271 */ 272 int 273 fdprint(aux, fdc) 274 void *aux; 275 const char *fdc; 276 { 277 register struct fdc_attach_args *fa = aux; 278 279 if (!fdc) 280 aprint_normal(" drive %d", fa->fa_drive); 281 return QUIET; 282 } 283 284 void 285 fdcattach(fdc) 286 struct fdc_softc *fdc; 287 { 288 struct fdc_attach_args fa; 289 bus_space_tag_t iot; 290 bus_space_handle_t ioh; 291 #if defined(i386) 292 int type; 293 #endif 294 295 iot = fdc->sc_iot; 296 ioh = fdc->sc_ioh; 297 callout_init(&fdc->sc_timo_ch); 298 callout_init(&fdc->sc_intr_ch); 299 300 fdc->sc_state = DEVIDLE; 301 TAILQ_INIT(&fdc->sc_drives); 302 303 fdc->sc_maxiosize = isa_dmamaxsize(fdc->sc_ic, fdc->sc_drq); 304 305 if (isa_dmamap_create(fdc->sc_ic, fdc->sc_drq, fdc->sc_maxiosize, 306 BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) { 307 printf("%s: can't set up ISA DMA map\n", 308 fdc->sc_dev.dv_xname); 309 return; 310 } 311 312 /* 313 * Reset the controller to get it into a known state. Not all 314 * probes necessarily need do this to discover the controller up 315 * front, so don't assume anything. 316 */ 317 318 bus_space_write_1(iot, ioh, fdout, 0); 319 delay(100); 320 bus_space_write_1(iot, ioh, fdout, FDO_FRST); 321 322 /* see if it can handle a command */ 323 if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0) { 324 printf ("%s: can't reset controller\n", fdc->sc_dev.dv_xname); 325 return; 326 } 327 out_fdc(iot, ioh, 0xdf); 328 out_fdc(iot, ioh, 2); 329 330 #if defined(i386) 331 /* 332 * The NVRAM info only tells us about the first two disks on the 333 * `primary' floppy controller. 334 */ 335 if (fdc->sc_dev.dv_unit == 0) 336 type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */ 337 else 338 type = -1; 339 #endif /* i386 */ 340 341 /* physical limit: four drives per controller. */ 342 for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) { 343 if (fdc->sc_known) { 344 if (fdc->sc_present & (1 << fa.fa_drive)) { 345 fa.fa_deftype = fdc->sc_knownfds[fa.fa_drive]; 346 config_found(&fdc->sc_dev, (void *)&fa, 347 fdprint); 348 } 349 } else { 350 #if defined(i386) 351 if (type >= 0 && fa.fa_drive < 2) 352 fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname, 353 type, fa.fa_drive); 354 else 355 fa.fa_deftype = NULL; /* unknown */ 356 #elif defined(atari) 357 /* 358 * Atari has a different ordening, defaults to 1.44 359 */ 360 fa.fa_deftype = &fd_types[2]; 361 #else 362 /* 363 * Default to 1.44MB on Alpha and BeBox. How do we tell 364 * on these platforms? 365 */ 366 fa.fa_deftype = &fd_types[0]; 367 #endif /* i386 */ 368 (void)config_found(&fdc->sc_dev, (void *)&fa, fdprint); 369 } 370 } 371 } 372 373 int 374 fdprobe(parent, match, aux) 375 struct device *parent; 376 struct cfdata *match; 377 void *aux; 378 { 379 struct fdc_softc *fdc = (void *)parent; 380 struct cfdata *cf = match; 381 struct fdc_attach_args *fa = aux; 382 int drive = fa->fa_drive; 383 bus_space_tag_t iot = fdc->sc_iot; 384 bus_space_handle_t ioh = fdc->sc_ioh; 385 int n; 386 387 if (cf->cf_loc[FDCCF_DRIVE] != FDCCF_DRIVE_DEFAULT && 388 cf->cf_loc[FDCCF_DRIVE] != drive) 389 return 0; 390 /* 391 * XXX 392 * This is to work around some odd interactions between this driver 393 * and SMC Ethernet cards. 394 */ 395 if (cf->cf_loc[FDCCF_DRIVE] == FDCCF_DRIVE_DEFAULT && drive >= 2) 396 return 0; 397 398 /* Use PNP information if available */ 399 if (fdc->sc_known) 400 return 1; 401 402 /* select drive and turn on motor */ 403 bus_space_write_1(iot, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive)); 404 /* wait for motor to spin up */ 405 delay(250000); 406 out_fdc(iot, ioh, NE7CMD_RECAL); 407 out_fdc(iot, ioh, drive); 408 /* wait for recalibrate */ 409 delay(2000000); 410 out_fdc(iot, ioh, NE7CMD_SENSEI); 411 n = fdcresult(fdc); 412 #ifdef FD_DEBUG 413 { 414 int i; 415 printf("fdprobe: status"); 416 for (i = 0; i < n; i++) 417 printf(" %x", fdc->sc_status[i]); 418 printf("\n"); 419 } 420 #endif 421 /* turn off motor */ 422 bus_space_write_1(iot, ioh, fdout, FDO_FRST); 423 424 #if defined(bebox) /* XXX What is this about? --thorpej@netbsd.org */ 425 if (n != 2 || (fdc->sc_status[1] != 0)) 426 return 0; 427 #else 428 if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20) 429 return 0; 430 #endif /* bebox */ 431 432 return 1; 433 } 434 435 /* 436 * Controller is working, and drive responded. Attach it. 437 */ 438 void 439 fdattach(parent, self, aux) 440 struct device *parent, *self; 441 void *aux; 442 { 443 struct fdc_softc *fdc = (void *)parent; 444 struct fd_softc *fd = (void *)self; 445 struct fdc_attach_args *fa = aux; 446 const struct fd_type *type = fa->fa_deftype; 447 int drive = fa->fa_drive; 448 449 callout_init(&fd->sc_motoron_ch); 450 callout_init(&fd->sc_motoroff_ch); 451 452 /* XXX Allow `flags' to override device type? */ 453 454 if (type) 455 printf(": %s, %d cyl, %d head, %d sec\n", type->name, 456 type->cyls, type->heads, type->sectrac); 457 else 458 printf(": density unknown\n"); 459 460 bufq_alloc(&fd->sc_q, BUFQ_DISKSORT|BUFQ_SORT_CYLINDER); 461 fd->sc_cylin = -1; 462 fd->sc_drive = drive; 463 fd->sc_deftype = type; 464 fdc->sc_fd[drive] = fd; 465 466 /* 467 * Initialize and attach the disk structure. 468 */ 469 fd->sc_dk.dk_name = fd->sc_dev.dv_xname; 470 fd->sc_dk.dk_driver = &fddkdriver; 471 disk_attach(&fd->sc_dk); 472 473 /* 474 * Establish a mountroot hook. 475 */ 476 mountroothook_establish(fd_mountroot_hook, &fd->sc_dev); 477 478 /* Needed to power off if the motor is on when we halt. */ 479 fd->sc_sdhook = shutdownhook_establish(fd_motor_off, fd); 480 481 #if NRND > 0 482 rnd_attach_source(&fd->rnd_source, fd->sc_dev.dv_xname, 483 RND_TYPE_DISK, 0); 484 #endif 485 } 486 487 #if defined(i386) 488 /* 489 * Translate nvram type into internal data structure. Return NULL for 490 * none/unknown/unusable. 491 */ 492 const struct fd_type * 493 fd_nvtotype(fdc, nvraminfo, drive) 494 char *fdc; 495 int nvraminfo, drive; 496 { 497 int type; 498 499 type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0; 500 switch (type) { 501 case NVRAM_DISKETTE_NONE: 502 return NULL; 503 case NVRAM_DISKETTE_12M: 504 return &fd_types[1]; 505 case NVRAM_DISKETTE_TYPE5: 506 case NVRAM_DISKETTE_TYPE6: 507 /* XXX We really ought to handle 2.88MB format. */ 508 case NVRAM_DISKETTE_144M: 509 #if NMCA > 0 510 if (MCA_system) 511 return &mca_fd_types[0]; 512 else 513 #endif /* NMCA > 0 */ 514 return &fd_types[0]; 515 case NVRAM_DISKETTE_360K: 516 return &fd_types[3]; 517 case NVRAM_DISKETTE_720K: 518 #if NMCA > 0 519 if (MCA_system) 520 return &mca_fd_types[1]; 521 else 522 #endif /* NMCA > 0 */ 523 return &fd_types[4]; 524 default: 525 printf("%s: drive %d: unknown device type 0x%x\n", 526 fdc, drive, type); 527 return NULL; 528 } 529 } 530 #endif /* i386 */ 531 532 __inline const struct fd_type * 533 fd_dev_to_type(fd, dev) 534 struct fd_softc *fd; 535 dev_t dev; 536 { 537 u_int type = FDTYPE(dev); 538 539 if (type > (sizeof(fd_types) / sizeof(fd_types[0]))) 540 return NULL; 541 return type ? &fd_types[type - 1] : fd->sc_deftype; 542 } 543 544 void 545 fdstrategy(bp) 546 register struct buf *bp; /* IO operation to perform */ 547 { 548 struct fd_softc *fd = device_lookup(&fd_cd, FDUNIT(bp->b_dev)); 549 int sz; 550 int s; 551 552 /* Valid unit, controller, and request? */ 553 if (bp->b_blkno < 0 || 554 ((bp->b_bcount % FDC_BSIZE) != 0 && 555 (bp->b_flags & B_FORMAT) == 0)) { 556 bp->b_error = EINVAL; 557 goto bad; 558 } 559 560 /* If it's a null transfer, return immediately. */ 561 if (bp->b_bcount == 0) 562 goto done; 563 564 sz = howmany(bp->b_bcount, FDC_BSIZE); 565 566 if (bp->b_blkno + sz > fd->sc_type->size) { 567 sz = fd->sc_type->size - bp->b_blkno; 568 if (sz == 0) { 569 /* If exactly at end of disk, return EOF. */ 570 goto done; 571 } 572 if (sz < 0) { 573 /* If past end of disk, return EINVAL. */ 574 bp->b_error = EINVAL; 575 goto bad; 576 } 577 /* Otherwise, truncate request. */ 578 bp->b_bcount = sz << DEV_BSHIFT; 579 } 580 581 bp->b_rawblkno = bp->b_blkno; 582 bp->b_cylinder = 583 bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl; 584 585 #ifdef FD_DEBUG 586 printf("fdstrategy: b_blkno %d b_bcount %ld blkno %d cylin %ld sz %d\n", 587 bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylinder, sz); 588 #endif 589 590 /* Queue transfer on drive, activate drive and controller if idle. */ 591 s = splbio(); 592 BUFQ_PUT(&fd->sc_q, bp); 593 callout_stop(&fd->sc_motoroff_ch); /* a good idea */ 594 if (fd->sc_active == 0) 595 fdstart(fd); 596 #ifdef DIAGNOSTIC 597 else { 598 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; 599 if (fdc->sc_state == DEVIDLE) { 600 printf("fdstrategy: controller inactive\n"); 601 fdcstart(fdc); 602 } 603 } 604 #endif 605 splx(s); 606 return; 607 608 bad: 609 bp->b_flags |= B_ERROR; 610 done: 611 /* Toss transfer; we're done early. */ 612 bp->b_resid = bp->b_bcount; 613 biodone(bp); 614 } 615 616 void 617 fdstart(fd) 618 struct fd_softc *fd; 619 { 620 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; 621 int active = !TAILQ_EMPTY(&fdc->sc_drives); 622 623 /* Link into controller queue. */ 624 fd->sc_active = 1; 625 TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); 626 627 /* If controller not already active, start it. */ 628 if (!active) 629 fdcstart(fdc); 630 } 631 632 void 633 fdfinish(fd, bp) 634 struct fd_softc *fd; 635 struct buf *bp; 636 { 637 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; 638 639 /* 640 * Move this drive to the end of the queue to give others a `fair' 641 * chance. We only force a switch if N operations are completed while 642 * another drive is waiting to be serviced, since there is a long motor 643 * startup delay whenever we switch. 644 */ 645 (void)BUFQ_GET(&fd->sc_q); 646 if (TAILQ_NEXT(fd, sc_drivechain) && ++fd->sc_ops >= 8) { 647 fd->sc_ops = 0; 648 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); 649 if (BUFQ_PEEK(&fd->sc_q) != NULL) 650 TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); 651 else 652 fd->sc_active = 0; 653 } 654 bp->b_resid = fd->sc_bcount; 655 fd->sc_skip = 0; 656 657 #if NRND > 0 658 rnd_add_uint32(&fd->rnd_source, bp->b_blkno); 659 #endif 660 661 biodone(bp); 662 /* turn off motor 5s from now */ 663 callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd); 664 fdc->sc_state = DEVIDLE; 665 } 666 667 int 668 fdread(dev, uio, flags) 669 dev_t dev; 670 struct uio *uio; 671 int flags; 672 { 673 674 return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio)); 675 } 676 677 int 678 fdwrite(dev, uio, flags) 679 dev_t dev; 680 struct uio *uio; 681 int flags; 682 { 683 684 return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio)); 685 } 686 687 void 688 fd_set_motor(fdc, reset) 689 struct fdc_softc *fdc; 690 int reset; 691 { 692 struct fd_softc *fd; 693 u_char status; 694 int n; 695 696 if ((fd = TAILQ_FIRST(&fdc->sc_drives)) != NULL) 697 status = fd->sc_drive; 698 else 699 status = 0; 700 if (!reset) 701 status |= FDO_FRST | FDO_FDMAEN; 702 for (n = 0; n < 4; n++) 703 if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR)) 704 status |= FDO_MOEN(n); 705 bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, status); 706 } 707 708 void 709 fd_motor_off(arg) 710 void *arg; 711 { 712 struct fd_softc *fd = arg; 713 int s; 714 715 s = splbio(); 716 fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); 717 fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0); 718 splx(s); 719 } 720 721 void 722 fd_motor_on(arg) 723 void *arg; 724 { 725 struct fd_softc *fd = arg; 726 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; 727 int s; 728 729 s = splbio(); 730 fd->sc_flags &= ~FD_MOTOR_WAIT; 731 if ((TAILQ_FIRST(&fdc->sc_drives) == fd) &&(fdc->sc_state == MOTORWAIT)) 732 (void) fdcintr(fdc); 733 splx(s); 734 } 735 736 int 737 fdcresult(fdc) 738 struct fdc_softc *fdc; 739 { 740 bus_space_tag_t iot = fdc->sc_iot; 741 bus_space_handle_t ioh = fdc->sc_ioh; 742 u_char i; 743 u_int j = 100000, 744 n = 0; 745 746 for (; j; j--) { 747 i = bus_space_read_1(iot, ioh, fdsts) & 748 (NE7_DIO | NE7_RQM | NE7_CB); 749 if (i == NE7_RQM) 750 return n; 751 if (i == (NE7_DIO | NE7_RQM | NE7_CB)) { 752 if (n >= sizeof(fdc->sc_status)) { 753 log(LOG_ERR, "fdcresult: overrun\n"); 754 return -1; 755 } 756 fdc->sc_status[n++] = 757 bus_space_read_1(iot, ioh, fddata); 758 } 759 delay(10); 760 } 761 log(LOG_ERR, "fdcresult: timeout\n"); 762 return -1; 763 } 764 765 int 766 out_fdc(iot, ioh, x) 767 bus_space_tag_t iot; 768 bus_space_handle_t ioh; 769 u_char x; 770 { 771 int i = 100000; 772 773 while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0); 774 if (i <= 0) 775 return -1; 776 while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0); 777 if (i <= 0) 778 return -1; 779 bus_space_write_1(iot, ioh, fddata, x); 780 return 0; 781 } 782 783 int 784 fdopen(dev, flags, mode, p) 785 dev_t dev; 786 int flags; 787 int mode; 788 struct proc *p; 789 { 790 struct fd_softc *fd; 791 const struct fd_type *type; 792 793 fd = device_lookup(&fd_cd, FDUNIT(dev)); 794 if (fd == NULL) 795 return (ENXIO); 796 797 type = fd_dev_to_type(fd, dev); 798 if (type == NULL) 799 return ENXIO; 800 801 if ((fd->sc_flags & FD_OPEN) != 0 && 802 memcmp(fd->sc_type, type, sizeof(*type))) 803 return EBUSY; 804 805 fd->sc_type_copy = *type; 806 fd->sc_type = &fd->sc_type_copy; 807 fd->sc_cylin = -1; 808 fd->sc_flags |= FD_OPEN; 809 810 return 0; 811 } 812 813 int 814 fdclose(dev, flags, mode, p) 815 dev_t dev; 816 int flags; 817 int mode; 818 struct proc *p; 819 { 820 struct fd_softc *fd = device_lookup(&fd_cd, FDUNIT(dev)); 821 822 fd->sc_flags &= ~FD_OPEN; 823 fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT); 824 return 0; 825 } 826 827 void 828 fdcstart(fdc) 829 struct fdc_softc *fdc; 830 { 831 832 #ifdef DIAGNOSTIC 833 /* only got here if controller's drive queue was inactive; should 834 be in idle state */ 835 if (fdc->sc_state != DEVIDLE) { 836 printf("fdcstart: not idle\n"); 837 return; 838 } 839 #endif 840 (void) fdcintr(fdc); 841 } 842 843 void 844 fdcstatus(dv, n, s) 845 struct device *dv; 846 int n; 847 char *s; 848 { 849 struct fdc_softc *fdc = (void *)dv->dv_parent; 850 char bits[64]; 851 852 if (n == 0) { 853 out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI); 854 (void) fdcresult(fdc); 855 n = 2; 856 } 857 858 printf("%s: %s", dv->dv_xname, s); 859 860 switch (n) { 861 case 0: 862 printf("\n"); 863 break; 864 case 2: 865 printf(" (st0 %s cyl %d)\n", 866 bitmask_snprintf(fdc->sc_status[0], NE7_ST0BITS, 867 bits, sizeof(bits)), fdc->sc_status[1]); 868 break; 869 case 7: 870 printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0], 871 NE7_ST0BITS, bits, sizeof(bits))); 872 printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1], 873 NE7_ST1BITS, bits, sizeof(bits))); 874 printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2], 875 NE7_ST2BITS, bits, sizeof(bits))); 876 printf(" cyl %d head %d sec %d)\n", 877 fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]); 878 break; 879 #ifdef DIAGNOSTIC 880 default: 881 printf("\nfdcstatus: weird size"); 882 break; 883 #endif 884 } 885 } 886 887 void 888 fdctimeout(arg) 889 void *arg; 890 { 891 struct fdc_softc *fdc = arg; 892 struct fd_softc *fd = TAILQ_FIRST(&fdc->sc_drives); 893 int s; 894 895 s = splbio(); 896 #ifdef DEBUG 897 log(LOG_ERR, "fdctimeout: state %d\n", fdc->sc_state); 898 #endif 899 fdcstatus(&fd->sc_dev, 0, "timeout"); 900 901 if (BUFQ_PEEK(&fd->sc_q) != NULL) 902 fdc->sc_state++; 903 else 904 fdc->sc_state = DEVIDLE; 905 906 (void) fdcintr(fdc); 907 splx(s); 908 } 909 910 void 911 fdcpseudointr(arg) 912 void *arg; 913 { 914 int s; 915 916 /* Just ensure it has the right spl. */ 917 s = splbio(); 918 (void) fdcintr(arg); 919 splx(s); 920 } 921 922 int 923 fdcintr(arg) 924 void *arg; 925 { 926 struct fdc_softc *fdc = arg; 927 #define st0 fdc->sc_status[0] 928 #define cyl fdc->sc_status[1] 929 struct fd_softc *fd; 930 struct buf *bp; 931 bus_space_tag_t iot = fdc->sc_iot; 932 bus_space_handle_t ioh = fdc->sc_ioh; 933 int read, head, sec, i, nblks; 934 struct fd_type *type; 935 struct ne7_fd_formb *finfo = NULL; 936 937 loop: 938 /* Is there a drive for the controller to do a transfer with? */ 939 fd = TAILQ_FIRST(&fdc->sc_drives); 940 if (fd == NULL) { 941 fdc->sc_state = DEVIDLE; 942 return 1; 943 } 944 945 /* Is there a transfer to this drive? If not, deactivate drive. */ 946 bp = BUFQ_PEEK(&fd->sc_q); 947 if (bp == NULL) { 948 fd->sc_ops = 0; 949 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); 950 fd->sc_active = 0; 951 goto loop; 952 } 953 954 if (bp->b_flags & B_FORMAT) 955 finfo = (struct ne7_fd_formb *)bp->b_data; 956 957 switch (fdc->sc_state) { 958 case DEVIDLE: 959 fdc->sc_errors = 0; 960 fd->sc_skip = 0; 961 fd->sc_bcount = bp->b_bcount; 962 fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE); 963 callout_stop(&fd->sc_motoroff_ch); 964 if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) { 965 fdc->sc_state = MOTORWAIT; 966 return 1; 967 } 968 if ((fd->sc_flags & FD_MOTOR) == 0) { 969 /* Turn on the motor, being careful about pairing. */ 970 struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1]; 971 if (ofd && ofd->sc_flags & FD_MOTOR) { 972 callout_stop(&ofd->sc_motoroff_ch); 973 ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); 974 } 975 fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT; 976 fd_set_motor(fdc, 0); 977 fdc->sc_state = MOTORWAIT; 978 /* Allow .25s for motor to stabilize. */ 979 callout_reset(&fd->sc_motoron_ch, hz / 4, 980 fd_motor_on, fd); 981 return 1; 982 } 983 /* Make sure the right drive is selected. */ 984 fd_set_motor(fdc, 0); 985 986 /* fall through */ 987 case DOSEEK: 988 doseek: 989 if (fd->sc_cylin == bp->b_cylinder) 990 goto doio; 991 992 out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */ 993 out_fdc(iot, ioh, fd->sc_type->steprate); 994 out_fdc(iot, ioh, 6); /* XXX head load time == 6ms */ 995 996 out_fdc(iot, ioh, NE7CMD_SEEK); /* seek function */ 997 out_fdc(iot, ioh, fd->sc_drive); /* drive number */ 998 out_fdc(iot, ioh, bp->b_cylinder * fd->sc_type->step); 999 1000 fd->sc_cylin = -1; 1001 fdc->sc_state = SEEKWAIT; 1002 1003 fd->sc_dk.dk_seek++; 1004 disk_busy(&fd->sc_dk); 1005 1006 callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc); 1007 return 1; 1008 1009 case DOIO: 1010 doio: 1011 type = fd->sc_type; 1012 if (finfo) 1013 fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) - 1014 (char *)finfo; 1015 sec = fd->sc_blkno % type->seccyl; 1016 nblks = type->seccyl - sec; 1017 nblks = min(nblks, fd->sc_bcount / FDC_BSIZE); 1018 nblks = min(nblks, fdc->sc_maxiosize / FDC_BSIZE); 1019 fd->sc_nblks = nblks; 1020 fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE; 1021 head = sec / type->sectrac; 1022 sec -= head * type->sectrac; 1023 #ifdef DIAGNOSTIC 1024 { 1025 int block; 1026 block = (fd->sc_cylin * type->heads + head) 1027 * type->sectrac + sec; 1028 if (block != fd->sc_blkno) { 1029 printf("fdcintr: block %d != blkno " 1030 "%" PRId64 "\n", block, fd->sc_blkno); 1031 #ifdef DDB 1032 Debugger(); 1033 #endif 1034 } 1035 } 1036 #endif 1037 read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE; 1038 isa_dmastart(fdc->sc_ic, fdc->sc_drq, 1039 bp->b_data + fd->sc_skip, fd->sc_nbytes, 1040 NULL, read | DMAMODE_DEMAND, BUS_DMA_NOWAIT); 1041 bus_space_write_1(iot, fdc->sc_fdctlioh, 0, type->rate); 1042 #ifdef FD_DEBUG 1043 printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n", 1044 read ? "read" : "write", fd->sc_drive, fd->sc_cylin, 1045 head, sec, nblks); 1046 #endif 1047 if (finfo) { 1048 /* formatting */ 1049 if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) { 1050 fdc->sc_errors = 4; 1051 fdcretry(fdc); 1052 goto loop; 1053 } 1054 out_fdc(iot, ioh, (head << 2) | fd->sc_drive); 1055 out_fdc(iot, ioh, finfo->fd_formb_secshift); 1056 out_fdc(iot, ioh, finfo->fd_formb_nsecs); 1057 out_fdc(iot, ioh, finfo->fd_formb_gaplen); 1058 out_fdc(iot, ioh, finfo->fd_formb_fillbyte); 1059 } else { 1060 if (read) 1061 out_fdc(iot, ioh, NE7CMD_READ); /* READ */ 1062 else 1063 out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */ 1064 out_fdc(iot, ioh, (head << 2) | fd->sc_drive); 1065 out_fdc(iot, ioh, fd->sc_cylin); /* track */ 1066 out_fdc(iot, ioh, head); 1067 out_fdc(iot, ioh, sec + 1); /* sector +1 */ 1068 out_fdc(iot, ioh, type->secsize);/* sector size */ 1069 out_fdc(iot, ioh, type->sectrac);/* sectors/track */ 1070 out_fdc(iot, ioh, type->gap1); /* gap1 size */ 1071 out_fdc(iot, ioh, type->datalen);/* data length */ 1072 } 1073 fdc->sc_state = IOCOMPLETE; 1074 1075 disk_busy(&fd->sc_dk); 1076 1077 /* allow 2 seconds for operation */ 1078 callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc); 1079 return 1; /* will return later */ 1080 1081 case SEEKWAIT: 1082 callout_stop(&fdc->sc_timo_ch); 1083 fdc->sc_state = SEEKCOMPLETE; 1084 /* allow 1/50 second for heads to settle */ 1085 callout_reset(&fdc->sc_intr_ch, hz / 50, fdcpseudointr, fdc); 1086 return 1; 1087 1088 case SEEKCOMPLETE: 1089 /* no data on seek */ 1090 disk_unbusy(&fd->sc_dk, 0, 0); 1091 1092 /* Make sure seek really happened. */ 1093 out_fdc(iot, ioh, NE7CMD_SENSEI); 1094 if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || 1095 cyl != bp->b_cylinder * fd->sc_type->step) { 1096 #ifdef FD_DEBUG 1097 fdcstatus(&fd->sc_dev, 2, "seek failed"); 1098 #endif 1099 fdcretry(fdc); 1100 goto loop; 1101 } 1102 fd->sc_cylin = bp->b_cylinder; 1103 goto doio; 1104 1105 case IOTIMEDOUT: 1106 isa_dmaabort(fdc->sc_ic, fdc->sc_drq); 1107 case SEEKTIMEDOUT: 1108 case RECALTIMEDOUT: 1109 case RESETTIMEDOUT: 1110 fdcretry(fdc); 1111 goto loop; 1112 1113 case IOCOMPLETE: /* IO DONE, post-analyze */ 1114 callout_stop(&fdc->sc_timo_ch); 1115 1116 disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid), 1117 (bp->b_flags & B_READ)); 1118 1119 if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) { 1120 isa_dmaabort(fdc->sc_ic, fdc->sc_drq); 1121 #ifdef FD_DEBUG 1122 fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ? 1123 "read failed" : "write failed"); 1124 printf("blkno %d nblks %d\n", 1125 fd->sc_blkno, fd->sc_nblks); 1126 #endif 1127 fdcretry(fdc); 1128 goto loop; 1129 } 1130 isa_dmadone(fdc->sc_ic, fdc->sc_drq); 1131 if (fdc->sc_errors) { 1132 diskerr(bp, "fd", "soft error (corrected)", LOG_PRINTF, 1133 fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL); 1134 printf("\n"); 1135 fdc->sc_errors = 0; 1136 } 1137 fd->sc_blkno += fd->sc_nblks; 1138 fd->sc_skip += fd->sc_nbytes; 1139 fd->sc_bcount -= fd->sc_nbytes; 1140 if (!finfo && fd->sc_bcount > 0) { 1141 bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl; 1142 goto doseek; 1143 } 1144 fdfinish(fd, bp); 1145 goto loop; 1146 1147 case DORESET: 1148 /* try a reset, keep motor on */ 1149 fd_set_motor(fdc, 1); 1150 delay(100); 1151 fd_set_motor(fdc, 0); 1152 fdc->sc_state = RESETCOMPLETE; 1153 callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc); 1154 return 1; /* will return later */ 1155 1156 case RESETCOMPLETE: 1157 callout_stop(&fdc->sc_timo_ch); 1158 /* clear the controller output buffer */ 1159 for (i = 0; i < 4; i++) { 1160 out_fdc(iot, ioh, NE7CMD_SENSEI); 1161 (void) fdcresult(fdc); 1162 } 1163 1164 /* fall through */ 1165 case DORECAL: 1166 out_fdc(iot, ioh, NE7CMD_RECAL); /* recalibrate function */ 1167 out_fdc(iot, ioh, fd->sc_drive); 1168 fdc->sc_state = RECALWAIT; 1169 callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc); 1170 return 1; /* will return later */ 1171 1172 case RECALWAIT: 1173 callout_stop(&fdc->sc_timo_ch); 1174 fdc->sc_state = RECALCOMPLETE; 1175 /* allow 1/30 second for heads to settle */ 1176 callout_reset(&fdc->sc_intr_ch, hz / 30, fdcpseudointr, fdc); 1177 return 1; /* will return later */ 1178 1179 case RECALCOMPLETE: 1180 out_fdc(iot, ioh, NE7CMD_SENSEI); 1181 if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) { 1182 #ifdef FD_DEBUG 1183 fdcstatus(&fd->sc_dev, 2, "recalibrate failed"); 1184 #endif 1185 fdcretry(fdc); 1186 goto loop; 1187 } 1188 fd->sc_cylin = 0; 1189 goto doseek; 1190 1191 case MOTORWAIT: 1192 if (fd->sc_flags & FD_MOTOR_WAIT) 1193 return 1; /* time's not up yet */ 1194 goto doseek; 1195 1196 default: 1197 fdcstatus(&fd->sc_dev, 0, "stray interrupt"); 1198 return 1; 1199 } 1200 #ifdef DIAGNOSTIC 1201 panic("fdcintr: impossible"); 1202 #endif 1203 #undef st0 1204 #undef cyl 1205 } 1206 1207 void 1208 fdcretry(fdc) 1209 struct fdc_softc *fdc; 1210 { 1211 char bits[64]; 1212 struct fd_softc *fd; 1213 struct buf *bp; 1214 1215 fd = TAILQ_FIRST(&fdc->sc_drives); 1216 bp = BUFQ_PEEK(&fd->sc_q); 1217 1218 if (fd->sc_opts & FDOPT_NORETRY) 1219 goto fail; 1220 switch (fdc->sc_errors) { 1221 case 0: 1222 /* try again */ 1223 fdc->sc_state = DOSEEK; 1224 break; 1225 1226 case 1: case 2: case 3: 1227 /* didn't work; try recalibrating */ 1228 fdc->sc_state = DORECAL; 1229 break; 1230 1231 case 4: 1232 /* still no go; reset the bastard */ 1233 fdc->sc_state = DORESET; 1234 break; 1235 1236 default: 1237 fail: 1238 if ((fd->sc_opts & FDOPT_SILENT) == 0) { 1239 diskerr(bp, "fd", "hard error", LOG_PRINTF, 1240 fd->sc_skip / FDC_BSIZE, 1241 (struct disklabel *)NULL); 1242 1243 printf(" (st0 %s", 1244 bitmask_snprintf(fdc->sc_status[0], 1245 NE7_ST0BITS, bits, 1246 sizeof(bits))); 1247 printf(" st1 %s", 1248 bitmask_snprintf(fdc->sc_status[1], 1249 NE7_ST1BITS, bits, 1250 sizeof(bits))); 1251 printf(" st2 %s", 1252 bitmask_snprintf(fdc->sc_status[2], 1253 NE7_ST2BITS, bits, 1254 sizeof(bits))); 1255 printf(" cyl %d head %d sec %d)\n", 1256 fdc->sc_status[3], 1257 fdc->sc_status[4], 1258 fdc->sc_status[5]); 1259 } 1260 1261 bp->b_flags |= B_ERROR; 1262 bp->b_error = EIO; 1263 fdfinish(fd, bp); 1264 } 1265 fdc->sc_errors++; 1266 } 1267 1268 int 1269 fdioctl(dev, cmd, addr, flag, p) 1270 dev_t dev; 1271 u_long cmd; 1272 caddr_t addr; 1273 int flag; 1274 struct proc *p; 1275 { 1276 struct fd_softc *fd = device_lookup(&fd_cd, FDUNIT(dev)); 1277 struct fdformat_parms *form_parms; 1278 struct fdformat_cmd *form_cmd; 1279 struct ne7_fd_formb *fd_formb; 1280 struct disklabel buffer; 1281 int error; 1282 unsigned int scratch; 1283 int il[FD_MAX_NSEC + 1]; 1284 register int i, j; 1285 #ifdef __HAVE_OLD_DISKLABEL 1286 struct disklabel newlabel; 1287 #endif 1288 1289 switch (cmd) { 1290 case DIOCGDINFO: 1291 #ifdef __HAVE_OLD_DISKLABEL 1292 case ODIOCGDINFO: 1293 #endif 1294 memset(&buffer, 0, sizeof(buffer)); 1295 1296 buffer.d_secpercyl = fd->sc_type->seccyl; 1297 buffer.d_type = DTYPE_FLOPPY; 1298 buffer.d_secsize = FDC_BSIZE; 1299 1300 if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL) 1301 return EINVAL; 1302 1303 #ifdef __HAVE_OLD_DISKLABEL 1304 if (cmd == ODIOCGDINFO) { 1305 if (buffer.d_npartitions > OLDMAXPARTITIONS) 1306 return ENOTTY; 1307 memcpy(addr, &buffer, sizeof (struct olddisklabel)); 1308 } else 1309 #endif 1310 *(struct disklabel *)addr = buffer; 1311 return 0; 1312 1313 case DIOCWLABEL: 1314 if ((flag & FWRITE) == 0) 1315 return EBADF; 1316 /* XXX do something */ 1317 return 0; 1318 1319 case DIOCWDINFO: 1320 #ifdef __HAVE_OLD_DISKLABEL 1321 case ODIOCWDINFO: 1322 #endif 1323 { 1324 struct disklabel *lp; 1325 1326 if ((flag & FWRITE) == 0) 1327 return EBADF; 1328 #ifdef __HAVE_OLD_DISKLABEL 1329 if (cmd == ODIOCWDINFO) { 1330 memset(&newlabel, 0, sizeof newlabel); 1331 memcpy(&newlabel, addr, sizeof (struct olddisklabel)); 1332 lp = &newlabel; 1333 } else 1334 #endif 1335 lp = (struct disklabel *)addr; 1336 1337 error = setdisklabel(&buffer, lp, 0, NULL); 1338 if (error) 1339 return error; 1340 1341 error = writedisklabel(dev, fdstrategy, &buffer, NULL); 1342 return error; 1343 } 1344 1345 case FDIOCGETFORMAT: 1346 form_parms = (struct fdformat_parms *)addr; 1347 form_parms->fdformat_version = FDFORMAT_VERSION; 1348 form_parms->nbps = 128 * (1 << fd->sc_type->secsize); 1349 form_parms->ncyl = fd->sc_type->cyls; 1350 form_parms->nspt = fd->sc_type->sectrac; 1351 form_parms->ntrk = fd->sc_type->heads; 1352 form_parms->stepspercyl = fd->sc_type->step; 1353 form_parms->gaplen = fd->sc_type->gap2; 1354 form_parms->fillbyte = fd->sc_type->fillbyte; 1355 form_parms->interleave = fd->sc_type->interleave; 1356 switch (fd->sc_type->rate) { 1357 case FDC_500KBPS: 1358 form_parms->xfer_rate = 500 * 1024; 1359 break; 1360 case FDC_300KBPS: 1361 form_parms->xfer_rate = 300 * 1024; 1362 break; 1363 case FDC_250KBPS: 1364 form_parms->xfer_rate = 250 * 1024; 1365 break; 1366 default: 1367 return EINVAL; 1368 } 1369 return 0; 1370 1371 case FDIOCSETFORMAT: 1372 if((flag & FWRITE) == 0) 1373 return EBADF; /* must be opened for writing */ 1374 form_parms = (struct fdformat_parms *)addr; 1375 if (form_parms->fdformat_version != FDFORMAT_VERSION) 1376 return EINVAL; /* wrong version of formatting prog */ 1377 1378 scratch = form_parms->nbps >> 7; 1379 if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 || 1380 scratch & ~(1 << (ffs(scratch)-1))) 1381 /* not a power-of-two multiple of 128 */ 1382 return EINVAL; 1383 1384 switch (form_parms->xfer_rate) { 1385 case 500 * 1024: 1386 fd->sc_type->rate = FDC_500KBPS; 1387 break; 1388 case 300 * 1024: 1389 fd->sc_type->rate = FDC_300KBPS; 1390 break; 1391 case 250 * 1024: 1392 fd->sc_type->rate = FDC_250KBPS; 1393 break; 1394 default: 1395 return EINVAL; 1396 } 1397 1398 if (form_parms->nspt > FD_MAX_NSEC || 1399 form_parms->fillbyte > 0xff || 1400 form_parms->interleave > 0xff) 1401 return EINVAL; 1402 fd->sc_type->sectrac = form_parms->nspt; 1403 if (form_parms->ntrk != 2 && form_parms->ntrk != 1) 1404 return EINVAL; 1405 fd->sc_type->heads = form_parms->ntrk; 1406 fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk; 1407 fd->sc_type->secsize = ffs(scratch)-1; 1408 fd->sc_type->gap2 = form_parms->gaplen; 1409 fd->sc_type->cyls = form_parms->ncyl; 1410 fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl * 1411 form_parms->nbps / DEV_BSIZE; 1412 fd->sc_type->step = form_parms->stepspercyl; 1413 fd->sc_type->fillbyte = form_parms->fillbyte; 1414 fd->sc_type->interleave = form_parms->interleave; 1415 return 0; 1416 1417 case FDIOCFORMAT_TRACK: 1418 if((flag & FWRITE) == 0) 1419 return EBADF; /* must be opened for writing */ 1420 form_cmd = (struct fdformat_cmd *)addr; 1421 if (form_cmd->formatcmd_version != FDFORMAT_VERSION) 1422 return EINVAL; /* wrong version of formatting prog */ 1423 1424 if (form_cmd->head >= fd->sc_type->heads || 1425 form_cmd->cylinder >= fd->sc_type->cyls) { 1426 return EINVAL; 1427 } 1428 1429 fd_formb = malloc(sizeof(struct ne7_fd_formb), 1430 M_TEMP, M_NOWAIT); 1431 if (fd_formb == 0) 1432 return ENOMEM; 1433 1434 fd_formb->head = form_cmd->head; 1435 fd_formb->cyl = form_cmd->cylinder; 1436 fd_formb->transfer_rate = fd->sc_type->rate; 1437 fd_formb->fd_formb_secshift = fd->sc_type->secsize; 1438 fd_formb->fd_formb_nsecs = fd->sc_type->sectrac; 1439 fd_formb->fd_formb_gaplen = fd->sc_type->gap2; 1440 fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte; 1441 1442 memset(il, 0, sizeof il); 1443 for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) { 1444 while (il[(j%fd_formb->fd_formb_nsecs)+1]) 1445 j++; 1446 il[(j%fd_formb->fd_formb_nsecs)+1] = i; 1447 j += fd->sc_type->interleave; 1448 } 1449 for (i = 0; i < fd_formb->fd_formb_nsecs; i++) { 1450 fd_formb->fd_formb_cylno(i) = form_cmd->cylinder; 1451 fd_formb->fd_formb_headno(i) = form_cmd->head; 1452 fd_formb->fd_formb_secno(i) = il[i+1]; 1453 fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize; 1454 } 1455 1456 error = fdformat(dev, fd_formb, p); 1457 free(fd_formb, M_TEMP); 1458 return error; 1459 1460 case FDIOCGETOPTS: /* get drive options */ 1461 *(int *)addr = fd->sc_opts; 1462 return 0; 1463 1464 case FDIOCSETOPTS: /* set drive options */ 1465 fd->sc_opts = *(int *)addr; 1466 return 0; 1467 1468 default: 1469 return ENOTTY; 1470 } 1471 1472 #ifdef DIAGNOSTIC 1473 panic("fdioctl: impossible"); 1474 #endif 1475 } 1476 1477 int 1478 fdformat(dev, finfo, p) 1479 dev_t dev; 1480 struct ne7_fd_formb *finfo; 1481 struct proc *p; 1482 { 1483 int rv = 0, s; 1484 struct fd_softc *fd = device_lookup(&fd_cd, FDUNIT(dev)); 1485 struct fd_type *type = fd->sc_type; 1486 struct buf *bp; 1487 1488 /* set up a buffer header for fdstrategy() */ 1489 bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT|M_ZERO); 1490 if(bp == 0) 1491 return ENOBUFS; 1492 bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 1493 bp->b_proc = p; 1494 bp->b_dev = dev; 1495 1496 /* 1497 * calculate a fake blkno, so fdstrategy() would initiate a 1498 * seek to the requested cylinder 1499 */ 1500 bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads) 1501 + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE; 1502 1503 bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 1504 bp->b_data = (caddr_t)finfo; 1505 1506 #ifdef DEBUG 1507 printf("fdformat: blkno %" PRIx64 " count %lx\n", 1508 bp->b_blkno, bp->b_bcount); 1509 #endif 1510 1511 /* now do the format */ 1512 fdstrategy(bp); 1513 1514 /* ...and wait for it to complete */ 1515 s = splbio(); 1516 while (!(bp->b_flags & B_DONE)) { 1517 rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 1518 if (rv == EWOULDBLOCK) 1519 break; 1520 } 1521 splx(s); 1522 1523 if (rv == EWOULDBLOCK) { 1524 /* timed out */ 1525 rv = EIO; 1526 biodone(bp); 1527 } 1528 if(bp->b_flags & B_ERROR) { 1529 rv = bp->b_error; 1530 } 1531 free(bp, M_TEMP); 1532 return rv; 1533 } 1534 1535 /* 1536 * Mountroot hook: prompt the user to enter the root file system 1537 * floppy. 1538 */ 1539 void 1540 fd_mountroot_hook(dev) 1541 struct device *dev; 1542 { 1543 int c; 1544 1545 printf("Insert filesystem floppy and press return."); 1546 cnpollc(1); 1547 for (;;) { 1548 c = cngetc(); 1549 if ((c == '\r') || (c == '\n')) { 1550 printf("\n"); 1551 break; 1552 } 1553 } 1554 cnpollc(0); 1555 } 1556