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