1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Don Ahn. 7 * 8 * Copyright (c) 1993, 1994 by 9 * jc@irbs.UUCP (John Capo) 10 * vak@zebub.msk.su (Serge Vakulenko) 11 * ache@astral.msk.su (Andrew A. Chernov) 12 * 13 * Copyright (c) 1993, 1994, 1995 by 14 * joerg_wunsch@uriah.sax.de (Joerg Wunsch) 15 * dufault@hda.com (Peter Dufault) 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. All advertising materials mentioning features or use of this software 26 * must display the following acknowledgement: 27 * This product includes software developed by the University of 28 * California, Berkeley and its contributors. 29 * 4. Neither the name of the University nor the names of its contributors 30 * may be used to endorse or promote products derived from this software 31 * without specific prior written permission. 32 * 33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 43 * SUCH DAMAGE. 44 * 45 * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 46 * $Id$ 47 * 48 */ 49 50 #include "ft.h" 51 #if NFT < 1 52 #undef NFDC 53 #endif 54 #include "fd.h" 55 56 #if NFDC > 0 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/kernel.h> 61 #include <sys/conf.h> 62 #include <sys/file.h> 63 #include <sys/ioctl.h> 64 #include <machine/clock.h> 65 #include <machine/ioctl_fd.h> 66 #include <sys/disklabel.h> 67 #include <sys/buf.h> 68 #include <sys/uio.h> 69 #include <sys/malloc.h> 70 #include <sys/proc.h> 71 #include <sys/syslog.h> 72 #ifdef notyet 73 #include <sys/dkstat.h> 74 #endif 75 #include <i386/isa/isa.h> 76 #include <i386/isa/isa_device.h> 77 #include <i386/isa/fdreg.h> 78 #include <i386/isa/fdc.h> 79 #include <i386/isa/rtc.h> 80 #include <machine/stdarg.h> 81 #if NFT > 0 82 #include <sys/ftape.h> 83 #include <i386/isa/ftreg.h> 84 #endif 85 #ifdef DEVFS 86 #include <sys/devfsext.h> 87 #endif 88 89 /* misuse a flag to identify format operation */ 90 #define B_FORMAT B_XXX 91 92 /* 93 * this biotab field doubles as a field for the physical unit number 94 * on the controller 95 */ 96 #define id_physid id_scsiid 97 98 /* error returns for fd_cmd() */ 99 #define FD_FAILED -1 100 #define FD_NOT_VALID -2 101 #define FDC_ERRMAX 100 /* do not log more */ 102 103 #define NUMTYPES 14 104 #define NUMDENS (NUMTYPES - 6) 105 106 /* These defines (-1) must match index for fd_types */ 107 #define F_TAPE_TYPE 0x020 /* bit for fd_types to indicate tape */ 108 #define NO_TYPE 0 /* must match NO_TYPE in ft.c */ 109 #define FD_1720 1 110 #define FD_1480 2 111 #define FD_1440 3 112 #define FD_1200 4 113 #define FD_820 5 114 #define FD_800 6 115 #define FD_720 7 116 #define FD_360 8 117 118 #define FD_1480in5_25 9 119 #define FD_1440in5_25 10 120 #define FD_820in5_25 11 121 #define FD_800in5_25 12 122 #define FD_720in5_25 13 123 #define FD_360in5_25 14 124 125 126 static struct fd_type fd_types[NUMTYPES] = 127 { 128 { 21,2,0xFF,0x04,82,3444,1,FDC_500KBPS,2,0x0C,2 }, /* 1.72M in HD 3.5in */ 129 { 18,2,0xFF,0x1B,82,2952,1,FDC_500KBPS,2,0x6C,1 }, /* 1.48M in HD 3.5in */ 130 { 18,2,0xFF,0x1B,80,2880,1,FDC_500KBPS,2,0x6C,1 }, /* 1.44M in HD 3.5in */ 131 { 15,2,0xFF,0x1B,80,2400,1,FDC_500KBPS,2,0x54,1 }, /* 1.2M in HD 5.25/3.5 */ 132 { 10,2,0xFF,0x10,82,1640,1,FDC_250KBPS,2,0x2E,1 }, /* 820K in HD 3.5in */ 133 { 10,2,0xFF,0x10,80,1600,1,FDC_250KBPS,2,0x2E,1 }, /* 800K in HD 3.5in */ 134 { 9,2,0xFF,0x20,80,1440,1,FDC_250KBPS,2,0x50,1 }, /* 720K in HD 3.5in */ 135 { 9,2,0xFF,0x2A,40, 720,1,FDC_250KBPS,2,0x50,1 }, /* 360K in DD 5.25in */ 136 137 { 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,0x02,2 }, /* 1.48M in HD 5.25in */ 138 { 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,0x02,2 }, /* 1.44M in HD 5.25in */ 139 { 10,2,0xFF,0x10,82,1640,1,FDC_300KBPS,2,0x2E,1 }, /* 820K in HD 5.25in */ 140 { 10,2,0xFF,0x10,80,1600,1,FDC_300KBPS,2,0x2E,1 }, /* 800K in HD 5.25in */ 141 { 9,2,0xFF,0x20,80,1440,1,FDC_300KBPS,2,0x50,1 }, /* 720K in HD 5.25in */ 142 { 9,2,0xFF,0x23,40, 720,2,FDC_300KBPS,2,0x50,1 }, /* 360K in HD 5.25in */ 143 }; 144 145 #define DRVS_PER_CTLR 2 /* 2 floppies */ 146 147 /***********************************************************************\ 148 * Per controller structure. * 149 \***********************************************************************/ 150 struct fdc_data fdc_data[NFDC]; 151 152 /***********************************************************************\ 153 * Per drive structure. * 154 * N per controller (DRVS_PER_CTLR) * 155 \***********************************************************************/ 156 static struct fd_data { 157 struct fdc_data *fdc; /* pointer to controller structure */ 158 int fdsu; /* this units number on this controller */ 159 int type; /* Drive type (FD_1440...) */ 160 struct fd_type *ft; /* pointer to the type descriptor */ 161 int flags; 162 #define FD_OPEN 0x01 /* it's open */ 163 #define FD_ACTIVE 0x02 /* it's active */ 164 #define FD_MOTOR 0x04 /* motor should be on */ 165 #define FD_MOTOR_WAIT 0x08 /* motor coming up */ 166 int skip; 167 int hddrv; 168 #define FD_NO_TRACK -2 169 int track; /* where we think the head is */ 170 int options; /* user configurable options, see ioctl_fd.h */ 171 #ifdef notyet 172 int dkunit; /* disk stats unit number */ 173 #endif 174 #ifdef DEVFS 175 void *bdevs[1 + NUMDENS + MAXPARTITIONS]; 176 void *cdevs[1 + NUMDENS + MAXPARTITIONS]; 177 #endif 178 } fd_data[NFD]; 179 180 /***********************************************************************\ 181 * Throughout this file the following conventions will be used: * 182 * fd is a pointer to the fd_data struct for the drive in question * 183 * fdc is a pointer to the fdc_data struct for the controller * 184 * fdu is the floppy drive unit number * 185 * fdcu is the floppy controller unit number * 186 * fdsu is the floppy drive unit number on that controller. (sub-unit) * 187 \***********************************************************************/ 188 189 #if NFT > 0 190 int ftopen(dev_t, int); 191 int ftintr(ftu_t ftu); 192 int ftclose(dev_t, int); 193 void ftstrategy(struct buf *); 194 int ftioctl(dev_t, int, caddr_t, int, struct proc *); 195 int ftdump(dev_t); 196 int ftsize(dev_t); 197 int ftattach(struct isa_device *, struct isa_device *, int); 198 #endif 199 200 /* autoconfig functions */ 201 static int fdprobe(struct isa_device *); 202 static int fdattach(struct isa_device *); 203 204 /* needed for ft driver, thus exported */ 205 int in_fdc(fdcu_t); 206 int out_fdc(fdcu_t, int); 207 208 /* internal functions */ 209 static void set_motor(fdcu_t, int, int); 210 # define TURNON 1 211 # define TURNOFF 0 212 static timeout_t fd_turnoff; 213 static timeout_t fd_motor_on; 214 static void fd_turnon(fdu_t); 215 static void fdc_reset(fdc_p); 216 static int fd_in(fdcu_t, int *); 217 static void fdstart(fdcu_t); 218 static timeout_t fd_timeout; 219 static timeout_t fd_pseudointr; 220 static int fdstate(fdcu_t, fdc_p); 221 static int retrier(fdcu_t); 222 static int fdformat(dev_t, struct fd_formb *, struct proc *); 223 224 225 #define DEVIDLE 0 226 #define FINDWORK 1 227 #define DOSEEK 2 228 #define SEEKCOMPLETE 3 229 #define IOCOMPLETE 4 230 #define RECALCOMPLETE 5 231 #define STARTRECAL 6 232 #define RESETCTLR 7 233 #define SEEKWAIT 8 234 #define RECALWAIT 9 235 #define MOTORWAIT 10 236 #define IOTIMEDOUT 11 237 238 #ifdef DEBUG 239 static char const * const fdstates[] = 240 { 241 "DEVIDLE", 242 "FINDWORK", 243 "DOSEEK", 244 "SEEKCOMPLETE", 245 "IOCOMPLETE", 246 "RECALCOMPLETE", 247 "STARTRECAL", 248 "RESETCTLR", 249 "SEEKWAIT", 250 "RECALWAIT", 251 "MOTORWAIT", 252 "IOTIMEDOUT" 253 }; 254 255 /* CAUTION: fd_debug causes huge amounts of logging output */ 256 static int volatile fd_debug = 0; 257 #define TRACE0(arg) if(fd_debug) printf(arg) 258 #define TRACE1(arg1, arg2) if(fd_debug) printf(arg1, arg2) 259 #else /* DEBUG */ 260 #define TRACE0(arg) 261 #define TRACE1(arg1, arg2) 262 #endif /* DEBUG */ 263 264 /* autoconfig structure */ 265 266 struct isa_driver fdcdriver = { 267 fdprobe, fdattach, "fdc", 268 }; 269 270 static d_open_t Fdopen; /* NOTE, not fdopen */ 271 static d_close_t fdclose; 272 static d_ioctl_t fdioctl; 273 static d_strategy_t fdstrategy; 274 275 #define CDEV_MAJOR 9 276 #define BDEV_MAJOR 2 277 static struct cdevsw fd_cdevsw; 278 static struct bdevsw fd_bdevsw = 279 { Fdopen, fdclose, fdstrategy, fdioctl, /*2*/ 280 nodump, nopsize, D_DISK, "fd", &fd_cdevsw, -1 }; 281 282 283 static struct isa_device *fdcdevs[NFDC]; 284 285 static int 286 fdc_err(fdcu_t fdcu, const char *s) 287 { 288 fdc_data[fdcu].fdc_errs++; 289 if(s) { 290 if(fdc_data[fdcu].fdc_errs < FDC_ERRMAX) 291 printf("fdc%d: %s", fdcu, s); 292 else if(fdc_data[fdcu].fdc_errs == FDC_ERRMAX) 293 printf("fdc%d: too many errors, not logging any more\n", 294 fdcu); 295 } 296 297 return FD_FAILED; 298 } 299 300 /* 301 * fd_cmd: Send a command to the chip. Takes a varargs with this structure: 302 * Unit number, 303 * # of output bytes, output bytes as ints ..., 304 * # of input bytes, input bytes as ints ... 305 */ 306 307 static int 308 fd_cmd(fdcu_t fdcu, int n_out, ...) 309 { 310 u_char cmd; 311 int n_in; 312 int n; 313 va_list ap; 314 315 va_start(ap, n_out); 316 cmd = (u_char)(va_arg(ap, int)); 317 va_end(ap); 318 va_start(ap, n_out); 319 for (n = 0; n < n_out; n++) 320 { 321 if (out_fdc(fdcu, va_arg(ap, int)) < 0) 322 { 323 char msg[50]; 324 sprintf(msg, 325 "cmd %x failed at out byte %d of %d\n", 326 cmd, n + 1, n_out); 327 return fdc_err(fdcu, msg); 328 } 329 } 330 n_in = va_arg(ap, int); 331 for (n = 0; n < n_in; n++) 332 { 333 int *ptr = va_arg(ap, int *); 334 if (fd_in(fdcu, ptr) < 0) 335 { 336 char msg[50]; 337 sprintf(msg, 338 "cmd %02x failed at in byte %d of %d\n", 339 cmd, n + 1, n_in); 340 return fdc_err(fdcu, msg); 341 } 342 } 343 344 return 0; 345 } 346 347 static int 348 fd_sense_drive_status(fdc_p fdc, int *st3p) 349 { 350 int st3; 351 352 if (fd_cmd(fdc->fdcu, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) 353 { 354 return fdc_err(fdc->fdcu, "Sense Drive Status failed\n"); 355 } 356 if (st3p) 357 *st3p = st3; 358 359 return 0; 360 } 361 362 static int 363 fd_sense_int(fdc_p fdc, int *st0p, int *cylp) 364 { 365 int st0, cyl; 366 367 int ret = fd_cmd(fdc->fdcu, 1, NE7CMD_SENSEI, 1, &st0); 368 369 if (ret) 370 { 371 (void)fdc_err(fdc->fdcu, 372 "sense intr err reading stat reg 0\n"); 373 return ret; 374 } 375 376 if (st0p) 377 *st0p = st0; 378 379 if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) 380 { 381 /* 382 * There doesn't seem to have been an interrupt. 383 */ 384 return FD_NOT_VALID; 385 } 386 387 if (fd_in(fdc->fdcu, &cyl) < 0) 388 { 389 return fdc_err(fdc->fdcu, "can't get cyl num\n"); 390 } 391 392 if (cylp) 393 *cylp = cyl; 394 395 return 0; 396 } 397 398 399 static int 400 fd_read_status(fdc_p fdc, int fdsu) 401 { 402 int i, ret; 403 404 for (i = 0; i < 7; i++) 405 { 406 /* 407 * XXX types are poorly chosen. Only bytes can by read 408 * from the hardware, but fdc_status wants u_longs and 409 * fd_in() gives ints. 410 */ 411 int status; 412 413 ret = fd_in(fdc->fdcu, &status); 414 fdc->status[i] = status; 415 if (ret != 0) 416 break; 417 } 418 419 if (ret == 0) 420 fdc->flags |= FDC_STAT_VALID; 421 else 422 fdc->flags &= ~FDC_STAT_VALID; 423 424 return ret; 425 } 426 427 /****************************************************************************/ 428 /* autoconfiguration stuff */ 429 /****************************************************************************/ 430 431 /* 432 * probe for existance of controller 433 */ 434 static int 435 fdprobe(struct isa_device *dev) 436 { 437 fdcu_t fdcu = dev->id_unit; 438 if(fdc_data[fdcu].flags & FDC_ATTACHED) 439 { 440 printf("fdc%d: unit used multiple times\n", fdcu); 441 return 0; 442 } 443 444 fdcdevs[fdcu] = dev; 445 fdc_data[fdcu].baseport = dev->id_iobase; 446 447 /* First - lets reset the floppy controller */ 448 outb(dev->id_iobase+FDOUT, 0); 449 DELAY(100); 450 outb(dev->id_iobase+FDOUT, FDO_FRST); 451 452 /* see if it can handle a command */ 453 if (fd_cmd(fdcu, 454 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 455 0)) 456 { 457 return(0); 458 } 459 return (IO_FDCSIZE); 460 } 461 462 /* 463 * wire controller into system, look for floppy units 464 */ 465 static int 466 fdattach(struct isa_device *dev) 467 { 468 unsigned fdt; 469 fdu_t fdu; 470 fdcu_t fdcu = dev->id_unit; 471 fdc_p fdc = fdc_data + fdcu; 472 fd_p fd; 473 int fdsu, st0, st3, i; 474 #if NFT > 0 475 int unithasfd; 476 #endif 477 struct isa_device *fdup; 478 int ic_type = 0; 479 #ifdef DEVFS 480 int mynor; 481 int typemynor; 482 int typesize; 483 #endif 484 485 fdc->fdcu = fdcu; 486 fdc->flags |= FDC_ATTACHED; 487 fdc->dmachan = dev->id_drq; 488 /* Acquire the DMA channel forever, The driver will do the rest */ 489 isa_dma_acquire(fdc->dmachan); 490 isa_dmainit(fdc->dmachan, 128 << 3 /* XXX max secsize */); 491 fdc->state = DEVIDLE; 492 /* reset controller, turn motor off, clear fdout mirror reg */ 493 outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); 494 TAILQ_INIT(&fdc->head); 495 496 /* check for each floppy drive */ 497 for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { 498 if (fdup->id_iobase != dev->id_iobase) 499 continue; 500 fdu = fdup->id_unit; 501 fd = &fd_data[fdu]; 502 if (fdu >= (NFD+NFT)) 503 continue; 504 fdsu = fdup->id_physid; 505 /* look up what bios thinks we have */ 506 switch (fdu) { 507 case 0: fdt = (rtcin(RTC_FDISKETTE) & 0xf0); 508 break; 509 case 1: fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); 510 break; 511 default: fdt = RTCFDT_NONE; 512 break; 513 } 514 /* is there a unit? */ 515 if ((fdt == RTCFDT_NONE) 516 #if NFT > 0 517 || (fdsu >= DRVS_PER_CTLR)) { 518 #else 519 ) { 520 fd->type = NO_TYPE; 521 #endif 522 #if NFT > 0 523 /* If BIOS says no floppy, or > 2nd device */ 524 /* Probe for and attach a floppy tape. */ 525 /* Tell FT if there was already a disk */ 526 /* with this unit number found. */ 527 528 unithasfd = 0; 529 if (fdu < NFD && fd->type != NO_TYPE) 530 unithasfd = 1; 531 if (ftattach(dev, fdup, unithasfd)) 532 continue; 533 if (fdsu < DRVS_PER_CTLR) 534 fd->type = NO_TYPE; 535 #endif 536 continue; 537 } 538 539 /* select it */ 540 set_motor(fdcu, fdsu, TURNON); 541 DELAY(1000000); /* 1 sec */ 542 543 if (ic_type == 0 && 544 fd_cmd(fdcu, 1, NE7CMD_VERSION, 1, &ic_type) == 0) 545 { 546 printf("fdc%d: ", fdcu); 547 ic_type = (u_char)ic_type; 548 switch( ic_type ) { 549 case 0x80: 550 printf("NEC 765\n"); 551 fdc->fdct = FDC_NE765; 552 break; 553 case 0x81: 554 printf("Intel 82077\n"); 555 fdc->fdct = FDC_I82077; 556 break; 557 case 0x90: 558 printf("NEC 72065B\n"); 559 fdc->fdct = FDC_NE72065; 560 break; 561 default: 562 printf("unknown IC type %02x\n", ic_type); 563 fdc->fdct = FDC_UNKNOWN; 564 break; 565 } 566 } 567 if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && 568 (st3 & NE7_ST3_T0)) { 569 /* if at track 0, first seek inwards */ 570 /* seek some steps: */ 571 (void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0); 572 DELAY(300000); /* ...wait a moment... */ 573 (void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ 574 } 575 576 /* If we're at track 0 first seek inwards. */ 577 if ((fd_sense_drive_status(fdc, &st3) == 0) && 578 (st3 & NE7_ST3_T0)) { 579 /* Seek some steps... */ 580 if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { 581 /* ...wait a moment... */ 582 DELAY(300000); 583 /* make ctrlr happy: */ 584 (void)fd_sense_int(fdc, 0, 0); 585 } 586 } 587 588 for(i = 0; i < 2; i++) { 589 /* 590 * we must recalibrate twice, just in case the 591 * heads have been beyond cylinder 76, since most 592 * FDCs still barf when attempting to recalibrate 593 * more than 77 steps 594 */ 595 /* go back to 0: */ 596 if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) { 597 /* a second being enough for full stroke seek*/ 598 DELAY(i == 0? 1000000: 300000); 599 600 /* anything responding? */ 601 if (fd_sense_int(fdc, &st0, 0) == 0 && 602 (st0 & NE7_ST0_EC) == 0) 603 break; /* already probed succesfully */ 604 } 605 } 606 607 set_motor(fdcu, fdsu, TURNOFF); 608 609 if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ 610 continue; 611 612 fd->track = FD_NO_TRACK; 613 fd->fdc = fdc; 614 fd->fdsu = fdsu; 615 fd->options = 0; 616 printf("fd%d: ", fdu); 617 618 switch (fdt) { 619 case RTCFDT_12M: 620 printf("1.2MB 5.25in\n"); 621 fd->type = FD_1200; 622 break; 623 case RTCFDT_144M: 624 printf("1.44MB 3.5in\n"); 625 fd->type = FD_1440; 626 break; 627 case RTCFDT_288M: 628 case RTCFDT_288M_1: 629 printf("2.88MB 3.5in - 1.44MB mode\n"); 630 fd->type = FD_1440; 631 break; 632 case RTCFDT_360K: 633 printf("360KB 5.25in\n"); 634 fd->type = FD_360; 635 break; 636 case RTCFDT_720K: 637 printf("720KB 3.5in\n"); 638 fd->type = FD_720; 639 break; 640 default: 641 printf("unknown\n"); 642 fd->type = NO_TYPE; 643 continue; 644 } 645 #ifdef DEVFS 646 mynor = fdu << 6; 647 fd->bdevs[0] = devfs_add_devswf(&fd_bdevsw, mynor, DV_BLK, 648 UID_ROOT, GID_OPERATOR, 0640, 649 "fd%d", fdu); 650 fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, 651 UID_ROOT, GID_OPERATOR, 0640, 652 "rfd%d", fdu); 653 for (i = 1; i < 1 + NUMDENS; i++) { 654 /* 655 * XXX this and the lookup in Fdopen() should be 656 * data driven. 657 */ 658 switch (fd->type) { 659 case FD_360: 660 if (i != FD_360) 661 continue; 662 break; 663 case FD_720: 664 if (i != FD_720 && i != FD_800 && i != FD_820) 665 continue; 666 break; 667 case FD_1200: 668 if (i != FD_360 && i != FD_720 && i != FD_800 669 && i != FD_820 && i != FD_1200 670 && i != FD_1440 && i != FD_1480) 671 continue; 672 break; 673 case FD_1440: 674 if (i != FD_720 && i != FD_800 && i != FD_820 675 && i != FD_1200 && i != FD_1440 676 && i != FD_1480 && i != FD_1720) 677 continue; 678 break; 679 } 680 typemynor = mynor | i; 681 typesize = fd_types[i - 1].size / 2; 682 /* 683 * XXX all these conversions give bloated code and 684 * confusing names. 685 */ 686 if (typesize == 1476) 687 typesize = 1480; 688 if (typesize == 1722) 689 typesize = 1720; 690 fd->bdevs[i] = 691 devfs_add_devswf(&fd_bdevsw, typemynor, DV_BLK, 692 UID_ROOT, GID_OPERATOR, 0640, 693 "fd%d.%d", fdu, typesize); 694 fd->cdevs[i] = 695 devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, 696 UID_ROOT, GID_OPERATOR, 0640, 697 "rfd%d.%d", fdu, typesize); 698 } 699 for (i = 0; i < MAXPARTITIONS; i++) { 700 fd->bdevs[1 + NUMDENS + i] = 701 devfs_link(fd->bdevs[0], 702 "fd%d%c", fdu, 'a' + i); 703 fd->cdevs[1 + NUMDENS + i] = 704 devfs_link(fd->cdevs[0], 705 "rfd%d%c", fdu, 'a' + i); 706 } 707 #endif /* DEVFS */ 708 #ifdef notyet 709 if (dk_ndrive < DK_NDRIVE) { 710 sprintf(dk_names[dk_ndrive], "fd%d", fdu); 711 fd->dkunit = dk_ndrive++; 712 /* 713 * XXX assume rate is FDC_500KBPS. 714 */ 715 dk_wpms[dk_ndrive] = 500000 / 8 / 2; 716 } else { 717 fd->dkunit = -1; 718 } 719 #endif 720 } 721 722 return (1); 723 } 724 725 /****************************************************************************/ 726 /* motor control stuff */ 727 /* remember to not deselect the drive we're working on */ 728 /****************************************************************************/ 729 static void 730 set_motor(fdcu_t fdcu, int fdsu, int turnon) 731 { 732 int fdout = fdc_data[fdcu].fdout; 733 int needspecify = 0; 734 735 if(turnon) { 736 fdout &= ~FDO_FDSEL; 737 fdout |= (FDO_MOEN0 << fdsu) + fdsu; 738 } else 739 fdout &= ~(FDO_MOEN0 << fdsu); 740 741 if(!turnon 742 && (fdout & (FDO_MOEN0+FDO_MOEN1+FDO_MOEN2+FDO_MOEN3)) == 0) 743 /* gonna turn off the last drive, put FDC to bed */ 744 fdout &= ~ (FDO_FRST|FDO_FDMAEN); 745 else { 746 /* make sure controller is selected and specified */ 747 if((fdout & (FDO_FRST|FDO_FDMAEN)) == 0) 748 needspecify = 1; 749 fdout |= (FDO_FRST|FDO_FDMAEN); 750 } 751 752 outb(fdc_data[fdcu].baseport+FDOUT, fdout); 753 fdc_data[fdcu].fdout = fdout; 754 TRACE1("[0x%x->FDOUT]", fdout); 755 756 if(needspecify) { 757 /* 758 * XXX 759 * special case: since we have just woken up the FDC 760 * from its sleep, we silently assume the command will 761 * be accepted, and do not test for a timeout 762 */ 763 (void)fd_cmd(fdcu, 3, NE7CMD_SPECIFY, 764 NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 765 0); 766 } 767 } 768 769 static void 770 fd_turnoff(void *arg1) 771 { 772 fdu_t fdu = (fdu_t)arg1; 773 int s; 774 fd_p fd = fd_data + fdu; 775 776 TRACE1("[fd%d: turnoff]", fdu); 777 778 /* 779 * Don't turn off the motor yet if the drive is active. 780 * XXX shouldn't even schedule turnoff until drive is inactive 781 * and nothing is queued on it. 782 */ 783 if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fdu) { 784 timeout(fd_turnoff, arg1, 4 * hz); 785 return; 786 } 787 788 s = splbio(); 789 fd->flags &= ~FD_MOTOR; 790 set_motor(fd->fdc->fdcu, fd->fdsu, TURNOFF); 791 splx(s); 792 } 793 794 static void 795 fd_motor_on(void *arg1) 796 { 797 fdu_t fdu = (fdu_t)arg1; 798 int s; 799 800 fd_p fd = fd_data + fdu; 801 s = splbio(); 802 fd->flags &= ~FD_MOTOR_WAIT; 803 if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) 804 { 805 fdintr(fd->fdc->fdcu); 806 } 807 splx(s); 808 } 809 810 static void 811 fd_turnon(fdu_t fdu) 812 { 813 fd_p fd = fd_data + fdu; 814 if(!(fd->flags & FD_MOTOR)) 815 { 816 fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT); 817 set_motor(fd->fdc->fdcu, fd->fdsu, TURNON); 818 timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ 819 } 820 } 821 822 static void 823 fdc_reset(fdc_p fdc) 824 { 825 fdcu_t fdcu = fdc->fdcu; 826 827 /* Try a reset, keep motor on */ 828 outb(fdc->baseport + FDOUT, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); 829 TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); 830 DELAY(100); 831 /* enable FDC, but defer interrupts a moment */ 832 outb(fdc->baseport + FDOUT, fdc->fdout & ~FDO_FDMAEN); 833 TRACE1("[0x%x->FDOUT]", fdc->fdout & ~FDO_FDMAEN); 834 DELAY(100); 835 outb(fdc->baseport + FDOUT, fdc->fdout); 836 TRACE1("[0x%x->FDOUT]", fdc->fdout); 837 838 /* XXX after a reset, silently believe the FDC will accept commands */ 839 (void)fd_cmd(fdcu, 3, NE7CMD_SPECIFY, 840 NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 841 0); 842 } 843 844 /****************************************************************************/ 845 /* fdc in/out */ 846 /****************************************************************************/ 847 int 848 in_fdc(fdcu_t fdcu) 849 { 850 int baseport = fdc_data[fdcu].baseport; 851 int i, j = 100000; 852 while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) 853 != (NE7_DIO|NE7_RQM) && j-- > 0) 854 if (i == NE7_RQM) 855 return fdc_err(fdcu, "ready for output in input\n"); 856 if (j <= 0) 857 return fdc_err(fdcu, bootverbose? "input ready timeout\n": 0); 858 #ifdef DEBUG 859 i = inb(baseport+FDDATA); 860 TRACE1("[FDDATA->0x%x]", (unsigned char)i); 861 return(i); 862 #else 863 return inb(baseport+FDDATA); 864 #endif 865 } 866 867 /* 868 * fd_in: Like in_fdc, but allows you to see if it worked. 869 */ 870 static int 871 fd_in(fdcu_t fdcu, int *ptr) 872 { 873 int baseport = fdc_data[fdcu].baseport; 874 int i, j = 100000; 875 while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) 876 != (NE7_DIO|NE7_RQM) && j-- > 0) 877 if (i == NE7_RQM) 878 return fdc_err(fdcu, "ready for output in input\n"); 879 if (j <= 0) 880 return fdc_err(fdcu, bootverbose? "input ready timeout\n": 0); 881 #ifdef DEBUG 882 i = inb(baseport+FDDATA); 883 TRACE1("[FDDATA->0x%x]", (unsigned char)i); 884 *ptr = i; 885 return 0; 886 #else 887 i = inb(baseport+FDDATA); 888 if (ptr) 889 *ptr = i; 890 return 0; 891 #endif 892 } 893 894 int 895 out_fdc(fdcu_t fdcu, int x) 896 { 897 int baseport = fdc_data[fdcu].baseport; 898 int i; 899 900 /* Check that the direction bit is set */ 901 i = 100000; 902 while ((inb(baseport+FDSTS) & NE7_DIO) && i-- > 0); 903 if (i <= 0) return fdc_err(fdcu, "direction bit not set\n"); 904 905 /* Check that the floppy controller is ready for a command */ 906 i = 100000; 907 while ((inb(baseport+FDSTS) & NE7_RQM) == 0 && i-- > 0); 908 if (i <= 0) 909 return fdc_err(fdcu, bootverbose? "output ready timeout\n": 0); 910 911 /* Send the command and return */ 912 outb(baseport+FDDATA, x); 913 TRACE1("[0x%x->FDDATA]", x); 914 return (0); 915 } 916 917 /****************************************************************************/ 918 /* fdopen/fdclose */ 919 /****************************************************************************/ 920 int 921 Fdopen(dev_t dev, int flags, int mode, struct proc *p) 922 { 923 fdu_t fdu = FDUNIT(minor(dev)); 924 int type = FDTYPE(minor(dev)); 925 fdc_p fdc; 926 927 #if NFT > 0 928 /* check for a tape open */ 929 if (type & F_TAPE_TYPE) 930 return(ftopen(dev, flags)); 931 #endif 932 /* check bounds */ 933 if (fdu >= NFD) 934 return(ENXIO); 935 fdc = fd_data[fdu].fdc; 936 if ((fdc == NULL) || (fd_data[fdu].type == NO_TYPE)) 937 return(ENXIO); 938 if (type > NUMDENS) 939 return(ENXIO); 940 if (type == 0) 941 type = fd_data[fdu].type; 942 else { 943 if (type != fd_data[fdu].type) { 944 switch (fd_data[fdu].type) { 945 case FD_360: 946 return(ENXIO); 947 case FD_720: 948 if ( type != FD_820 949 && type != FD_800 950 ) 951 return(ENXIO); 952 break; 953 case FD_1200: 954 switch (type) { 955 case FD_1480: 956 type = FD_1480in5_25; 957 break; 958 case FD_1440: 959 type = FD_1440in5_25; 960 break; 961 case FD_820: 962 type = FD_820in5_25; 963 break; 964 case FD_800: 965 type = FD_800in5_25; 966 break; 967 case FD_720: 968 type = FD_720in5_25; 969 break; 970 case FD_360: 971 type = FD_360in5_25; 972 break; 973 default: 974 return(ENXIO); 975 } 976 break; 977 case FD_1440: 978 if ( type != FD_1720 979 && type != FD_1480 980 && type != FD_1200 981 && type != FD_820 982 && type != FD_800 983 && type != FD_720 984 ) 985 return(ENXIO); 986 break; 987 } 988 } 989 } 990 fd_data[fdu].ft = fd_types + type - 1; 991 fd_data[fdu].flags |= FD_OPEN; 992 993 return 0; 994 } 995 996 int 997 fdclose(dev_t dev, int flags, int mode, struct proc *p) 998 { 999 fdu_t fdu = FDUNIT(minor(dev)); 1000 1001 #if NFT > 0 1002 int type = FDTYPE(minor(dev)); 1003 1004 if (type & F_TAPE_TYPE) 1005 return ftclose(dev, flags); 1006 #endif 1007 fd_data[fdu].flags &= ~FD_OPEN; 1008 fd_data[fdu].options &= ~FDOPT_NORETRY; 1009 1010 return(0); 1011 } 1012 1013 1014 /****************************************************************************/ 1015 /* fdstrategy */ 1016 /****************************************************************************/ 1017 void 1018 fdstrategy(struct buf *bp) 1019 { 1020 unsigned nblocks, blknum, cando; 1021 int s; 1022 fdcu_t fdcu; 1023 fdu_t fdu; 1024 fdc_p fdc; 1025 fd_p fd; 1026 size_t fdblk; 1027 1028 fdu = FDUNIT(minor(bp->b_dev)); 1029 fd = &fd_data[fdu]; 1030 fdc = fd->fdc; 1031 fdcu = fdc->fdcu; 1032 1033 #if NFT > 0 1034 if (FDTYPE(minor(bp->b_dev)) & F_TAPE_TYPE) { 1035 /* ft tapes do not (yet) support strategy i/o */ 1036 bp->b_error = ENODEV; 1037 bp->b_flags |= B_ERROR; 1038 goto bad; 1039 } 1040 /* check for controller already busy with tape */ 1041 if (fdc->flags & FDC_TAPE_BUSY) { 1042 bp->b_error = EBUSY; 1043 bp->b_flags |= B_ERROR; 1044 goto bad; 1045 } 1046 #endif 1047 fdblk = 128 << (fd->ft->secsize); 1048 if (!(bp->b_flags & B_FORMAT)) { 1049 if ((fdu >= NFD) || (bp->b_blkno < 0)) { 1050 printf( 1051 "fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n", 1052 fdu, (u_long)bp->b_blkno, bp->b_bcount); 1053 bp->b_error = EINVAL; 1054 bp->b_flags |= B_ERROR; 1055 goto bad; 1056 } 1057 if ((bp->b_bcount % fdblk) != 0) { 1058 bp->b_error = EINVAL; 1059 bp->b_flags |= B_ERROR; 1060 goto bad; 1061 } 1062 } 1063 1064 /* 1065 * Set up block calculations. 1066 */ 1067 if (bp->b_blkno > 20000000) { 1068 /* 1069 * Reject unreasonably high block number, prevent the 1070 * multiplication below from overflowing. 1071 */ 1072 bp->b_error = EINVAL; 1073 bp->b_flags |= B_ERROR; 1074 goto bad; 1075 } 1076 blknum = (unsigned) bp->b_blkno * DEV_BSIZE/fdblk; 1077 nblocks = fd->ft->size; 1078 bp->b_resid = 0; 1079 if (blknum + (bp->b_bcount / fdblk) > nblocks) { 1080 if (blknum <= nblocks) { 1081 cando = (nblocks - blknum) * fdblk; 1082 bp->b_resid = bp->b_bcount - cando; 1083 if (cando == 0) 1084 goto bad; /* not actually bad but EOF */ 1085 } else { 1086 bp->b_error = EINVAL; 1087 bp->b_flags |= B_ERROR; 1088 goto bad; 1089 } 1090 } 1091 bp->b_pblkno = bp->b_blkno; 1092 s = splbio(); 1093 tqdisksort(&fdc->head, bp); 1094 untimeout(fd_turnoff, (caddr_t)fdu); /* a good idea */ 1095 fdstart(fdcu); 1096 splx(s); 1097 return; 1098 1099 bad: 1100 biodone(bp); 1101 } 1102 1103 /***************************************************************\ 1104 * fdstart * 1105 * We have just queued something.. if the controller is not busy * 1106 * then simulate the case where it has just finished a command * 1107 * So that it (the interrupt routine) looks on the queue for more* 1108 * work to do and picks up what we just added. * 1109 * If the controller is already busy, we need do nothing, as it * 1110 * will pick up our work when the present work completes * 1111 \***************************************************************/ 1112 static void 1113 fdstart(fdcu_t fdcu) 1114 { 1115 int s; 1116 1117 s = splbio(); 1118 if(fdc_data[fdcu].state == DEVIDLE) 1119 { 1120 fdintr(fdcu); 1121 } 1122 splx(s); 1123 } 1124 1125 static void 1126 fd_timeout(void *arg1) 1127 { 1128 fdcu_t fdcu = (fdcu_t)arg1; 1129 fdu_t fdu = fdc_data[fdcu].fdu; 1130 int baseport = fdc_data[fdcu].baseport; 1131 struct buf *bp; 1132 int s; 1133 1134 bp = TAILQ_FIRST(&fdc_data[fdcu].head); 1135 1136 /* 1137 * Due to IBM's brain-dead design, the FDC has a faked ready 1138 * signal, hardwired to ready == true. Thus, any command 1139 * issued if there's no diskette in the drive will _never_ 1140 * complete, and must be aborted by resetting the FDC. 1141 * Many thanks, Big Blue! 1142 */ 1143 1144 s = splbio(); 1145 1146 TRACE1("fd%d[fd_timeout()]", fdu); 1147 /* See if the controller is still busy (patiently awaiting data) */ 1148 if(((inb(baseport + FDSTS)) & (NE7_CB|NE7_RQM)) == NE7_CB) 1149 { 1150 TRACE1("[FDSTS->0x%x]", inb(baseport + FDSTS)); 1151 /* yup, it is; kill it now */ 1152 fdc_reset(&fdc_data[fdcu]); 1153 printf("fd%d: Operation timeout\n", fdu); 1154 } 1155 1156 if (bp) 1157 { 1158 retrier(fdcu); 1159 fdc_data[fdcu].status[0] = NE7_ST0_IC_RC; 1160 fdc_data[fdcu].state = IOTIMEDOUT; 1161 if( fdc_data[fdcu].retry < 6) 1162 fdc_data[fdcu].retry = 6; 1163 } 1164 else 1165 { 1166 fdc_data[fdcu].fd = (fd_p) 0; 1167 fdc_data[fdcu].fdu = -1; 1168 fdc_data[fdcu].state = DEVIDLE; 1169 } 1170 fdintr(fdcu); 1171 splx(s); 1172 } 1173 1174 /* just ensure it has the right spl */ 1175 static void 1176 fd_pseudointr(void *arg1) 1177 { 1178 fdcu_t fdcu = (fdcu_t)arg1; 1179 int s; 1180 1181 s = splbio(); 1182 fdintr(fdcu); 1183 splx(s); 1184 } 1185 1186 /***********************************************************************\ 1187 * fdintr * 1188 * keep calling the state machine until it returns a 0 * 1189 * ALWAYS called at SPLBIO * 1190 \***********************************************************************/ 1191 void 1192 fdintr(fdcu_t fdcu) 1193 { 1194 fdc_p fdc = fdc_data + fdcu; 1195 #if NFT > 0 1196 fdu_t fdu = fdc->fdu; 1197 1198 if (fdc->flags & FDC_TAPE_BUSY) 1199 (ftintr(fdu)); 1200 else 1201 #endif 1202 while(fdstate(fdcu, fdc)) 1203 ; 1204 } 1205 1206 /***********************************************************************\ 1207 * The controller state machine. * 1208 * if it returns a non zero value, it should be called again immediatly * 1209 \***********************************************************************/ 1210 static int 1211 fdstate(fdcu_t fdcu, fdc_p fdc) 1212 { 1213 int read, format, head, sec = 0, sectrac, st0, cyl, st3; 1214 unsigned blknum = 0, b_cylinder = 0; 1215 fdu_t fdu = fdc->fdu; 1216 fd_p fd; 1217 register struct buf *bp; 1218 struct fd_formb *finfo = NULL; 1219 size_t fdblk; 1220 1221 bp = TAILQ_FIRST(&fdc->head); 1222 if(!bp) { 1223 /***********************************************\ 1224 * nothing left for this controller to do * 1225 * Force into the IDLE state, * 1226 \***********************************************/ 1227 fdc->state = DEVIDLE; 1228 if(fdc->fd) 1229 { 1230 printf("fd%d: unexpected valid fd pointer\n", 1231 fdc->fdu); 1232 fdc->fd = (fd_p) 0; 1233 fdc->fdu = -1; 1234 } 1235 TRACE1("[fdc%d IDLE]", fdcu); 1236 return(0); 1237 } 1238 fdu = FDUNIT(minor(bp->b_dev)); 1239 fd = fd_data + fdu; 1240 fdblk = 128 << fd->ft->secsize; 1241 if (fdc->fd && (fd != fdc->fd)) 1242 { 1243 printf("fd%d: confused fd pointers\n", fdu); 1244 } 1245 read = bp->b_flags & B_READ; 1246 format = bp->b_flags & B_FORMAT; 1247 if(format) { 1248 finfo = (struct fd_formb *)bp->b_un.b_addr; 1249 fd->skip = (char *)&(finfo->fd_formb_cylno(0)) 1250 - (char *)finfo; 1251 } 1252 if (fdc->state == DOSEEK || fdc->state == SEEKCOMPLETE) { 1253 blknum = (unsigned) bp->b_blkno * DEV_BSIZE/fdblk + 1254 fd->skip/fdblk; 1255 b_cylinder = blknum / (fd->ft->sectrac * fd->ft->heads); 1256 } 1257 TRACE1("fd%d", fdu); 1258 TRACE1("[%s]", fdstates[fdc->state]); 1259 TRACE1("(0x%x)", fd->flags); 1260 untimeout(fd_turnoff, (caddr_t)fdu); 1261 timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); 1262 switch (fdc->state) 1263 { 1264 case DEVIDLE: 1265 case FINDWORK: /* we have found new work */ 1266 fdc->retry = 0; 1267 fd->skip = 0; 1268 fdc->fd = fd; 1269 fdc->fdu = fdu; 1270 outb(fdc->baseport+FDCTL, fd->ft->trans); 1271 TRACE1("[0x%x->FDCTL]", fd->ft->trans); 1272 /*******************************************************\ 1273 * If the next drive has a motor startup pending, then * 1274 * it will start up in it's own good time * 1275 \*******************************************************/ 1276 if(fd->flags & FD_MOTOR_WAIT) 1277 { 1278 fdc->state = MOTORWAIT; 1279 return(0); /* come back later */ 1280 } 1281 /*******************************************************\ 1282 * Maybe if it's not starting, it SHOULD be starting * 1283 \*******************************************************/ 1284 if (!(fd->flags & FD_MOTOR)) 1285 { 1286 fdc->state = MOTORWAIT; 1287 fd_turnon(fdu); 1288 return(0); 1289 } 1290 else /* at least make sure we are selected */ 1291 { 1292 set_motor(fdcu, fd->fdsu, TURNON); 1293 } 1294 fdc->state = DOSEEK; 1295 break; 1296 case DOSEEK: 1297 if (b_cylinder == (unsigned)fd->track) 1298 { 1299 fdc->state = SEEKCOMPLETE; 1300 break; 1301 } 1302 if (fd_cmd(fdcu, 3, NE7CMD_SEEK, 1303 fd->fdsu, b_cylinder * fd->ft->steptrac, 1304 0)) 1305 { 1306 /* 1307 * seek command not accepted, looks like 1308 * the FDC went off to the Saints... 1309 */ 1310 fdc->retry = 6; /* try a reset */ 1311 return(retrier(fdcu)); 1312 } 1313 fd->track = FD_NO_TRACK; 1314 fdc->state = SEEKWAIT; 1315 return(0); /* will return later */ 1316 case SEEKWAIT: 1317 /* allow heads to settle */ 1318 timeout(fd_pseudointr, (caddr_t)fdcu, hz / 16); 1319 fdc->state = SEEKCOMPLETE; 1320 return(0); /* will return later */ 1321 case SEEKCOMPLETE : /* SEEK DONE, START DMA */ 1322 /* Make sure seek really happened*/ 1323 if(fd->track == FD_NO_TRACK) 1324 { 1325 int descyl = b_cylinder * fd->ft->steptrac; 1326 do { 1327 /* 1328 * This might be a "ready changed" interrupt, 1329 * which cannot really happen since the 1330 * RDY pin is hardwired to + 5 volts. This 1331 * generally indicates a "bouncing" intr 1332 * line, so do one of the following: 1333 * 1334 * When running on an enhanced FDC that is 1335 * known to not go stuck after responding 1336 * with INVALID, fetch all interrupt states 1337 * until seeing either an INVALID or a 1338 * real interrupt condition. 1339 * 1340 * When running on a dumb old NE765, give 1341 * up immediately. The controller will 1342 * provide up to four dummy RC interrupt 1343 * conditions right after reset (for the 1344 * corresponding four drives), so this is 1345 * our only chance to get notice that it 1346 * was not the FDC that caused the interrupt. 1347 */ 1348 if (fd_sense_int(fdc, &st0, &cyl) 1349 == FD_NOT_VALID) 1350 return 0; 1351 if(fdc->fdct == FDC_NE765 1352 && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC) 1353 return 0; /* hope for a real intr */ 1354 } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); 1355 1356 if (0 == descyl) 1357 { 1358 int failed = 0; 1359 /* 1360 * seek to cyl 0 requested; make sure we are 1361 * really there 1362 */ 1363 if (fd_sense_drive_status(fdc, &st3)) 1364 failed = 1; 1365 if ((st3 & NE7_ST3_T0) == 0) { 1366 printf( 1367 "fd%d: Seek to cyl 0, but not really there (ST3 = %b)\n", 1368 fdu, st3, NE7_ST3BITS); 1369 failed = 1; 1370 } 1371 1372 if (failed) 1373 { 1374 if(fdc->retry < 3) 1375 fdc->retry = 3; 1376 return(retrier(fdcu)); 1377 } 1378 } 1379 1380 if (cyl != descyl) 1381 { 1382 printf( 1383 "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", 1384 fdu, descyl, cyl, st0); 1385 return(retrier(fdcu)); 1386 } 1387 } 1388 1389 fd->track = b_cylinder; 1390 isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip, 1391 format ? bp->b_bcount : fdblk, fdc->dmachan); 1392 sectrac = fd->ft->sectrac; 1393 sec = blknum % (sectrac * fd->ft->heads); 1394 head = sec / sectrac; 1395 sec = sec % sectrac + 1; 1396 fd->hddrv = ((head&1)<<2)+fdu; 1397 1398 if(format || !read) 1399 { 1400 /* make sure the drive is writable */ 1401 if(fd_sense_drive_status(fdc, &st3) != 0) 1402 { 1403 /* stuck controller? */ 1404 fdc->retry = 6; /* reset the beast */ 1405 return(retrier(fdcu)); 1406 } 1407 if(st3 & NE7_ST3_WP) 1408 { 1409 /* 1410 * XXX YES! this is ugly. 1411 * in order to force the current operation 1412 * to fail, we will have to fake an FDC 1413 * error - all error handling is done 1414 * by the retrier() 1415 */ 1416 fdc->status[0] = NE7_ST0_IC_AT; 1417 fdc->status[1] = NE7_ST1_NW; 1418 fdc->status[2] = 0; 1419 fdc->status[3] = fd->track; 1420 fdc->status[4] = head; 1421 fdc->status[5] = sec; 1422 fdc->retry = 8; /* break out immediately */ 1423 fdc->state = IOTIMEDOUT; /* not really... */ 1424 return (1); 1425 } 1426 } 1427 1428 if(format) 1429 { 1430 /* formatting */ 1431 if(fd_cmd(fdcu, 6, 1432 NE7CMD_FORMAT, 1433 head << 2 | fdu, 1434 finfo->fd_formb_secshift, 1435 finfo->fd_formb_nsecs, 1436 finfo->fd_formb_gaplen, 1437 finfo->fd_formb_fillbyte, 1438 0)) 1439 { 1440 /* controller fell over */ 1441 fdc->retry = 6; 1442 return(retrier(fdcu)); 1443 } 1444 } 1445 else 1446 { 1447 if (fd_cmd(fdcu, 9, 1448 (read ? NE7CMD_READ : NE7CMD_WRITE), 1449 head << 2 | fdu, /* head & unit */ 1450 fd->track, /* track */ 1451 head, 1452 sec, /* sector + 1 */ 1453 fd->ft->secsize, /* sector size */ 1454 sectrac, /* sectors/track */ 1455 fd->ft->gap, /* gap size */ 1456 fd->ft->datalen, /* data length */ 1457 0)) 1458 { 1459 /* the beast is sleeping again */ 1460 fdc->retry = 6; 1461 return(retrier(fdcu)); 1462 } 1463 } 1464 fdc->state = IOCOMPLETE; 1465 timeout(fd_timeout, (caddr_t)fdcu, hz); 1466 return(0); /* will return later */ 1467 case IOCOMPLETE: /* IO DONE, post-analyze */ 1468 untimeout(fd_timeout, (caddr_t)fdcu); 1469 1470 if (fd_read_status(fdc, fd->fdsu)) 1471 { 1472 if (fdc->retry < 6) 1473 fdc->retry = 6; /* force a reset */ 1474 return retrier(fdcu); 1475 } 1476 1477 fdc->state = IOTIMEDOUT; 1478 1479 /* FALLTHROUGH */ 1480 1481 case IOTIMEDOUT: 1482 isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, 1483 format ? bp->b_bcount : fdblk, fdc->dmachan); 1484 if (fdc->status[0] & NE7_ST0_IC) 1485 { 1486 if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT 1487 && fdc->status[1] & NE7_ST1_OR) { 1488 /* 1489 * DMA overrun. Someone hogged the bus 1490 * and didn't release it in time for the 1491 * next FDC transfer. 1492 * Just restart it, don't increment retry 1493 * count. (vak) 1494 */ 1495 fdc->state = SEEKCOMPLETE; 1496 return (1); 1497 } 1498 else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_IV 1499 && fdc->retry < 6) 1500 fdc->retry = 6; /* force a reset */ 1501 else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT 1502 && fdc->status[2] & NE7_ST2_WC 1503 && fdc->retry < 3) 1504 fdc->retry = 3; /* force recalibrate */ 1505 return(retrier(fdcu)); 1506 } 1507 /* All OK */ 1508 fd->skip += fdblk; 1509 if (!format && fd->skip < bp->b_bcount - bp->b_resid) 1510 { 1511 /* set up next transfer */ 1512 fdc->state = DOSEEK; 1513 } 1514 else 1515 { 1516 /* ALL DONE */ 1517 fd->skip = 0; 1518 TAILQ_REMOVE(&fdc->head, bp, b_act); 1519 biodone(bp); 1520 fdc->fd = (fd_p) 0; 1521 fdc->fdu = -1; 1522 fdc->state = FINDWORK; 1523 } 1524 return(1); 1525 case RESETCTLR: 1526 fdc_reset(fdc); 1527 fdc->retry++; 1528 fdc->state = STARTRECAL; 1529 break; 1530 case STARTRECAL: 1531 /* XXX clear the fdc results from the last reset, if any. */ 1532 { 1533 int i; 1534 for (i = 0; i < 4; i++) 1535 (void)fd_sense_int(fdc, &st0, &cyl); 1536 } 1537 1538 if(fd_cmd(fdcu, 1539 2, NE7CMD_RECAL, fdu, 1540 0)) /* Recalibrate Function */ 1541 { 1542 /* arrgl */ 1543 fdc->retry = 6; 1544 return(retrier(fdcu)); 1545 } 1546 fdc->state = RECALWAIT; 1547 return(0); /* will return later */ 1548 case RECALWAIT: 1549 /* allow heads to settle */ 1550 timeout(fd_pseudointr, (caddr_t)fdcu, hz / 8); 1551 fdc->state = RECALCOMPLETE; 1552 return(0); /* will return later */ 1553 case RECALCOMPLETE: 1554 do { 1555 /* 1556 * See SEEKCOMPLETE for a comment on this: 1557 */ 1558 if (fd_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID) 1559 return 0; 1560 if(fdc->fdct == FDC_NE765 1561 && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC) 1562 return 0; /* hope for a real intr */ 1563 } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); 1564 if ((st0 & NE7_ST0_IC) != NE7_ST0_IC_NT || cyl != 0) 1565 { 1566 if(fdc->retry > 3) 1567 /* 1568 * a recalibrate from beyond cylinder 77 1569 * will "fail" due to the FDC limitations; 1570 * since people used to complain much about 1571 * the failure message, try not logging 1572 * this one if it seems to be the first 1573 * time in a line 1574 */ 1575 printf("fd%d: recal failed ST0 %b cyl %d\n", 1576 fdu, st0, NE7_ST0BITS, cyl); 1577 if(fdc->retry < 3) fdc->retry = 3; 1578 return(retrier(fdcu)); 1579 } 1580 fd->track = 0; 1581 /* Seek (probably) necessary */ 1582 fdc->state = DOSEEK; 1583 return(1); /* will return immediatly */ 1584 case MOTORWAIT: 1585 if(fd->flags & FD_MOTOR_WAIT) 1586 { 1587 return(0); /* time's not up yet */ 1588 } 1589 /* 1590 * since the controller was off, it has lost its 1591 * idea about the current track it were; thus, 1592 * recalibrate the bastard 1593 */ 1594 fdc->state = STARTRECAL; 1595 return(1); /* will return immediatly */ 1596 default: 1597 printf("fdc%d: Unexpected FD int->", fdcu); 1598 if (fd_read_status(fdc, fd->fdsu) == 0) 1599 printf("FDC status :%lx %lx %lx %lx %lx %lx %lx ", 1600 fdc->status[0], 1601 fdc->status[1], 1602 fdc->status[2], 1603 fdc->status[3], 1604 fdc->status[4], 1605 fdc->status[5], 1606 fdc->status[6] ); 1607 else 1608 printf("No status available "); 1609 if (fd_sense_int(fdc, &st0, &cyl) != 0) 1610 { 1611 printf("[controller is dead now]\n"); 1612 return(0); 1613 } 1614 printf("ST0 = %x, PCN = %x\n", st0, cyl); 1615 return(0); 1616 } 1617 /*XXX confusing: some branches return immediately, others end up here*/ 1618 return(1); /* Come back immediatly to new state */ 1619 } 1620 1621 static int 1622 retrier(fdcu) 1623 fdcu_t fdcu; 1624 { 1625 fdc_p fdc = fdc_data + fdcu; 1626 register struct buf *bp; 1627 1628 bp = TAILQ_FIRST(&fdc->head); 1629 1630 if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) 1631 goto fail; 1632 switch(fdc->retry) 1633 { 1634 case 0: case 1: case 2: 1635 fdc->state = SEEKCOMPLETE; 1636 break; 1637 case 3: case 4: case 5: 1638 fdc->state = STARTRECAL; 1639 break; 1640 case 6: 1641 fdc->state = RESETCTLR; 1642 break; 1643 case 7: 1644 break; 1645 default: 1646 fail: 1647 { 1648 dev_t sav_b_dev = bp->b_dev; 1649 /* Trick diskerr */ 1650 bp->b_dev = makedev(major(bp->b_dev), 1651 (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART); 1652 diskerr(bp, "fd", "hard error", LOG_PRINTF, 1653 fdc->fd->skip / DEV_BSIZE, 1654 (struct disklabel *)NULL); 1655 bp->b_dev = sav_b_dev; 1656 if (fdc->flags & FDC_STAT_VALID) 1657 { 1658 printf( 1659 " (ST0 %b ST1 %b ST2 %b cyl %ld hd %ld sec %ld)\n", 1660 fdc->status[0], NE7_ST0BITS, 1661 fdc->status[1], NE7_ST1BITS, 1662 fdc->status[2], NE7_ST2BITS, 1663 fdc->status[3], fdc->status[4], 1664 fdc->status[5]); 1665 } 1666 else 1667 printf(" (No status)\n"); 1668 } 1669 bp->b_flags |= B_ERROR; 1670 bp->b_error = EIO; 1671 bp->b_resid += bp->b_bcount - fdc->fd->skip; 1672 TAILQ_REMOVE(&fdc->head, bp, b_act); 1673 fdc->fd->skip = 0; 1674 biodone(bp); 1675 fdc->state = FINDWORK; 1676 fdc->fd = (fd_p) 0; 1677 fdc->fdu = -1; 1678 /* XXX abort current command, if any. */ 1679 return(1); 1680 } 1681 fdc->retry++; 1682 return(1); 1683 } 1684 1685 static int 1686 fdformat(dev, finfo, p) 1687 dev_t dev; 1688 struct fd_formb *finfo; 1689 struct proc *p; 1690 { 1691 fdu_t fdu; 1692 fd_p fd; 1693 1694 struct buf *bp; 1695 int rv = 0, s; 1696 size_t fdblk; 1697 1698 fdu = FDUNIT(minor(dev)); 1699 fd = &fd_data[fdu]; 1700 fdblk = 128 << fd->ft->secsize; 1701 1702 /* set up a buffer header for fdstrategy() */ 1703 bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 1704 if(bp == 0) 1705 return ENOBUFS; 1706 /* 1707 * keep the process from being swapped 1708 */ 1709 p->p_flag |= P_PHYSIO; 1710 bzero((void *)bp, sizeof(struct buf)); 1711 bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 1712 bp->b_proc = p; 1713 bp->b_dev = dev; 1714 1715 /* 1716 * calculate a fake blkno, so fdstrategy() would initiate a 1717 * seek to the requested cylinder 1718 */ 1719 bp->b_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) 1720 + finfo->head * fd->ft->sectrac) * fdblk / DEV_BSIZE; 1721 1722 bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 1723 bp->b_un.b_addr = (caddr_t)finfo; 1724 1725 /* now do the format */ 1726 fdstrategy(bp); 1727 1728 /* ...and wait for it to complete */ 1729 s = splbio(); 1730 while(!(bp->b_flags & B_DONE)) 1731 { 1732 rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 1733 if(rv == EWOULDBLOCK) 1734 break; 1735 } 1736 splx(s); 1737 1738 if(rv == EWOULDBLOCK) { 1739 /* timed out */ 1740 rv = EIO; 1741 biodone(bp); 1742 } 1743 if(bp->b_flags & B_ERROR) 1744 rv = bp->b_error; 1745 /* 1746 * allow the process to be swapped 1747 */ 1748 p->p_flag &= ~P_PHYSIO; 1749 free(bp, M_TEMP); 1750 return rv; 1751 } 1752 1753 /* 1754 * TODO: don't allocate buffer on stack. 1755 */ 1756 1757 int 1758 fdioctl(dev, cmd, addr, flag, p) 1759 dev_t dev; 1760 int cmd; 1761 caddr_t addr; 1762 int flag; 1763 struct proc *p; 1764 { 1765 fdu_t fdu = FDUNIT(minor(dev)); 1766 fd_p fd = &fd_data[fdu]; 1767 size_t fdblk; 1768 1769 struct fd_type *fdt; 1770 struct disklabel *dl; 1771 char buffer[DEV_BSIZE]; 1772 int error = 0; 1773 1774 #if NFT > 0 1775 int type = FDTYPE(minor(dev)); 1776 1777 /* check for a tape ioctl */ 1778 if (type & F_TAPE_TYPE) 1779 return ftioctl(dev, cmd, addr, flag, p); 1780 #endif 1781 1782 fdblk = 128 << fd->ft->secsize; 1783 1784 switch (cmd) 1785 { 1786 case DIOCGDINFO: 1787 bzero(buffer, sizeof (buffer)); 1788 dl = (struct disklabel *)buffer; 1789 dl->d_secsize = fdblk; 1790 fdt = fd_data[FDUNIT(minor(dev))].ft; 1791 dl->d_secpercyl = fdt->size / fdt->tracks; 1792 dl->d_type = DTYPE_FLOPPY; 1793 1794 if (readdisklabel(dkmodpart(dev, RAW_PART), fdstrategy, dl) 1795 == NULL) 1796 error = 0; 1797 else 1798 error = EINVAL; 1799 1800 *(struct disklabel *)addr = *dl; 1801 break; 1802 1803 case DIOCSDINFO: 1804 if ((flag & FWRITE) == 0) 1805 error = EBADF; 1806 break; 1807 1808 case DIOCWLABEL: 1809 if ((flag & FWRITE) == 0) 1810 error = EBADF; 1811 break; 1812 1813 case DIOCWDINFO: 1814 if ((flag & FWRITE) == 0) 1815 { 1816 error = EBADF; 1817 break; 1818 } 1819 1820 dl = (struct disklabel *)addr; 1821 1822 if ((error = setdisklabel((struct disklabel *)buffer, dl, 1823 (u_long)0)) != 0) 1824 break; 1825 1826 error = writedisklabel(dev, fdstrategy, 1827 (struct disklabel *)buffer); 1828 break; 1829 1830 case FD_FORM: 1831 if((flag & FWRITE) == 0) 1832 error = EBADF; /* must be opened for writing */ 1833 else if(((struct fd_formb *)addr)->format_version != 1834 FD_FORMAT_VERSION) 1835 error = EINVAL; /* wrong version of formatting prog */ 1836 else 1837 error = fdformat(dev, (struct fd_formb *)addr, p); 1838 break; 1839 1840 case FD_GTYPE: /* get drive type */ 1841 *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft; 1842 break; 1843 1844 case FD_STYPE: /* set drive type */ 1845 /* this is considered harmful; only allow for superuser */ 1846 if(suser(p->p_ucred, &p->p_acflag) != 0) 1847 return EPERM; 1848 *fd_data[FDUNIT(minor(dev))].ft = *(struct fd_type *)addr; 1849 break; 1850 1851 case FD_GOPTS: /* get drive options */ 1852 *(int *)addr = fd_data[FDUNIT(minor(dev))].options; 1853 break; 1854 1855 case FD_SOPTS: /* set drive options */ 1856 fd_data[FDUNIT(minor(dev))].options = *(int *)addr; 1857 break; 1858 1859 default: 1860 error = ENOTTY; 1861 break; 1862 } 1863 return (error); 1864 } 1865 1866 1867 static fd_devsw_installed = 0; 1868 1869 static void fd_drvinit(void *notused ) 1870 { 1871 1872 if( ! fd_devsw_installed ) { 1873 bdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &fd_bdevsw); 1874 fd_devsw_installed = 1; 1875 } 1876 } 1877 1878 SYSINIT(fddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,fd_drvinit,NULL) 1879 1880 #endif 1881 /* 1882 * Hello emacs, these are the 1883 * Local Variables: 1884 * c-indent-level: 8 1885 * c-continued-statement-offset: 8 1886 * c-continued-brace-offset: 0 1887 * c-brace-offset: -8 1888 * c-brace-imaginary-offset: 0 1889 * c-argdecl-indent: 8 1890 * c-label-offset: -8 1891 * c++-hanging-braces: 1 1892 * c++-access-specifier-offset: -8 1893 * c++-empty-arglist-indent: 8 1894 * c++-friend-offset: 0 1895 * End: 1896 */ 1897