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