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