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