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