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