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