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