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