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