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