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/buf.h> 64#include <sys/bus.h> 65#include <sys/conf.h> 66#include <sys/disklabel.h> 67#include <sys/devicestat.h> 68#include <sys/fcntl.h> 69#include <sys/malloc.h> 70#include <sys/module.h> 71#include <sys/proc.h> 72#include <sys/syslog.h> 73 74#include <sys/bus.h> 75#include <machine/bus.h> 76#include <sys/rman.h> 77 78#include <machine/clock.h> 79#include <machine/ioctl_fd.h> 80#include <machine/resource.h> 81#include <machine/stdarg.h> 82 83#ifdef DEVFS 84#include <sys/devfsext.h> 85#endif /* DEVFS */ 86 87#include <isa/isavar.h> 88#ifdef PC98 89#include <pc98/pc98/pc98.h> 90#include <pc98/pc98/pc98_machdep.h> 91#include <pc98/pc98/epsonio.h> 92#include <i386/isa/isa_dma.h> 93#include <pc98/pc98/fdreg.h> 94#else 95#include <i386/isa/isa.h> 96#include <i386/isa/isa_dma.h> 97#include <i386/isa/fdreg.h> 98#include <isa/rtc.h> 99#endif 100#include <isa/fdc.h> 101 102#ifdef FDC_YE 103#undef FDC_YE 104#warning "fix FDC_YE! - newbus casualty" 105#endif 106 107/* misuse a flag to identify format operation */ 108#define B_FORMAT B_XXX 109 110/* configuration flags */ 111#define FDC_PRETEND_D0 (1 << 0) /* pretend drive 0 to be there */ 112#ifdef FDC_YE 113#define FDC_IS_PCMCIA (1 << 1) /* if successful probe, then it's 114 a PCMCIA device */ 115#endif 116 117/* internally used only, not really from CMOS: */ 118#define RTCFDT_144M_PRETENDED 0x1000 119 120/* error returns for fd_cmd() */ 121#define FD_FAILED -1 122#define FD_NOT_VALID -2 123#define FDC_ERRMAX 100 /* do not log more */ 124 125#ifdef PC98 126#define NUMTYPES 5 127#define NUMDENS NUMTYPES 128#else 129#define NUMTYPES 14 130#define NUMDENS (NUMTYPES - 6) 131#endif 132 133/* These defines (-1) must match index for fd_types */ 134#define F_TAPE_TYPE 0x020 /* bit for fd_types to indicate tape */ 135#define NO_TYPE 0 /* must match NO_TYPE in ft.c */ 136#ifdef PC98 137#define FDT_NONE 0 /* none present */ 138#define FDT_12M 1 /* 1M/640K FDD */ 139#define FDT_144M 2 /* 1.44M/1M/640K FDD */ 140 141#define FD_1200 1 142#define FD_1232 2 143#define FD_720 3 144#define FD_640 4 145#define FD_1440 5 146#else 147#define FD_1720 1 148#define FD_1480 2 149#define FD_1440 3 150#define FD_1200 4 151#define FD_820 5 152#define FD_800 6 153#define FD_720 7 154#define FD_360 8 155 156#define FD_1480in5_25 9 157#define FD_1440in5_25 10 158#define FD_820in5_25 11 159#define FD_800in5_25 12 160#define FD_720in5_25 13 161#define FD_360in5_25 14 162#endif 163 164 165static struct fd_type fd_types[NUMTYPES] = 166{ 167#ifdef PC98 168{ 15,2,0xFF,0x1B,80,2400,1,0,2,0x54,1 }, /* 1.2 meg HD floppy */ 169{ 8,3,0xFF,0x35,77,1232,1,0,2,0x74,1 }, /* 1.2 meg HD floppy 1024/sec */ 170{ 9,2,0xFF,0x20,80,1440,1,1,2,0x50,1 }, /* 720k floppy in 1.2meg drive */ 171{ 8,2,0xFF,0x2A,80,1280,1,1,2,0x50,1 }, /* 640k floppy in 1.2meg drive */ 172{ 18,2,0xFF,0x1B,80,2880,1,2,2,0x54,1 }, /* 1.44 meg HD 3.5in floppy */ 173#else 174{ 21,2,0xFF,0x04,82,3444,1,FDC_500KBPS,2,0x0C,2 }, /* 1.72M in HD 3.5in */ 175{ 18,2,0xFF,0x1B,82,2952,1,FDC_500KBPS,2,0x6C,1 }, /* 1.48M in HD 3.5in */ 176{ 18,2,0xFF,0x1B,80,2880,1,FDC_500KBPS,2,0x6C,1 }, /* 1.44M in HD 3.5in */ 177{ 15,2,0xFF,0x1B,80,2400,1,FDC_500KBPS,2,0x54,1 }, /* 1.2M in HD 5.25/3.5 */ 178{ 10,2,0xFF,0x10,82,1640,1,FDC_250KBPS,2,0x2E,1 }, /* 820K in HD 3.5in */ 179{ 10,2,0xFF,0x10,80,1600,1,FDC_250KBPS,2,0x2E,1 }, /* 800K in HD 3.5in */ 180{ 9,2,0xFF,0x20,80,1440,1,FDC_250KBPS,2,0x50,1 }, /* 720K in HD 3.5in */ 181{ 9,2,0xFF,0x2A,40, 720,1,FDC_250KBPS,2,0x50,1 }, /* 360K in DD 5.25in */ 182 183{ 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,0x02,2 }, /* 1.48M in HD 5.25in */ 184{ 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,0x02,2 }, /* 1.44M in HD 5.25in */ 185{ 10,2,0xFF,0x10,82,1640,1,FDC_300KBPS,2,0x2E,1 }, /* 820K in HD 5.25in */ 186{ 10,2,0xFF,0x10,80,1600,1,FDC_300KBPS,2,0x2E,1 }, /* 800K in HD 5.25in */ 187{ 9,2,0xFF,0x20,80,1440,1,FDC_300KBPS,2,0x50,1 }, /* 720K in HD 5.25in */ 188{ 9,2,0xFF,0x23,40, 720,2,FDC_300KBPS,2,0x50,1 }, /* 360K in HD 5.25in */ 189#endif 190}; 191 192#ifdef PC98 193#define DRVS_PER_CTLR 4 /* 4 floppies */ 194#else 195#define DRVS_PER_CTLR 2 /* 2 floppies */ 196#endif 197 198/***********************************************************************\ 199* Per controller structure. * 200\***********************************************************************/ 201static devclass_t fdc_devclass; 202 203/***********************************************************************\ 204* Per drive structure. * 205* N per controller (DRVS_PER_CTLR) * 206\***********************************************************************/ 207struct fd_data { 208 struct fdc_data *fdc; /* pointer to controller structure */ 209 int fdsu; /* this units number on this controller */ 210 int type; /* Drive type (FD_1440...) */ 211 struct fd_type *ft; /* pointer to the type descriptor */ 212 int flags; 213#define FD_OPEN 0x01 /* it's open */ 214#define FD_ACTIVE 0x02 /* it's active */ 215#define FD_MOTOR 0x04 /* motor should be on */ 216#define FD_MOTOR_WAIT 0x08 /* motor coming up */ 217 int skip; 218 int hddrv; 219#define FD_NO_TRACK -2 220 int track; /* where we think the head is */ 221 int options; /* user configurable options, see ioctl_fd.h */ 222 struct callout_handle toffhandle; 223 struct callout_handle tohandle; 224 struct devstat device_stats; 225#ifdef DEVFS 226 void *bdevs[1 + NUMDENS + MAXPARTITIONS]; 227 void *cdevs[1 + NUMDENS + MAXPARTITIONS]; 228#endif 229#ifdef PC98 230 int pc98_trans; 231#endif 232 device_t dev; 233 fdu_t fdu; 234}; 235static devclass_t fd_devclass; 236 237#ifdef EPSON_NRDISK 238typedef unsigned int nrd_t; 239 240#define P_NRD_ADDRH 0xc24 241#define P_NRD_ADDRM 0xc22 242#define P_NRD_ADDRL 0xc20 243#define P_NRD_CHECK 0xc20 244#define P_NRD_DATA 0xc26 245#define P_NRD_LED 0xc36 246#define B_NRD_CHK 0x80 247#define B_NRD_LED 0x40 248#define A_NRD_INFO 0x2 249#define A_NRD_BASE 0x400 250#define NRD_STATUS 0x0 251#define NRD_ST0_HD 0x04 252 253static fdu_t nrdu=-1; 254static int nrdsec=0; 255static nrd_t nrdblkn=0; 256static nrd_t nrdaddr=0x0; 257 258#define nrd_check_ready() ({ \ 259 (epson_inb(P_NRD_CHECK) & B_NRD_CHK) ? 0 : 1; \ 260 }) 261#define nrd_LED_on() epson_outb(P_NRD_LED, B_NRD_LED) 262#define nrd_LED_off() epson_outb(P_NRD_LED, ~B_NRD_LED) 263#define nrd_trac() ((int)(nrd_info(nrdaddr) & 0xff)) 264#define nrd_head() ((int)((nrd_info(nrdaddr) >> 8) & 0xff)) 265#define nrd_sec() ((int)(nrd_info(nrdaddr + 2) & 0xff)) 266#define nrd_secsize() ((int)((nrd_info(A_NRD_INFO) >> 8) & 0xff)) 267#define nrd_addrset(p) nrd_addr((nrd_t)((nrd_t)p+A_NRD_BASE)) 268 269static inline void 270nrd_addr(addr) 271 nrd_t addr; 272{ 273 epson_outb(P_NRD_ADDRH, (u_char)((addr >> 16) & 0x1f)); 274 epson_outb(P_NRD_ADDRM, (u_char)((addr >> 8) & 0xff)); 275 epson_outb(P_NRD_ADDRL, (u_char)(addr & 0xff)); 276} 277 278static inline u_short 279nrd_info(addr) 280 nrd_t addr; 281{ 282 u_short tmp; 283 284 nrd_addr(addr); 285 outb(0x43f, 0x42); 286 tmp = (short)inw(P_NRD_DATA); 287 outb(0x43f, 0x40); 288 return ((u_short)tmp); 289} 290#endif /* EPSON_NRDISK */ 291 292/***********************************************************************\ 293* Throughout this file the following conventions will be used: * 294* fd is a pointer to the fd_data struct for the drive in question * 295* fdc is a pointer to the fdc_data struct for the controller * 296* fdu is the floppy drive unit number * 297* fdcu is the floppy controller unit number * 298* fdsu is the floppy drive unit number on that controller. (sub-unit) * 299\***********************************************************************/ 300 301#ifdef FDC_YE 302#include "card.h" 303static int yeattach(struct isa_device *); 304#endif 305 306/* needed for ft driver, thus exported */ 307int in_fdc(struct fdc_data *); 308int out_fdc(struct fdc_data *, int); 309 310/* internal functions */ 311static void fdc_add_device(device_t, const char *, int); 312static void fdc_intr(void *); 313static void set_motor(struct fdc_data *, int, int); 314# define TURNON 1 315# define TURNOFF 0 316static timeout_t fd_turnoff; 317static timeout_t fd_motor_on; 318static void fd_turnon(struct fd_data *); 319static void fdc_reset(fdc_p); 320static int fd_in(struct fdc_data *, int *); 321static void fdstart(struct fdc_data *); 322static timeout_t fd_iotimeout; 323static timeout_t fd_pseudointr; 324static int fdstate(struct fdc_data *); 325static int retrier(struct fdc_data *); 326static int fdformat(dev_t, struct fd_formb *, struct proc *); 327 328static int enable_fifo(fdc_p fdc); 329 330static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */ 331 332 333#define DEVIDLE 0 334#define FINDWORK 1 335#define DOSEEK 2 336#define SEEKCOMPLETE 3 337#define IOCOMPLETE 4 338#define RECALCOMPLETE 5 339#define STARTRECAL 6 340#define RESETCTLR 7 341#define SEEKWAIT 8 342#define RECALWAIT 9 343#define MOTORWAIT 10 344#define IOTIMEDOUT 11 345#define RESETCOMPLETE 12 346#ifdef FDC_YE 347#define PIOREAD 13 348#endif 349 350#ifdef FDC_DEBUG 351static char const * const fdstates[] = 352{ 353"DEVIDLE", 354"FINDWORK", 355"DOSEEK", 356"SEEKCOMPLETE", 357"IOCOMPLETE", 358"RECALCOMPLETE", 359"STARTRECAL", 360"RESETCTLR", 361"SEEKWAIT", 362"RECALWAIT", 363"MOTORWAIT", 364"IOTIMEDOUT", 365"RESETCOMPLETE", 366#ifdef FDC_YE 367"PIOREAD", 368#endif 369}; 370 371/* CAUTION: fd_debug causes huge amounts of logging output */ 372static int volatile fd_debug = 0; 373#define TRACE0(arg) if(fd_debug) printf(arg) 374#define TRACE1(arg1, arg2) if(fd_debug) printf(arg1, arg2) 375#else /* FDC_DEBUG */ 376#define TRACE0(arg) 377#define TRACE1(arg1, arg2) 378#endif /* FDC_DEBUG */ 379 380#ifdef FDC_YE 381#if NCARD > 0 382#include <sys/select.h> 383#include <sys/module.h> 384#include <pccard/cardinfo.h> 385#include <pccard/driver.h> 386#include <pccard/slot.h> 387 388/* 389 * PC-Card (PCMCIA) specific code. 390 */ 391static int yeinit(struct pccard_devinfo *); /* init device */ 392static void yeunload(struct pccard_devinfo *); /* Disable driver */ 393static int yeintr(struct pccard_devinfo *); /* Interrupt handler */ 394 395PCCARD_MODULE(fdc, yeinit, yeunload, yeintr, 0, bio_imask); 396 397/* 398 * this is the secret PIO data port (offset from base) 399 */ 400#define FDC_YE_DATAPORT 6 401 402/* 403 * Initialize the device - called from Slot manager. 404 */ 405static int yeinit(struct pccard_devinfo *devi) 406{ 407 fdc_p fdc = &fdc_data[devi->isahd.id_unit]; 408 409 /* validate unit number. */ 410 if (devi->isahd.id_unit >= NFDC) 411 return(ENODEV); 412 fdc->baseport = devi->isahd.id_iobase; 413 /* 414 * reset controller 415 */ 416 outb(fdc->baseport+FDOUT, 0); 417 DELAY(100); 418 outb(fdc->baseport+FDOUT, FDO_FRST); 419 420 /* 421 * wire into system 422 */ 423 if (yeattach(&devi->isahd) == 0) 424 return(ENXIO); 425 426 return(0); 427} 428 429/* 430 * yeunload - unload the driver and clear the table. 431 * XXX TODO: 432 * This is usually called when the card is ejected, but 433 * can be caused by a modunload of a controller driver. 434 * The idea is to reset the driver's view of the device 435 * and ensure that any driver entry points such as 436 * read and write do not hang. 437 */ 438static void yeunload(struct pccard_devinfo *devi) 439{ 440 if (fd_data[devi->isahd.id_unit].type == NO_TYPE) 441 return; 442 443 /* 444 * this prevents Fdopen() and fdstrategy() from attempting 445 * to access unloaded controller 446 */ 447 fd_data[devi->isahd.id_unit].type = NO_TYPE; 448 449 printf("fdc%d: unload\n", devi->isahd.id_unit); 450} 451 452/* 453 * yeintr - Shared interrupt called from 454 * front end of PC-Card handler. 455 */ 456static int yeintr(struct pccard_devinfo *devi) 457{ 458 fdintr((fdcu_t)devi->isahd.id_unit); 459 return(1); 460} 461#endif /* NCARD > 0 */ 462#endif /* FDC_YE */ 463 464static d_open_t Fdopen; /* NOTE, not fdopen */ 465static d_close_t fdclose; 466static d_ioctl_t fdioctl; 467static d_strategy_t fdstrategy; 468 469#define CDEV_MAJOR 9 470#define BDEV_MAJOR 2 471 472static struct cdevsw fd_cdevsw = { 473 /* open */ Fdopen, 474 /* close */ fdclose, 475 /* read */ physread, 476 /* write */ physwrite, 477 /* ioctl */ fdioctl, 478 /* stop */ nostop, 479 /* reset */ noreset, 480 /* devtotty */ nodevtotty, 481 /* poll */ nopoll, 482 /* mmap */ nommap, 483 /* strategy */ fdstrategy, 484 /* name */ "fd", 485 /* parms */ noparms, 486 /* maj */ CDEV_MAJOR, 487 /* dump */ nodump, 488 /* psize */ nopsize, 489 /* flags */ D_DISK, 490 /* maxio */ 0, 491 /* bmaj */ BDEV_MAJOR 492}; 493 494static int 495fdc_err(struct fdc_data *fdc, const char *s) 496{ 497 fdc->fdc_errs++; 498 if (s) { 499 if (fdc->fdc_errs < FDC_ERRMAX) { 500 device_print_prettyname(fdc->fdc_dev); 501 printf("%s", s); 502 } else if (fdc->fdc_errs == FDC_ERRMAX) { 503 device_print_prettyname(fdc->fdc_dev); 504 printf("too many errors, not logging any more\n"); 505 } 506 } 507 508 return FD_FAILED; 509} 510 511/* 512 * fd_cmd: Send a command to the chip. Takes a varargs with this structure: 513 * Unit number, 514 * # of output bytes, output bytes as ints ..., 515 * # of input bytes, input bytes as ints ... 516 */ 517static int 518fd_cmd(struct fdc_data *fdc, int n_out, ...) 519{ 520 u_char cmd; 521 int n_in; 522 int n; 523 va_list ap; 524 525 va_start(ap, n_out); 526 cmd = (u_char)(va_arg(ap, int)); 527 va_end(ap); 528 va_start(ap, n_out); 529 for (n = 0; n < n_out; n++) 530 { 531 if (out_fdc(fdc, va_arg(ap, int)) < 0) 532 { 533 char msg[50]; 534 snprintf(msg, sizeof(msg), 535 "cmd %x failed at out byte %d of %d\n", 536 cmd, n + 1, n_out); 537 return fdc_err(fdc, msg); 538 } 539 } 540 n_in = va_arg(ap, int); 541 for (n = 0; n < n_in; n++) 542 { 543 int *ptr = va_arg(ap, int *); 544 if (fd_in(fdc, ptr) < 0) 545 { 546 char msg[50]; 547 snprintf(msg, sizeof(msg), 548 "cmd %02x failed at in byte %d of %d\n", 549 cmd, n + 1, n_in); 550 return fdc_err(fdc, msg); 551 } 552 } 553 554 return 0; 555} 556 557static int 558enable_fifo(fdc_p fdc) 559{ 560 int i, j; 561 562 if ((fdc->flags & FDC_HAS_FIFO) == 0) { 563 564 /* 565 * XXX: 566 * Cannot use fd_cmd the normal way here, since 567 * this might be an invalid command. Thus we send the 568 * first byte, and check for an early turn of data directon. 569 */ 570 571 if (out_fdc(fdc, I8207X_CONFIGURE) < 0) 572 return fdc_err(fdc, "Enable FIFO failed\n"); 573 574 /* If command is invalid, return */ 575 j = 100000; 576 while ((i = inb(fdc->baseport + FDSTS) & (NE7_DIO | NE7_RQM)) 577 != NE7_RQM && j-- > 0) 578 if (i == (NE7_DIO | NE7_RQM)) { 579 fdc_reset(fdc); 580 return FD_FAILED; 581 } 582 if (j<0 || 583 fd_cmd(fdc, 3, 584 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) { 585 fdc_reset(fdc); 586 return fdc_err(fdc, "Enable FIFO failed\n"); 587 } 588 fdc->flags |= FDC_HAS_FIFO; 589 return 0; 590 } 591 if (fd_cmd(fdc, 4, 592 I8207X_CONFIGURE, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) 593 return fdc_err(fdc, "Re-enable FIFO failed\n"); 594 return 0; 595} 596 597static int 598fd_sense_drive_status(fdc_p fdc, int *st3p) 599{ 600 int st3; 601 602 if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) 603 { 604 return fdc_err(fdc, "Sense Drive Status failed\n"); 605 } 606 if (st3p) 607 *st3p = st3; 608 609 return 0; 610} 611 612static int 613fd_sense_int(fdc_p fdc, int *st0p, int *cylp) 614{ 615 int cyl, st0, ret; 616 617#ifdef EPSON_NRDISK 618 if (fdc->fdu == nrdu) { 619 if (fdc->fd->track >= 0) nrdaddr = (fdc->fd->track + 1) * 8; 620 else nrdaddr = 0x0; 621 *st0p = nrd_head() ? NRD_ST0_HD : NRD_STATUS; 622 *cylp = nrd_trac(); 623 } 624 else { 625#endif /* EPSON_NRDISK */ 626 ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0); 627 if (ret) { 628 (void)fdc_err(fdc, 629 "sense intr err reading stat reg 0\n"); 630 return ret; 631 } 632 633 if (st0p) 634 *st0p = st0; 635 636 if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) { 637 /* 638 * There doesn't seem to have been an interrupt. 639 */ 640 return FD_NOT_VALID; 641 } 642 643 if (fd_in(fdc, &cyl) < 0) { 644 return fdc_err(fdc, "can't get cyl num\n"); 645 } 646 647 if (cylp) 648 *cylp = cyl; 649 650#ifdef EPSON_NRDISK 651 } 652#endif /* EPSON_NRDISK */ 653 return 0; 654} 655 656 657static int 658fd_read_status(fdc_p fdc, int fdsu) 659{ 660 int i, ret; 661 662 for (i = 0; i < 7; i++) { 663 /* 664 * XXX types are poorly chosen. Only bytes can by read 665 * from the hardware, but fdc->status[] wants u_ints and 666 * fd_in() gives ints. 667 */ 668 int status; 669 670#ifdef EPSON_NRDISK 671 if (fdc->fdu == nrdu) { 672 switch (i) { 673 case 0: fdc->status[i] = nrd_head() 674 ? NRD_ST0_HD : NRD_STATUS; break; 675 case 1: fdc->status[i] = NRD_STATUS; break; 676 case 2: fdc->status[i] = NRD_STATUS; break; 677 case 3: fdc->status[i] = nrd_trac(); break; 678 case 4: fdc->status[i] = nrd_head(); break; 679 case 5: fdc->status[i] = nrdsec; break; 680 case 6: fdc->status[i] = nrd_secsize(); break; 681 } 682 ret = 0; 683 } 684 else { 685#endif /* EPSON_NRDISK */ 686 ret = fd_in(fdc, &status); 687 fdc->status[i] = status; 688 if (ret != 0) 689 break; 690#ifdef EPSON_NRDISK 691 } 692#endif /* EPSON_NRDISK */ 693 } 694 695 if (ret == 0) 696 fdc->flags |= FDC_STAT_VALID; 697 else 698 fdc->flags &= ~FDC_STAT_VALID; 699 700 return ret; 701} 702 703/****************************************************************************/ 704/* autoconfiguration stuff */ 705/****************************************************************************/ 706#ifdef PC98 707static int pc98_trans = 0; /* 0 : HD , 1 : DD , 2 : 1.44 */ 708static int pc98_trans_prev = 0; 709 710static void set_density(fdc_p fdc) 711{ 712 /* always motor on */ 713 outb(IO_FDPORT, (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC); 714 DELAY(100); 715 outb(fdc->baseport + FDOUT, FDO_RST | FDO_DMAE); 716 /* in the case of note W, always inhibit 100ms timer */ 717} 718 719static int pc98_fd_check_ready(fdu_t fdu) 720{ 721 fd_p fd = devclass_get_softc(fd_devclass, fdu); 722 struct fdc_data *fdc = fd->fdc; 723 int retry = 0; 724 725#ifdef EPSON_NRDISK 726 if (fdu == nrdu) { 727 if (nrd_check_ready()) return 0; 728 else return -1; 729 } 730#endif 731 while (retry++ < 30000) { 732 set_motor(fdc, fd->fdsu, TURNON); 733 out_fdc(fdc, NE7CMD_SENSED); /* Sense Drive Status */ 734 DELAY(100); 735 out_fdc(fdc, fdu); /* Drive number */ 736 DELAY(100); 737 if ((in_fdc(fdc) & NE7_ST3_RD)){ 738 outb(fdc->baseport + FDOUT, 739 FDO_DMAE | FDO_MTON); 740 DELAY(10); 741 return 0; 742 } 743 } 744 return -1; 745} 746#endif 747 748static int 749fdc_probe(device_t dev) 750{ 751 int error, i, ic_type; 752 struct fdc_data *fdc; 753 char myname[8]; /* better be long enough */ 754 755 fdc = device_get_softc(dev); 756 bzero(fdc, sizeof *fdc); 757 fdc->fdc_dev = dev; 758 fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0; 759 fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0; 760 761 fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, 762 &fdc->rid_ioport, 0ul, ~0ul, 763 IO_FDCSIZE, RF_ACTIVE); 764 if (fdc->res_ioport == 0) { 765 device_print_prettyname(dev); 766 printf("cannot reserve I/O port range\n"); 767 error = ENXIO; 768 goto out; 769 } 770 fdc->baseport = fdc->res_ioport->r_start; 771 772 fdc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, 773 &fdc->rid_irq, 0ul, ~0ul, 1, 774 RF_ACTIVE); 775 if (fdc->res_irq == 0) { 776 device_print_prettyname(dev); 777 printf("cannot reserve interrupt line\n"); 778 error = ENXIO; 779 goto out; 780 } 781 fdc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, 782 &fdc->rid_drq, 0ul, ~0ul, 1, 783 RF_ACTIVE); 784 if (fdc->res_drq == 0) { 785 device_print_prettyname(dev); 786 printf("cannot reserve DMA request line\n"); 787 error = ENXIO; 788 goto out; 789 } 790 fdc->dmachan = fdc->res_drq->r_start; 791 error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq, 792 INTR_TYPE_BIO, fdc_intr, fdc, &fdc->fdc_intr); 793 794#ifndef PC98 795 /* First - lets reset the floppy controller */ 796 outb(fdc->baseport + FDOUT, 0); 797 DELAY(100); 798 outb(fdc->baseport + FDOUT, FDO_FRST); 799#endif 800 801 /* see if it can handle a command */ 802#ifdef PC98 803 if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240), 804 NE7_SPEC_2(2, 0), 0)) { 805 error = ENXIO; 806 goto out; 807 } 808#else 809 if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), 810 NE7_SPEC_2(2, 0), 0)) { 811 error = ENXIO; 812 goto out; 813 } 814#endif 815 816#ifndef PC98 817 if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) { 818 ic_type = (u_char)ic_type; 819 switch (ic_type) { 820 case 0x80: 821 device_set_desc(dev, "NEC 765 or clone"); 822 fdc->fdct = FDC_NE765; 823 break; 824 case 0x81: 825 device_set_desc(dev, "Intel 82077 or clone"); 826 fdc->fdct = FDC_I82077; 827 break; 828 case 0x90: 829 device_set_desc(dev, "NEC 72065B or clone"); 830 fdc->fdct = FDC_NE72065; 831 break; 832 default: 833 device_set_desc(dev, "generic floppy controller"); 834 fdc->fdct = FDC_UNKNOWN; 835 break; 836 } 837 } 838#endif 839 840 snprintf(myname, sizeof(myname), "%s%d", device_get_name(dev), 841 device_get_unit(dev)); 842 for (i = resource_query_string(-1, "at", myname); i != -1; 843 i = resource_query_string(i, "at", myname)) 844 fdc_add_device(dev, resource_query_name(i), 845 resource_query_unit(i)); 846#ifdef FDC_YE 847 /* 848 * don't succeed on probe; wait 849 * for PCCARD subsystem to do it 850 */ 851 if (dev->id_flags & FDC_IS_PCMCIA) 852 return(0); 853#endif 854 return (0); 855 856out: 857 if (fdc->fdc_intr) 858 BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq, 859 fdc->fdc_intr); 860 if (fdc->res_irq != 0) { 861 bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq, 862 fdc->res_irq); 863 bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq, 864 fdc->res_irq); 865 } 866 if (fdc->res_ioport != 0) { 867 bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, 868 fdc->res_ioport); 869 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, 870 fdc->res_ioport); 871 } 872 if (fdc->res_drq != 0) { 873 bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq, 874 fdc->res_drq); 875 bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq, 876 fdc->res_drq); 877 } 878 return (error); 879} 880 881/* 882 * Aped dfr@freebsd.org's isa_add_device(). 883 */ 884static void 885fdc_add_device(device_t dev, const char *name, int unit) 886{ 887 int disabled, *ivar; 888 device_t child; 889 890 ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT); 891 if (ivar == 0) 892 return; 893 if (resource_int_value(name, unit, "drive", ivar) == 0) 894 *ivar = 0; 895 child = device_add_child(dev, name, unit, ivar); 896 if (child == 0) 897 return; 898 if (resource_int_value(name, unit, "disabled", &disabled) == 0) 899 device_disable(child); 900} 901 902static int 903fdc_attach(device_t dev) 904{ 905 struct fdc_data *fdc = device_get_softc(dev); 906 fdcu_t fdcu = device_get_unit(dev); 907 908 fdc->fdcu = fdcu; 909 fdc->flags |= FDC_ATTACHED; 910 911 /* Acquire the DMA channel forever, The driver will do the rest */ 912 /* XXX should integrate with rman */ 913 isa_dma_acquire(fdc->dmachan); 914 isa_dmainit(fdc->dmachan, 128 << 3 /* XXX max secsize */); 915 fdc->state = DEVIDLE; 916 917#ifdef PC98 918 /* reset controller, turn motor off, clear fdout mirror reg */ 919 fdc_reset(fdc); 920#else 921 /* reset controller, turn motor off, clear fdout mirror reg */ 922 outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); 923#endif 924 bufq_init(&fdc->head); 925 926#ifdef FIFO_BEFORE_MOTORON 927 /* Hmm, this doesn't work here - is set_motor() magic? -Peter */ 928 if (fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN 929 && enable_fifo(fdc) == 0) { 930 device_print_prettyname(dev); 931 printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); 932 } 933#endif 934 /* 935 * Probe and attach any children as were configured above. 936 */ 937 return (bus_generic_attach(dev)); 938} 939 940static void 941fdc_print_child(device_t me, device_t child) 942{ 943 printf(" at %s%d drive %d", device_get_name(me), device_get_unit(me), 944 *(int *)device_get_ivars(child)); 945} 946 947static int 948fd_probe(device_t dev) 949{ 950 int i; 951 u_int fdt, st0, st3; 952 struct fd_data *fd; 953 struct fdc_data *fdc; 954 fdsu_t fdsu; 955#ifndef FIFO_BEFORE_MOTORON 956 static int fd_fifo = 0; 957#endif 958 959 fdsu = *(int *)device_get_ivars(dev); /* xxx cheat a bit... */ 960 fd = device_get_softc(dev); 961 fdc = device_get_softc(device_get_parent(dev)); 962 963 bzero(fd, sizeof *fd); 964 fd->dev = dev; 965 fd->fdc = fdc; 966 fd->fdsu = fdsu; 967 fd->fdu = device_get_unit(dev); 968 969#ifdef PC98 970 /* look up what bios thinks we have */ 971 switch (fd->fdu) { 972 case 0: case 1: case 2: case 3: 973 if ((PC98_SYSTEM_PARAMETER(0x5ae) >> fd->fdu) & 0x01) 974 fdt = FDT_144M; 975#ifdef EPSON_NRDISK 976 else if ((PC98_SYSTEM_PARAMETER(0x55c) >> fd->fdu) & 0x01) { 977 fdt = FDT_12M; 978 switch (epson_machine_id) { 979 case 0x20: case 0x27: 980 if ((PC98_SYSTEM_PARAMETER(0x488) >> fd->fdu) & 0x01) { 981 if (nrd_check_ready()) { 982 nrd_LED_on(); 983 nrdu = fd->fdu; 984 } else { 985 fdt = FDT_NONE; 986 } 987 } 988 } 989 } 990#else /* !EPSON_NRDISK */ 991 else if ((PC98_SYSTEM_PARAMETER(0x55c) >> fd->fdu) & 0x01) { 992 fdt = FDT_12M; 993 switch (epson_machine_id) { 994 case 0x20: case 0x27: 995 if ((PC98_SYSTEM_PARAMETER(0x488) >> fd->fdu) & 0x01) 996 fdt = FDT_NONE; 997 } 998 } 999#endif /* EPSON_NRDISK */ 1000 else 1001 fdt = FDT_NONE; 1002 break; 1003 default: 1004 fdt = FDT_NONE; 1005 break; 1006 } 1007#else 1008 /* look up what bios thinks we have */ 1009 switch (fd->fdu) { 1010 case 0: 1011 if (isa_get_flags(fdc->fdc_dev) & FDC_PRETEND_D0) 1012 fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED; 1013 else 1014 fdt = (rtcin(RTC_FDISKETTE) & 0xf0); 1015 break; 1016 case 1: 1017 fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); 1018 break; 1019 default: 1020 fdt = RTCFDT_NONE; 1021 break; 1022 } 1023#endif 1024 1025 /* is there a unit? */ 1026#ifdef PC98 1027 if (fdt == FDT_NONE) 1028 return (ENXIO); 1029#else 1030 if (fdt == RTCFDT_NONE) 1031 return (ENXIO); 1032#endif 1033 1034#ifndef PC98 1035 /* select it */ 1036 set_motor(fdc, fdsu, TURNON); 1037 DELAY(1000000); /* 1 sec */ 1038 1039#ifndef FIFO_BEFORE_MOTORON 1040 if (fd_fifo == 0 && fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN 1041 && enable_fifo(fdc) == 0) { 1042 device_print_prettyname(device_get_parent(dev)); 1043 printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); 1044 } 1045 fd_fifo = 1; 1046#endif 1047 1048 if ((fd_cmd(fdc, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) 1049 && (st3 & NE7_ST3_T0)) { 1050 /* if at track 0, first seek inwards */ 1051 /* seek some steps: */ 1052 fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0); 1053 DELAY(300000); /* ...wait a moment... */ 1054 fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ 1055 } 1056 1057 /* If we're at track 0 first seek inwards. */ 1058 if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) { 1059 /* Seek some steps... */ 1060 if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { 1061 /* ...wait a moment... */ 1062 DELAY(300000); 1063 /* make ctrlr happy: */ 1064 fd_sense_int(fdc, 0, 0); 1065 } 1066 } 1067 1068 for (i = 0; i < 2; i++) { 1069 /* 1070 * we must recalibrate twice, just in case the 1071 * heads have been beyond cylinder 76, since most 1072 * FDCs still barf when attempting to recalibrate 1073 * more than 77 steps 1074 */ 1075 /* go back to 0: */ 1076 if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) { 1077 /* a second being enough for full stroke seek*/ 1078 DELAY(i == 0 ? 1000000 : 300000); 1079 1080 /* anything responding? */ 1081 if (fd_sense_int(fdc, &st0, 0) == 0 && 1082 (st0 & NE7_ST0_EC) == 0) 1083 break; /* already probed succesfully */ 1084 } 1085 } 1086 1087 set_motor(fdc, fdsu, TURNOFF); 1088 1089 if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ 1090 return (ENXIO); 1091#endif /* PC98 */ 1092 1093 fd->track = FD_NO_TRACK; 1094 fd->fdc = fdc; 1095 fd->fdsu = fdsu; 1096 fd->options = 0; 1097 callout_handle_init(&fd->toffhandle); 1098 callout_handle_init(&fd->tohandle); 1099 1100#ifdef PC98 1101 switch (fdt) { 1102 case FDT_12M: 1103#ifdef EPSON_NRDISK 1104 if (fdu == nrdu) { 1105 device_set_desc(dev, "EPSON RAM DRIVE"); 1106 nrd_LED_off(); 1107 } else 1108 device_set_desc(dev, "1M/640M FDD"); 1109#else 1110 device_set_desc(dev, "1M/640M FDD"); 1111#endif 1112 fd->type = FD_1200; 1113 fd->pc98_trans = 0; 1114 break; 1115 case FDT_144M: 1116 device_set_desc(dev, "1.44M FDD"); 1117 fd->type = FD_1200; 1118 fd->pc98_trans = 0; 1119 outb(0x4be, (fd->fdu << 5) | 0x10); 1120 break; 1121 default: 1122 return (ENXIO); 1123 } 1124#else 1125 switch (fdt) { 1126 case RTCFDT_12M: 1127 device_set_desc(dev, "1200-KB 5.25\" drive"); 1128 fd->type = FD_1200; 1129 break; 1130 case RTCFDT_144M | RTCFDT_144M_PRETENDED: 1131 device_set_desc(dev, "config-pretended 1440-MB 3.5\" drive"); 1132 fdt = RTCFDT_144M; 1133 fd->type = FD_1440; 1134 case RTCFDT_144M: 1135 device_set_desc(dev, "1440-KB 3.5\" drive"); 1136 fd->type = FD_1440; 1137 break; 1138 case RTCFDT_288M: 1139 case RTCFDT_288M_1: 1140 device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)"); 1141 fd->type = FD_1440; 1142 break; 1143 case RTCFDT_360K: 1144 device_set_desc(dev, "360-KB 5.25\" drive"); 1145 fd->type = FD_360; 1146 break; 1147 case RTCFDT_720K: 1148 printf("720-KB 3.5\" drive"); 1149 fd->type = FD_720; 1150 break; 1151 default: 1152 return (ENXIO); 1153 } 1154#endif 1155 return (0); 1156} 1157 1158static int 1159fd_attach(device_t dev) 1160{ 1161 struct fd_data *fd; 1162#ifdef DEVFS 1163 int i; 1164 int mynor; 1165 int typemynor; 1166 int typesize; 1167#endif 1168 1169 fd = device_get_softc(dev); 1170 1171#ifdef DEVFS /* XXX bitrot */ 1172 mynor = fd->fdu << 6; 1173 fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, 1174 UID_ROOT, GID_OPERATOR, 0640, 1175 "fd%d", fd->fdu); 1176 fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, 1177 UID_ROOT, GID_OPERATOR, 0640, 1178 "rfd%d", fd->fdu); 1179 for (i = 1; i < 1 + NUMDENS; i++) { 1180 /* 1181 * XXX this and the lookup in Fdopen() should be 1182 * data driven. 1183 */ 1184#ifdef PC98 1185 switch (fd->type) { 1186 case FDT_12M: 1187 if (i != FD_1200 && i != FD_1232 1188 && i != FD_720 && i != FD_640) 1189 continue; 1190 break; 1191 case FDT_144M: 1192 if (i != FD_1200 && i != FD_1232 1193 && i != FD_720 && i != FD_640 1194 && i != FD_1440) 1195 continue; 1196 break; 1197 } 1198#else 1199 switch (fd->type) { 1200 case FD_360: 1201 if (i != FD_360) 1202 continue; 1203 break; 1204 case FD_720: 1205 if (i != FD_720 && i != FD_800 && i != FD_820) 1206 continue; 1207 break; 1208 case FD_1200: 1209 if (i != FD_360 && i != FD_720 && i != FD_800 1210 && i != FD_820 && i != FD_1200 1211 && i != FD_1440 && i != FD_1480) 1212 continue; 1213 break; 1214 case FD_1440: 1215 if (i != FD_720 && i != FD_800 && i != FD_820 1216 && i != FD_1200 && i != FD_1440 1217 && i != FD_1480 && i != FD_1720) 1218 continue; 1219 break; 1220 } 1221#endif 1222#ifdef PC98 1223 if (i == FD_1232) 1224 typesize = fd_types[i - 1].size; 1225 else 1226 typesize = fd_types[i - 1].size / 2; 1227#else 1228 typesize = fd_types[i - 1].size / 2; 1229 /* 1230 * XXX all these conversions give bloated code and 1231 * confusing names. 1232 */ 1233 if (typesize == 1476) 1234 typesize = 1480; 1235 if (typesize == 1722) 1236 typesize = 1720; 1237#endif 1238 typemynor = mynor | i; 1239 fd->bdevs[i] = 1240 devfs_add_devswf(&fd_cdevsw, typemynor, DV_BLK, 1241 UID_ROOT, GID_OPERATOR, 0640, 1242 "fd%d.%d", fd->fdu, typesize); 1243 fd->cdevs[i] = 1244 devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, 1245 UID_ROOT, GID_OPERATOR, 0640, 1246 "rfd%d.%d", fd->fdu, typesize); 1247 } 1248 1249 for (i = 0; i < MAXPARTITIONS; i++) { 1250 fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], 1251 "fd%d%c", fd->fdu, 'a' + i); 1252 fd->cdevs[1 + NUMDENS + i] = 1253 devfs_makelink(fd->cdevs[0], 1254 "rfd%d%c", fd->fdu, 'a' + i); 1255 } 1256#endif /* DEVFS */ 1257 /* 1258 * Export the drive to the devstat interface. 1259 */ 1260 devstat_add_entry(&fd->device_stats, device_get_name(dev), 1261 device_get_unit(dev), 512, DEVSTAT_NO_ORDERED_TAGS, 1262 DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, 1263 DEVSTAT_PRIORITY_FD); 1264 return (0); 1265} 1266 1267#ifdef FDC_YE 1268/* 1269 * this is a subset of fdattach() optimized for the Y-E Data 1270 * PCMCIA floppy drive. 1271 */ 1272static int yeattach(struct isa_device *dev) 1273{ 1274 fdcu_t fdcu = dev->id_unit; 1275 fdc_p fdc = fdc_data + fdcu; 1276 fdsu_t fdsu = 0; /* assume 1 drive per YE controller */ 1277 fdu_t fdu; 1278 fd_p fd; 1279 int st0, st3, i; 1280#ifdef DEVFS 1281 int mynor; 1282 int typemynor; 1283 int typesize; 1284#endif 1285 fdc->fdcu = fdcu; 1286 /* 1287 * the FDC_PCMCIA flag is used to to indicate special PIO is used 1288 * instead of DMA 1289 */ 1290 fdc->flags = FDC_ATTACHED|FDC_PCMCIA; 1291 fdc->state = DEVIDLE; 1292 /* reset controller, turn motor off, clear fdout mirror reg */ 1293 outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); 1294 bufq_init(&fdc->head); 1295 /* 1296 * assume 2 drives/ "normal" controller 1297 */ 1298 fdu = fdcu * 2; 1299 if (fdu >= NFD) { 1300 printf("fdu %d >= NFD\n",fdu); 1301 return(0); 1302 }; 1303 fd = &fd_data[fdu]; 1304 1305 set_motor(fdcu, fdsu, TURNON); 1306 DELAY(1000000); /* 1 sec */ 1307 fdc->fdct = FDC_NE765; 1308 1309 if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && 1310 (st3 & NE7_ST3_T0)) { 1311 /* if at track 0, first seek inwards */ 1312 /* seek some steps: */ 1313 (void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0); 1314 DELAY(300000); /* ...wait a moment... */ 1315 (void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ 1316 } 1317 1318 /* If we're at track 0 first seek inwards. */ 1319 if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) { 1320 /* Seek some steps... */ 1321 if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { 1322 /* ...wait a moment... */ 1323 DELAY(300000); 1324 /* make ctrlr happy: */ 1325 (void)fd_sense_int(fdc, 0, 0); 1326 } 1327 } 1328 1329 for(i = 0; i < 2; i++) { 1330 /* 1331 * we must recalibrate twice, just in case the 1332 * heads have been beyond cylinder 76, since most 1333 * FDCs still barf when attempting to recalibrate 1334 * more than 77 steps 1335 */ 1336 /* go back to 0: */ 1337 if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) { 1338 /* a second being enough for full stroke seek*/ 1339 DELAY(i == 0? 1000000: 300000); 1340 1341 /* anything responding? */ 1342 if (fd_sense_int(fdc, &st0, 0) == 0 && 1343 (st0 & NE7_ST0_EC) == 0) 1344 break; /* already probed succesfully */ 1345 } 1346 } 1347 1348 set_motor(fdcu, fdsu, TURNOFF); 1349 1350 if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ 1351 return(0); 1352 1353 fd->track = FD_NO_TRACK; 1354 fd->fdc = fdc; 1355 fd->fdsu = fdsu; 1356 fd->options = 0; 1357 printf("fdc%d: 1.44MB 3.5in PCMCIA\n", fdcu); 1358 fd->type = FD_1440; 1359 1360#ifdef DEVFS 1361 mynor = fdcu << 6; 1362 fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, 1363 UID_ROOT, GID_OPERATOR, 0640, 1364 "fd%d", fdu); 1365 fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, 1366 UID_ROOT, GID_OPERATOR, 0640, 1367 "rfd%d", fdu); 1368 /* 1369 * XXX this and the lookup in Fdopen() should be 1370 * data driven. 1371 */ 1372 typemynor = mynor | FD_1440; 1373 typesize = fd_types[FD_1440 - 1].size / 2; 1374 /* 1375 * XXX all these conversions give bloated code and 1376 * confusing names. 1377 */ 1378 if (typesize == 1476) 1379 typesize = 1480; 1380 if (typesize == 1722) 1381 typesize = 1720; 1382 fd->bdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor, 1383 DV_BLK, UID_ROOT, GID_OPERATOR, 1384 0640, "fd%d.%d", fdu, typesize); 1385 fd->cdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor, 1386 DV_CHR, UID_ROOT, GID_OPERATOR, 1387 0640,"rfd%d.%d", fdu, typesize); 1388 for (i = 0; i < MAXPARTITIONS; i++) { 1389 fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], 1390 "fd%d%c", fdu, 'a' + i); 1391 fd->cdevs[1 + NUMDENS + i] = devfs_makelink(fd->cdevs[0], 1392 "rfd%d%c", fdu, 'a' + i); 1393 } 1394#endif /* DEVFS */ 1395 return (1); 1396} 1397#endif 1398 1399/****************************************************************************/ 1400/* motor control stuff */ 1401/* remember to not deselect the drive we're working on */ 1402/****************************************************************************/ 1403static void 1404set_motor(struct fdc_data *fdc, int fdsu, int turnon) 1405{ 1406 int fdout = fdc->fdout; 1407 int needspecify = 0; 1408 1409#ifdef PC98 1410 outb(IO_FDPORT, (pc98_trans != 1 ? FDP_FDDEXC : 0)|FDP_PORTEXC); 1411 DELAY(10); 1412 fdout = FDO_DMAE|FDO_MTON; 1413#else 1414 if(turnon) { 1415 fdout &= ~FDO_FDSEL; 1416 fdout |= (FDO_MOEN0 << fdsu) + fdsu; 1417 } else 1418 fdout &= ~(FDO_MOEN0 << fdsu); 1419 1420 if(!turnon 1421 && (fdout & (FDO_MOEN0+FDO_MOEN1+FDO_MOEN2+FDO_MOEN3)) == 0) 1422 /* gonna turn off the last drive, put FDC to bed */ 1423 fdout &= ~ (FDO_FRST|FDO_FDMAEN); 1424 else { 1425 /* make sure controller is selected and specified */ 1426 if((fdout & (FDO_FRST|FDO_FDMAEN)) == 0) 1427 needspecify = 1; 1428 fdout |= (FDO_FRST|FDO_FDMAEN); 1429 } 1430#endif 1431 1432 outb(fdc->baseport+FDOUT, fdout); 1433 fdc->fdout = fdout; 1434 TRACE1("[0x%x->FDOUT]", fdout); 1435 1436 if (needspecify) { 1437 /* 1438 * XXX 1439 * special case: since we have just woken up the FDC 1440 * from its sleep, we silently assume the command will 1441 * be accepted, and do not test for a timeout 1442 */ 1443#ifdef PC98 1444 (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, 1445 NE7_SPEC_1(4, 240), NE7_SPEC_2(2, 0), 1446 0); 1447#else 1448 (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, 1449 NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 1450 0); 1451#endif 1452 if (fdc->flags & FDC_HAS_FIFO) 1453 (void) enable_fifo(fdc); 1454 } 1455} 1456 1457static void 1458fd_turnoff(void *xfd) 1459{ 1460 int s; 1461 fd_p fd = xfd; 1462 1463 TRACE1("[fd%d: turnoff]", fd->fdu); 1464 1465 /* 1466 * Don't turn off the motor yet if the drive is active. 1467 * XXX shouldn't even schedule turnoff until drive is inactive 1468 * and nothing is queued on it. 1469 */ 1470 if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) { 1471 fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); 1472 return; 1473 } 1474 1475 s = splbio(); 1476 fd->flags &= ~FD_MOTOR; 1477 set_motor(fd->fdc, fd->fdsu, TURNOFF); 1478 splx(s); 1479} 1480 1481static void 1482fd_motor_on(void *xfd) 1483{ 1484 int s; 1485 fd_p fd = xfd; 1486 1487 s = splbio(); 1488 fd->flags &= ~FD_MOTOR_WAIT; 1489 if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) 1490 { 1491 fdc_intr(fd->fdc); 1492 } 1493 splx(s); 1494} 1495 1496static void 1497fd_turnon(fd_p fd) 1498{ 1499 if(!(fd->flags & FD_MOTOR)) 1500 { 1501 fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT); 1502 set_motor(fd->fdc, fd->fdsu, TURNON); 1503 timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */ 1504 } 1505} 1506 1507static void 1508fdc_reset(fdc_p fdc) 1509{ 1510 /* Try a reset, keep motor on */ 1511#ifdef PC98 1512 set_density(fdc); 1513 if (pc98_machine_type & M_EPSON_PC98) 1514 outb(fdc->baseport + FDOUT, 0xe8); 1515 else 1516 outb(fdc->baseport + FDOUT, 0xd8); 1517 DELAY(200); 1518 outb(fdc->baseport + FDOUT, 0x18); 1519 DELAY(10); 1520#else 1521 outb(fdc->baseport + FDOUT, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); 1522 TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); 1523 DELAY(100); 1524 /* enable FDC, but defer interrupts a moment */ 1525 outb(fdc->baseport + FDOUT, fdc->fdout & ~FDO_FDMAEN); 1526 TRACE1("[0x%x->FDOUT]", fdc->fdout & ~FDO_FDMAEN); 1527 DELAY(100); 1528 outb(fdc->baseport + FDOUT, fdc->fdout); 1529 TRACE1("[0x%x->FDOUT]", fdc->fdout); 1530#endif 1531 1532 /* XXX after a reset, silently believe the FDC will accept commands */ 1533#ifdef PC98 1534 (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, 1535 NE7_SPEC_1(4, 240), NE7_SPEC_2(2, 0), 1536 0); 1537#else 1538 (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, 1539 NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 1540 0); 1541#endif 1542 if (fdc->flags & FDC_HAS_FIFO) 1543 (void) enable_fifo(fdc); 1544} 1545 1546/****************************************************************************/ 1547/* fdc in/out */ 1548/****************************************************************************/ 1549int 1550in_fdc(struct fdc_data *fdc) 1551{ 1552 int baseport = fdc->baseport; 1553 int i, j = 100000; 1554 while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) 1555 != (NE7_DIO|NE7_RQM) && j-- > 0) 1556 if (i == NE7_RQM) 1557 return fdc_err(fdc, "ready for output in input\n"); 1558 if (j <= 0) 1559 return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); 1560#ifdef FDC_DEBUG 1561 i = inb(baseport+FDDATA); 1562 TRACE1("[FDDATA->0x%x]", (unsigned char)i); 1563 return(i); 1564#else /* !FDC_DEBUG */ 1565 return inb(baseport+FDDATA); 1566#endif /* FDC_DEBUG */ 1567} 1568 1569/* 1570 * fd_in: Like in_fdc, but allows you to see if it worked. 1571 */ 1572static int 1573fd_in(struct fdc_data *fdc, int *ptr) 1574{ 1575 int baseport = fdc->baseport; 1576 int i, j = 100000; 1577 while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) 1578 != (NE7_DIO|NE7_RQM) && j-- > 0) 1579 if (i == NE7_RQM) 1580 return fdc_err(fdc, "ready for output in input\n"); 1581 if (j <= 0) 1582 return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); 1583#ifdef FDC_DEBUG 1584 i = inb(baseport+FDDATA); 1585 TRACE1("[FDDATA->0x%x]", (unsigned char)i); 1586 *ptr = i; 1587 return 0; 1588#else /* !FDC_DEBUG */ 1589 i = inb(baseport+FDDATA); 1590 if (ptr) 1591 *ptr = i; 1592 return 0; 1593#endif /* FDC_DEBUG */ 1594} 1595 1596int 1597out_fdc(struct fdc_data *fdc, int x) 1598{ 1599 int baseport = fdc->baseport; 1600 int i; 1601 1602 /* Check that the direction bit is set */ 1603 i = 100000; 1604 while ((inb(baseport+FDSTS) & NE7_DIO) && i-- > 0); 1605 if (i <= 0) return fdc_err(fdc, "direction bit not set\n"); 1606 1607 /* Check that the floppy controller is ready for a command */ 1608 i = 100000; 1609 while ((inb(baseport+FDSTS) & NE7_RQM) == 0 && i-- > 0); 1610 if (i <= 0) 1611 return fdc_err(fdc, bootverbose? "output ready timeout\n": 0); 1612 1613 /* Send the command and return */ 1614 outb(baseport+FDDATA, x); 1615 TRACE1("[0x%x->FDDATA]", x); 1616 return (0); 1617} 1618 1619/****************************************************************************/ 1620/* fdopen/fdclose */ 1621/****************************************************************************/ 1622int 1623Fdopen(dev_t dev, int flags, int mode, struct proc *p) 1624{ 1625 fdu_t fdu = FDUNIT(minor(dev)); 1626 int type = FDTYPE(minor(dev)); 1627 fd_p fd; 1628 fdc_p fdc; 1629 1630 /* check bounds */ 1631 if ((fd = devclass_get_softc(fd_devclass, fdu)) == 0) 1632 return (ENXIO); 1633 fdc = fd->fdc; 1634 if ((fdc == NULL) || (fd->type == NO_TYPE)) 1635 return (ENXIO); 1636 if (type > NUMDENS) 1637 return (ENXIO); 1638#ifdef PC98 1639 if (pc98_fd_check_ready(fdu) == -1) 1640 return(EIO); 1641#endif 1642 if (type == 0) 1643 type = fd->type; 1644#ifndef PC98 1645 else { 1646 /* 1647 * For each type of basic drive, make sure we are trying 1648 * to open a type it can do, 1649 */ 1650 if (type != fd->type) { 1651 switch (fd->type) { 1652 case FD_360: 1653 return (ENXIO); 1654 case FD_720: 1655 if ( type != FD_820 1656 && type != FD_800 1657 ) 1658 return (ENXIO); 1659 break; 1660 case FD_1200: 1661 switch (type) { 1662 case FD_1480: 1663 type = FD_1480in5_25; 1664 break; 1665 case FD_1440: 1666 type = FD_1440in5_25; 1667 break; 1668 case FD_820: 1669 type = FD_820in5_25; 1670 break; 1671 case FD_800: 1672 type = FD_800in5_25; 1673 break; 1674 case FD_720: 1675 type = FD_720in5_25; 1676 break; 1677 case FD_360: 1678 type = FD_360in5_25; 1679 break; 1680 default: 1681 return(ENXIO); 1682 } 1683 break; 1684 case FD_1440: 1685 if ( type != FD_1720 1686 && type != FD_1480 1687 && type != FD_1200 1688 && type != FD_820 1689 && type != FD_800 1690 && type != FD_720 1691 ) 1692 return(ENXIO); 1693 break; 1694 } 1695 } 1696 } 1697#endif 1698 fd->ft = fd_types + type - 1; 1699 fd->flags |= FD_OPEN; 1700 device_busy(fd->dev); 1701 device_busy(fd->fdc->fdc_dev); 1702 return 0; 1703} 1704 1705int 1706fdclose(dev_t dev, int flags, int mode, struct proc *p) 1707{ 1708 fdu_t fdu = FDUNIT(minor(dev)); 1709 struct fd_data *fd; 1710 1711 fd = devclass_get_softc(fd_devclass, fdu); 1712 fd->flags &= ~FD_OPEN; 1713 fd->options &= ~FDOPT_NORETRY; 1714 1715 return (0); 1716} 1717 1718/****************************************************************************/ 1719/* fdstrategy */ 1720/****************************************************************************/ 1721void 1722fdstrategy(struct buf *bp) 1723{ 1724 unsigned nblocks, blknum, cando; 1725 int s; 1726 fdu_t fdu; 1727 fdc_p fdc; 1728 fd_p fd; 1729 size_t fdblk; 1730 1731 fdu = FDUNIT(minor(bp->b_dev)); 1732 fd = devclass_get_softc(fd_devclass, fdu); 1733 if (fd == 0) 1734 panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)", 1735 (u_long)major(bp->b_dev), (u_long)minor(bp->b_dev)); 1736 fdc = fd->fdc; 1737#ifdef FDC_YE 1738 if (fd->type == NO_TYPE) { 1739 bp->b_error = ENXIO; 1740 bp->b_flags |= B_ERROR; 1741 /* 1742 * I _refuse_ to use a goto 1743 */ 1744 biodone(bp); 1745 return; 1746 }; 1747#endif 1748 1749 fdblk = 128 << (fd->ft->secsize); 1750 if (!(bp->b_flags & B_FORMAT)) { 1751 if (bp->b_blkno < 0) { 1752 printf( 1753 "fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n", 1754 fdu, (u_long)bp->b_blkno, bp->b_bcount); 1755 bp->b_error = EINVAL; 1756 bp->b_flags |= B_ERROR; 1757 goto bad; 1758 } 1759 if ((bp->b_bcount % fdblk) != 0) { 1760 bp->b_error = EINVAL; 1761 bp->b_flags |= B_ERROR; 1762 goto bad; 1763 } 1764 } 1765 1766 /* 1767 * Set up block calculations. 1768 */ 1769 if (bp->b_blkno > 20000000) { 1770 /* 1771 * Reject unreasonably high block number, prevent the 1772 * multiplication below from overflowing. 1773 */ 1774 bp->b_error = EINVAL; 1775 bp->b_flags |= B_ERROR; 1776 goto bad; 1777 } 1778 blknum = (unsigned) bp->b_blkno * DEV_BSIZE/fdblk; 1779 nblocks = fd->ft->size; 1780 bp->b_resid = 0; 1781 if (blknum + (bp->b_bcount / fdblk) > nblocks) { 1782 if (blknum <= nblocks) { 1783 cando = (nblocks - blknum) * fdblk; 1784 bp->b_resid = bp->b_bcount - cando; 1785 if (cando == 0) 1786 goto bad; /* not actually bad but EOF */ 1787 } else { 1788 bp->b_error = EINVAL; 1789 bp->b_flags |= B_ERROR; 1790 goto bad; 1791 } 1792 } 1793 bp->b_pblkno = bp->b_blkno; 1794 s = splbio(); 1795 bufqdisksort(&fdc->head, bp); 1796 untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */ 1797 1798 /* Tell devstat we are starting on the transaction */ 1799 devstat_start_transaction(&fd->device_stats); 1800 1801 fdstart(fdc); 1802 splx(s); 1803 return; 1804 1805bad: 1806 biodone(bp); 1807} 1808 1809/***************************************************************\ 1810* fdstart * 1811* We have just queued something.. if the controller is not busy * 1812* then simulate the case where it has just finished a command * 1813* So that it (the interrupt routine) looks on the queue for more* 1814* work to do and picks up what we just added. * 1815* If the controller is already busy, we need do nothing, as it * 1816* will pick up our work when the present work completes * 1817\***************************************************************/ 1818static void 1819fdstart(struct fdc_data *fdc) 1820{ 1821 int s; 1822 1823 s = splbio(); 1824 if(fdc->state == DEVIDLE) 1825 { 1826 fdc_intr(fdc); 1827 } 1828 splx(s); 1829} 1830 1831static void 1832fd_iotimeout(void *xfdc) 1833{ 1834 fdc_p fdc; 1835 int s; 1836 1837 fdc = xfdc; 1838 TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); 1839 1840 /* 1841 * Due to IBM's brain-dead design, the FDC has a faked ready 1842 * signal, hardwired to ready == true. Thus, any command 1843 * issued if there's no diskette in the drive will _never_ 1844 * complete, and must be aborted by resetting the FDC. 1845 * Many thanks, Big Blue! 1846 * The FDC must not be reset directly, since that would 1847 * interfere with the state machine. Instead, pretend that 1848 * the command completed but was invalid. The state machine 1849 * will reset the FDC and retry once. 1850 */ 1851 s = splbio(); 1852 fdc->status[0] = NE7_ST0_IC_IV; 1853 fdc->flags &= ~FDC_STAT_VALID; 1854 fdc->state = IOTIMEDOUT; 1855 fdc_intr(fdc); 1856 splx(s); 1857} 1858 1859/* just ensure it has the right spl */ 1860static void 1861fd_pseudointr(void *xfdc) 1862{ 1863 int s; 1864 1865 s = splbio(); 1866 fdc_intr(xfdc); 1867 splx(s); 1868} 1869 1870/***********************************************************************\ 1871* fdintr * 1872* keep calling the state machine until it returns a 0 * 1873* ALWAYS called at SPLBIO * 1874\***********************************************************************/ 1875static void 1876fdc_intr(void *xfdc) 1877{ 1878 fdc_p fdc = xfdc; 1879 while(fdstate(fdc)) 1880 ; 1881} 1882 1883#ifdef FDC_YE 1884/* 1885 * magic pseudo-DMA initialization for YE FDC. Sets count and 1886 * direction 1887 */ 1888#define SET_BCDR(wr,cnt,port) outb(port,(((cnt)-1) & 0xff)); \ 1889 outb(port+1,((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f))) 1890 1891/* 1892 * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy 1893 */ 1894static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count) 1895{ 1896 u_char *cptr = (u_char *)addr; 1897 fdc_p fdc = &fdc_data[fdcu]; 1898 int io = fdc->baseport; 1899 1900 if (flags & B_READ) { 1901 if (fdc->state != PIOREAD) { 1902 fdc->state = PIOREAD; 1903 return(0); 1904 }; 1905 SET_BCDR(0,count,io); 1906 insb(io+FDC_YE_DATAPORT,cptr,count); 1907 } else { 1908 outsb(io+FDC_YE_DATAPORT,cptr,count); 1909 SET_BCDR(0,count,io); 1910 }; 1911 return(1); 1912} 1913#endif /* FDC_YE */ 1914 1915/***********************************************************************\ 1916* The controller state machine. * 1917* if it returns a non zero value, it should be called again immediatly * 1918\***********************************************************************/ 1919static int 1920fdstate(fdc_p fdc) 1921{ 1922 int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; 1923 unsigned blknum = 0, b_cylinder = 0; 1924 fdu_t fdu = fdc->fdu; 1925 fd_p fd; 1926 register struct buf *bp; 1927 struct fd_formb *finfo = NULL; 1928 size_t fdblk; 1929 1930 bp = fdc->bp; 1931 if (bp == NULL) { 1932 bp = bufq_first(&fdc->head); 1933 if (bp != NULL) { 1934 bufq_remove(&fdc->head, bp); 1935 fdc->bp = bp; 1936 } 1937 } 1938 if (bp == NULL) { 1939 /***********************************************\ 1940 * nothing left for this controller to do * 1941 * Force into the IDLE state, * 1942 \***********************************************/ 1943 fdc->state = DEVIDLE; 1944 if (fdc->fd) { 1945 device_print_prettyname(fdc->fdc_dev); 1946 printf("unexpected valid fd pointer\n"); 1947 fdc->fd = (fd_p) 0; 1948 fdc->fdu = -1; 1949 } 1950 TRACE1("[fdc%d IDLE]", fdc->fdcu); 1951 return (0); 1952 } 1953 fdu = FDUNIT(minor(bp->b_dev)); 1954 fd = devclass_get_softc(fd_devclass, fdu); 1955 fdblk = 128 << fd->ft->secsize; 1956 if (fdc->fd && (fd != fdc->fd)) { 1957 device_print_prettyname(fd->dev); 1958 printf("confused fd pointers\n"); 1959 } 1960 read = bp->b_flags & B_READ; 1961 format = bp->b_flags & B_FORMAT; 1962 if (format) { 1963 finfo = (struct fd_formb *)bp->b_data; 1964 fd->skip = (char *)&(finfo->fd_formb_cylno(0)) 1965 - (char *)finfo; 1966 } 1967 if (fdc->state == DOSEEK || fdc->state == SEEKCOMPLETE) { 1968 blknum = (unsigned) bp->b_pblkno * DEV_BSIZE/fdblk + 1969 fd->skip/fdblk; 1970 b_cylinder = blknum / (fd->ft->sectrac * fd->ft->heads); 1971 } 1972 TRACE1("fd%d", fdu); 1973 TRACE1("[%s]", fdstates[fdc->state]); 1974 TRACE1("(0x%x)", fd->flags); 1975 untimeout(fd_turnoff, fd, fd->toffhandle); 1976 fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); 1977 switch (fdc->state) 1978 { 1979 case DEVIDLE: 1980 case FINDWORK: /* we have found new work */ 1981 fdc->retry = 0; 1982 fd->skip = 0; 1983 fdc->fd = fd; 1984 fdc->fdu = fdu; 1985#ifdef PC98 1986 pc98_trans = fd->ft->trans; 1987 if (pc98_trans_prev != pc98_trans) { 1988 int i; 1989 set_density(fdc); 1990 for (i = 0; i < 10; i++) { 1991 outb(0x5f, 0); 1992 outb(0x5f, 0); 1993 } 1994 pc98_trans_prev = pc98_trans; 1995 } 1996 if (pc98_trans != fd->pc98_trans) { 1997 if (pc98_trans != 1 && 1998 (PC98_SYSTEM_PARAMETER(0x5ae) >> fdu) & 0x01) { 1999 outb(0x4be, (fdu << 5) | 0x10 | (pc98_trans >> 1)); 2000 outb(0x5f, 0); 2001 outb(0x5f, 0); 2002 } 2003 fd->pc98_trans = pc98_trans; 2004 } 2005#else 2006 outb(fdc->baseport+FDCTL, fd->ft->trans); 2007#endif 2008 TRACE1("[0x%x->FDCTL]", fd->ft->trans); 2009 /*******************************************************\ 2010 * If the next drive has a motor startup pending, then * 2011 * it will start up in its own good time * 2012 \*******************************************************/ 2013 if(fd->flags & FD_MOTOR_WAIT) { 2014 fdc->state = MOTORWAIT; 2015 return (0); /* come back later */ 2016 } 2017 /*******************************************************\ 2018 * Maybe if it's not starting, it SHOULD be starting * 2019 \*******************************************************/ 2020#ifdef EPSON_NRDISK 2021 if (fdu != nrdu) { 2022 if (!(fd->flags & FD_MOTOR)) 2023 { 2024 fdc->state = MOTORWAIT; 2025 fd_turnon(fdu); 2026 return(0); 2027 } 2028 else /* at least make sure we are selected */ 2029 { 2030 set_motor(fdcu, fd->fdsu, TURNON); 2031 } 2032 } 2033#else /* !EPSON_NRDISK */ 2034 if (!(fd->flags & FD_MOTOR)) 2035 { 2036 fdc->state = MOTORWAIT; 2037 fd_turnon(fd); 2038 return (0); 2039 } 2040 else /* at least make sure we are selected */ 2041 { 2042 set_motor(fdc, fd->fdsu, TURNON); 2043 } 2044#endif 2045 if (fdc->flags & FDC_NEEDS_RESET) { 2046 fdc->state = RESETCTLR; 2047 fdc->flags &= ~FDC_NEEDS_RESET; 2048 } else 2049 fdc->state = DOSEEK; 2050 break; 2051 case DOSEEK: 2052 if (b_cylinder == (unsigned)fd->track) 2053 { 2054 fdc->state = SEEKCOMPLETE; 2055 break; 2056 } 2057#ifdef PC98 2058 pc98_fd_check_ready(fdu); 2059#endif 2060 if (fd_cmd(fdc, 3, NE7CMD_SEEK, 2061 fd->fdsu, b_cylinder * fd->ft->steptrac, 2062 0)) 2063 { 2064 /* 2065 * seek command not accepted, looks like 2066 * the FDC went off to the Saints... 2067 */ 2068 fdc->retry = 6; /* try a reset */ 2069 return(retrier(fdc)); 2070 } 2071 fd->track = FD_NO_TRACK; 2072 fdc->state = SEEKWAIT; 2073 return(0); /* will return later */ 2074 case SEEKWAIT: 2075 /* allow heads to settle */ 2076 timeout(fd_pseudointr, fdc, hz / 16); 2077 fdc->state = SEEKCOMPLETE; 2078 return(0); /* will return later */ 2079 case SEEKCOMPLETE : /* SEEK DONE, START DMA */ 2080 /* Make sure seek really happened*/ 2081 if(fd->track == FD_NO_TRACK) { 2082 int descyl = b_cylinder * fd->ft->steptrac; 2083 do { 2084 /* 2085 * This might be a "ready changed" interrupt, 2086 * which cannot really happen since the 2087 * RDY pin is hardwired to + 5 volts. This 2088 * generally indicates a "bouncing" intr 2089 * line, so do one of the following: 2090 * 2091 * When running on an enhanced FDC that is 2092 * known to not go stuck after responding 2093 * with INVALID, fetch all interrupt states 2094 * until seeing either an INVALID or a 2095 * real interrupt condition. 2096 * 2097 * When running on a dumb old NE765, give 2098 * up immediately. The controller will 2099 * provide up to four dummy RC interrupt 2100 * conditions right after reset (for the 2101 * corresponding four drives), so this is 2102 * our only chance to get notice that it 2103 * was not the FDC that caused the interrupt. 2104 */ 2105 if (fd_sense_int(fdc, &st0, &cyl) 2106 == FD_NOT_VALID) 2107 return 0; 2108 if(fdc->fdct == FDC_NE765 2109 && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC) 2110 return 0; /* hope for a real intr */ 2111 } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); 2112 2113 if (0 == descyl) { 2114 int failed = 0; 2115 /* 2116 * seek to cyl 0 requested; make sure we are 2117 * really there 2118 */ 2119 if (fd_sense_drive_status(fdc, &st3)) 2120 failed = 1; 2121#ifdef EPSON_NRDISK 2122 if (fdu == nrdu) st3 = NE7_ST3_T0; 2123#endif /* EPSON_NRDISK */ 2124 if ((st3 & NE7_ST3_T0) == 0) { 2125 printf( 2126 "fd%d: Seek to cyl 0, but not really there (ST3 = %b)\n", 2127 fdu, st3, NE7_ST3BITS); 2128 failed = 1; 2129 } 2130 2131 if (failed) { 2132 if(fdc->retry < 3) 2133 fdc->retry = 3; 2134 return (retrier(fdc)); 2135 } 2136 } 2137#ifdef EPSON_NRDISK 2138 if (fdu == nrdu) cyl = descyl; 2139#endif 2140 2141 if (cyl != descyl) { 2142 printf( 2143 "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", 2144 fdu, descyl, cyl, st0); 2145 if (fdc->retry < 3) 2146 fdc->retry = 3; 2147 return (retrier(fdc)); 2148 } 2149 } 2150 2151 fd->track = b_cylinder; 2152#ifdef EPSON_NRDISK 2153 if (fdu != nrdu) { 2154#endif /* EPSON_NRDISK */ 2155#ifdef FDC_YE 2156 if (!(fdc->flags & FDC_PCMCIA)) 2157#endif 2158 isa_dmastart(bp->b_flags, bp->b_data+fd->skip, 2159 format ? bp->b_bcount : fdblk, fdc->dmachan); 2160 sectrac = fd->ft->sectrac; 2161 sec = blknum % (sectrac * fd->ft->heads); 2162 head = sec / sectrac; 2163 sec = sec % sectrac + 1; 2164 fd->hddrv = ((head&1)<<2)+fdu; 2165 2166 if(format || !read) 2167 { 2168 /* make sure the drive is writable */ 2169 if(fd_sense_drive_status(fdc, &st3) != 0) 2170 { 2171 /* stuck controller? */ 2172 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2173 format ? bp->b_bcount : fdblk, 2174 fdc->dmachan); 2175 fdc->retry = 6; /* reset the beast */ 2176 return (retrier(fdc)); 2177 } 2178 if(st3 & NE7_ST3_WP) 2179 { 2180 /* 2181 * XXX YES! this is ugly. 2182 * in order to force the current operation 2183 * to fail, we will have to fake an FDC 2184 * error - all error handling is done 2185 * by the retrier() 2186 */ 2187 fdc->status[0] = NE7_ST0_IC_AT; 2188 fdc->status[1] = NE7_ST1_NW; 2189 fdc->status[2] = 0; 2190 fdc->status[3] = fd->track; 2191 fdc->status[4] = head; 2192 fdc->status[5] = sec; 2193 fdc->retry = 8; /* break out immediately */ 2194 fdc->state = IOTIMEDOUT; /* not really... */ 2195 return (1); 2196 } 2197 } 2198 2199 if (format) { 2200#ifdef FDC_YE 2201 if (fdc->flags & FDC_PCMCIA) 2202 (void)fdcpio(fdcu,bp->b_flags, 2203 bp->b_data+fd->skip, 2204 bp->b_bcount); 2205#endif 2206 /* formatting */ 2207 if(fd_cmd(fdc, 6, NE7CMD_FORMAT, head << 2 | fdu, 2208 finfo->fd_formb_secshift, 2209 finfo->fd_formb_nsecs, 2210 finfo->fd_formb_gaplen, 2211 finfo->fd_formb_fillbyte, 0)) { 2212 /* controller fell over */ 2213 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2214 format ? bp->b_bcount : fdblk, 2215 fdc->dmachan); 2216 fdc->retry = 6; 2217 return (retrier(fdc)); 2218 } 2219 } else { 2220#ifdef FDC_YE 2221 if (fdc->flags & FDC_PCMCIA) { 2222 /* 2223 * this seems to be necessary even when 2224 * reading data 2225 */ 2226 SET_BCDR(1,fdblk,fdc->baseport); 2227 2228 /* 2229 * perform the write pseudo-DMA before 2230 * the WRITE command is sent 2231 */ 2232 if (!read) 2233 (void)fdcpio(fdcu,bp->b_flags, 2234 bp->b_data+fd->skip, 2235 fdblk); 2236 } 2237#endif 2238 if (fd_cmd(fdc, 9, 2239 (read ? NE7CMD_READ : NE7CMD_WRITE), 2240 head << 2 | fdu, /* head & unit */ 2241 fd->track, /* track */ 2242 head, 2243 sec, /* sector + 1 */ 2244 fd->ft->secsize, /* sector size */ 2245 sectrac, /* sectors/track */ 2246 fd->ft->gap, /* gap size */ 2247 fd->ft->datalen, /* data length */ 2248 0)) { 2249 /* the beast is sleeping again */ 2250 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2251 format ? bp->b_bcount : fdblk, 2252 fdc->dmachan); 2253 fdc->retry = 6; 2254 return (retrier(fdc)); 2255 } 2256 } 2257#ifdef FDC_YE 2258 if (fdc->flags & FDC_PCMCIA) 2259 /* 2260 * if this is a read, then simply await interrupt 2261 * before performing PIO 2262 */ 2263 if (read && !fdcpio(fdcu,bp->b_flags, 2264 bp->b_data+fd->skip,fdblk)) { 2265 fd->tohandle = timeout(fd_iotimeout, 2266 (caddr_t)fdcu, hz); 2267 return(0); /* will return later */ 2268 }; 2269 2270 /* 2271 * write (or format) operation will fall through and 2272 * await completion interrupt 2273 */ 2274#endif 2275 fdc->state = IOCOMPLETE; 2276 fd->tohandle = timeout(fd_iotimeout, fdc, hz); 2277 return (0); /* will return later */ 2278#ifdef EPSON_NRDISK 2279 } 2280 else { 2281 nrdblkn = (nrd_t)((unsigned long)bp->b_blkno*DEV_BSIZE/fdblk 2282 + fd->skip/fdblk); 2283 nrd_LED_on(); 2284 nrd_addrset(fdblk * nrdblkn); 2285 while (!nrd_check_ready()) DELAY(1); 2286 if (read) epson_insw(P_NRD_DATA, 2287 bp->b_data + fd->skip, 2288 fdblk / sizeof(short)); 2289 else epson_outsw(P_NRD_DATA, 2290 bp->b_data + fd->skip, 2291 (format ? bp->b_bcount : fdblk) 2292 / sizeof(short)); 2293 2294 blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/fdblk 2295 + fd->skip/fdblk; 2296 sectrac = fd->ft->sectrac; 2297 sec = blknum % (sectrac * fd->ft->heads); 2298 head = sec / sectrac; 2299 sec = sec % sectrac + 1; 2300 fd->hddrv = ((head&1)<<2)+fdu; 2301 2302 if (nrdsec++ >= nrd_sec()) 2303 nrdaddr = (nrd_t)(fd->track * 8 + head * 4); 2304 nrdsec = sec; 2305 fdc->state = IOCOMPLETE; 2306 } 2307#endif 2308#ifdef FDC_YE 2309 case PIOREAD: 2310 /* 2311 * actually perform the PIO read. The IOCOMPLETE case 2312 * removes the timeout for us. 2313 */ 2314 (void)fdcpio(fdcu,bp->b_flags,bp->b_data+fd->skip,fdblk); 2315 fdc->state = IOCOMPLETE; 2316 /* FALLTHROUGH */ 2317#endif 2318 case IOCOMPLETE: /* IO DONE, post-analyze */ 2319#ifdef EPSON_NRDISK 2320 if (fdu != nrdu) 2321 untimeout(fd_iotimeout, fdc, fd->tohandle); 2322#else 2323 untimeout(fd_iotimeout, fdc, fd->tohandle); 2324#endif 2325 2326 if (fd_read_status(fdc, fd->fdsu)) { 2327 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2328 format ? bp->b_bcount : fdblk, 2329 fdc->dmachan); 2330 if (fdc->retry < 6) 2331 fdc->retry = 6; /* force a reset */ 2332 return (retrier(fdc)); 2333 } 2334 2335 fdc->state = IOTIMEDOUT; 2336 2337 /* FALLTHROUGH */ 2338 2339 case IOTIMEDOUT: 2340#ifdef EPSON_NRDISK 2341 if (fdu != nrdu) { 2342#endif /* EPSON_NRDISK */ 2343#ifdef FDC_YE 2344 if (!(fdc->flags & FDC_PCMCIA)) 2345#endif 2346 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2347 format ? bp->b_bcount : fdblk, fdc->dmachan); 2348#ifdef EPSON_NRDISK 2349 } 2350 else nrd_LED_off(); 2351#endif /* EPSON_NRDISK */ 2352 if (fdc->status[0] & NE7_ST0_IC) { 2353 if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT 2354 && fdc->status[1] & NE7_ST1_OR) { 2355 /* 2356 * DMA overrun. Someone hogged the bus 2357 * and didn't release it in time for the 2358 * next FDC transfer. 2359 * Just restart it, don't increment retry 2360 * count. (vak) 2361 */ 2362 fdc->state = SEEKCOMPLETE; 2363 return (1); 2364 } 2365 else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_IV 2366 && fdc->retry < 6) 2367 fdc->retry = 6; /* force a reset */ 2368 else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT 2369 && fdc->status[2] & NE7_ST2_WC 2370 && fdc->retry < 3) 2371 fdc->retry = 3; /* force recalibrate */ 2372 return (retrier(fdc)); 2373 } 2374 /* All OK */ 2375 fd->skip += fdblk; 2376 if (!format && fd->skip < bp->b_bcount - bp->b_resid) { 2377 /* set up next transfer */ 2378 fdc->state = DOSEEK; 2379 } else { 2380 /* ALL DONE */ 2381 fd->skip = 0; 2382 fdc->bp = NULL; 2383 /* Tell devstat we have finished with the transaction */ 2384 devstat_end_transaction(&fd->device_stats, 2385 bp->b_bcount - bp->b_resid, 2386 DEVSTAT_TAG_NONE, 2387 (bp->b_flags & B_READ) ? 2388 DEVSTAT_READ : DEVSTAT_WRITE); 2389 biodone(bp); 2390 fdc->fd = (fd_p) 0; 2391 fdc->fdu = -1; 2392 fdc->state = FINDWORK; 2393 } 2394 return (1); 2395 case RESETCTLR: 2396 fdc_reset(fdc); 2397 fdc->retry++; 2398 fdc->state = RESETCOMPLETE; 2399 return (0); 2400 case RESETCOMPLETE: 2401 /* 2402 * Discard all the results from the reset so that they 2403 * can't cause an unexpected interrupt later. 2404 */ 2405 for (i = 0; i < 4; i++) 2406 (void)fd_sense_int(fdc, &st0, &cyl); 2407 fdc->state = STARTRECAL; 2408 /* Fall through. */ 2409 case STARTRECAL: 2410#ifdef PC98 2411 pc98_fd_check_ready(fdu); 2412#endif 2413 if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) { 2414 /* arrgl */ 2415 fdc->retry = 6; 2416 return (retrier(fdc)); 2417 } 2418 fdc->state = RECALWAIT; 2419 return (0); /* will return later */ 2420 case RECALWAIT: 2421 /* allow heads to settle */ 2422 timeout(fd_pseudointr, fdc, hz / 8); 2423 fdc->state = RECALCOMPLETE; 2424 return (0); /* will return later */ 2425 case RECALCOMPLETE: 2426 do { 2427 /* 2428 * See SEEKCOMPLETE for a comment on this: 2429 */ 2430 if (fd_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID) 2431 return 0; 2432 if(fdc->fdct == FDC_NE765 2433 && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC) 2434 return 0; /* hope for a real intr */ 2435 } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); 2436#ifdef EPSON_NRDISK 2437 if (fdu == nrdu) { 2438 st0 = NE7_ST0_IC_NT; 2439 cyl = 0; 2440 } 2441#endif 2442 if ((st0 & NE7_ST0_IC) != NE7_ST0_IC_NT || cyl != 0) 2443 { 2444 if(fdc->retry > 3) 2445 /* 2446 * a recalibrate from beyond cylinder 77 2447 * will "fail" due to the FDC limitations; 2448 * since people used to complain much about 2449 * the failure message, try not logging 2450 * this one if it seems to be the first 2451 * time in a line 2452 */ 2453 printf("fd%d: recal failed ST0 %b cyl %d\n", 2454 fdu, st0, NE7_ST0BITS, cyl); 2455 if(fdc->retry < 3) fdc->retry = 3; 2456 return (retrier(fdc)); 2457 } 2458 fd->track = 0; 2459 /* Seek (probably) necessary */ 2460 fdc->state = DOSEEK; 2461 return (1); /* will return immediatly */ 2462 case MOTORWAIT: 2463 if(fd->flags & FD_MOTOR_WAIT) 2464 { 2465 return (0); /* time's not up yet */ 2466 } 2467 if (fdc->flags & FDC_NEEDS_RESET) { 2468 fdc->state = RESETCTLR; 2469 fdc->flags &= ~FDC_NEEDS_RESET; 2470 } else { 2471 /* 2472 * If all motors were off, then the controller was 2473 * reset, so it has lost track of the current 2474 * cylinder. Recalibrate to handle this case. 2475 * But first, discard the results of the reset. 2476 */ 2477 fdc->state = RESETCOMPLETE; 2478 } 2479 return (1); /* will return immediatly */ 2480 default: 2481 device_print_prettyname(fdc->fdc_dev); 2482 printf("unexpected FD int->"); 2483 if (fd_read_status(fdc, fd->fdsu) == 0) 2484 printf("FDC status :%x %x %x %x %x %x %x ", 2485 fdc->status[0], 2486 fdc->status[1], 2487 fdc->status[2], 2488 fdc->status[3], 2489 fdc->status[4], 2490 fdc->status[5], 2491 fdc->status[6] ); 2492 else 2493 printf("No status available "); 2494 if (fd_sense_int(fdc, &st0, &cyl) != 0) 2495 { 2496 printf("[controller is dead now]\n"); 2497 return (0); 2498 } 2499 printf("ST0 = %x, PCN = %x\n", st0, cyl); 2500 return (0); 2501 } 2502 /*XXX confusing: some branches return immediately, others end up here*/ 2503 return (1); /* Come back immediatly to new state */ 2504} 2505 2506static int 2507retrier(struct fdc_data *fdc) 2508{ 2509 register struct buf *bp; 2510 struct fd_data *fd; 2511 int fdu; 2512 2513 bp = fdc->bp; 2514 2515 /* XXX shouldn't this be cached somewhere? */ 2516 fdu = FDUNIT(minor(bp->b_dev)); 2517 fd = devclass_get_softc(fd_devclass, fdu); 2518 if (fd->options & FDOPT_NORETRY) 2519 goto fail; 2520 2521 switch (fdc->retry) { 2522 case 0: case 1: case 2: 2523 fdc->state = SEEKCOMPLETE; 2524 break; 2525 case 3: case 4: case 5: 2526 fdc->state = STARTRECAL; 2527 break; 2528 case 6: 2529 fdc->state = RESETCTLR; 2530 break; 2531 case 7: 2532 break; 2533 default: 2534 fail: 2535 { 2536 dev_t sav_b_dev = bp->b_dev; 2537 /* Trick diskerr */ 2538 bp->b_dev = makedev(major(bp->b_dev), 2539 (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART); 2540 diskerr(bp, "fd", "hard error", LOG_PRINTF, 2541 fdc->fd->skip / DEV_BSIZE, 2542 (struct disklabel *)NULL); 2543 bp->b_dev = sav_b_dev; 2544 if (fdc->flags & FDC_STAT_VALID) 2545 { 2546 printf( 2547 " (ST0 %b ST1 %b ST2 %b cyl %u hd %u sec %u)\n", 2548 fdc->status[0], NE7_ST0BITS, 2549 fdc->status[1], NE7_ST1BITS, 2550 fdc->status[2], NE7_ST2BITS, 2551 fdc->status[3], fdc->status[4], 2552 fdc->status[5]); 2553 } 2554 else 2555 printf(" (No status)\n"); 2556 } 2557 bp->b_flags |= B_ERROR; 2558 bp->b_error = EIO; 2559 bp->b_resid += bp->b_bcount - fdc->fd->skip; 2560 fdc->bp = NULL; 2561 2562 /* Tell devstat we have finished with the transaction */ 2563 devstat_end_transaction(&fdc->fd->device_stats, 2564 bp->b_bcount - bp->b_resid, 2565 DEVSTAT_TAG_NONE, 2566 (bp->b_flags & B_READ) ? DEVSTAT_READ : 2567 DEVSTAT_WRITE); 2568 fdc->fd->skip = 0; 2569 biodone(bp); 2570 fdc->state = FINDWORK; 2571 fdc->flags |= FDC_NEEDS_RESET; 2572 fdc->fd = (fd_p) 0; 2573 fdc->fdu = -1; 2574 return (1); 2575 } 2576 fdc->retry++; 2577 return (1); 2578} 2579 2580static int 2581fdformat(dev, finfo, p) 2582 dev_t dev; 2583 struct fd_formb *finfo; 2584 struct proc *p; 2585{ 2586 fdu_t fdu; 2587 fd_p fd; 2588 2589 struct buf *bp; 2590 int rv = 0, s; 2591 size_t fdblk; 2592 2593 fdu = FDUNIT(minor(dev)); 2594 fd = devclass_get_softc(fd_devclass, fdu); 2595 fdblk = 128 << fd->ft->secsize; 2596 2597 /* set up a buffer header for fdstrategy() */ 2598 bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 2599 if(bp == 0) 2600 return ENOBUFS; 2601 /* 2602 * keep the process from being swapped 2603 */ 2604 PHOLD(p); 2605 bzero((void *)bp, sizeof(struct buf));
| 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/buf.h> 64#include <sys/bus.h> 65#include <sys/conf.h> 66#include <sys/disklabel.h> 67#include <sys/devicestat.h> 68#include <sys/fcntl.h> 69#include <sys/malloc.h> 70#include <sys/module.h> 71#include <sys/proc.h> 72#include <sys/syslog.h> 73 74#include <sys/bus.h> 75#include <machine/bus.h> 76#include <sys/rman.h> 77 78#include <machine/clock.h> 79#include <machine/ioctl_fd.h> 80#include <machine/resource.h> 81#include <machine/stdarg.h> 82 83#ifdef DEVFS 84#include <sys/devfsext.h> 85#endif /* DEVFS */ 86 87#include <isa/isavar.h> 88#ifdef PC98 89#include <pc98/pc98/pc98.h> 90#include <pc98/pc98/pc98_machdep.h> 91#include <pc98/pc98/epsonio.h> 92#include <i386/isa/isa_dma.h> 93#include <pc98/pc98/fdreg.h> 94#else 95#include <i386/isa/isa.h> 96#include <i386/isa/isa_dma.h> 97#include <i386/isa/fdreg.h> 98#include <isa/rtc.h> 99#endif 100#include <isa/fdc.h> 101 102#ifdef FDC_YE 103#undef FDC_YE 104#warning "fix FDC_YE! - newbus casualty" 105#endif 106 107/* misuse a flag to identify format operation */ 108#define B_FORMAT B_XXX 109 110/* configuration flags */ 111#define FDC_PRETEND_D0 (1 << 0) /* pretend drive 0 to be there */ 112#ifdef FDC_YE 113#define FDC_IS_PCMCIA (1 << 1) /* if successful probe, then it's 114 a PCMCIA device */ 115#endif 116 117/* internally used only, not really from CMOS: */ 118#define RTCFDT_144M_PRETENDED 0x1000 119 120/* error returns for fd_cmd() */ 121#define FD_FAILED -1 122#define FD_NOT_VALID -2 123#define FDC_ERRMAX 100 /* do not log more */ 124 125#ifdef PC98 126#define NUMTYPES 5 127#define NUMDENS NUMTYPES 128#else 129#define NUMTYPES 14 130#define NUMDENS (NUMTYPES - 6) 131#endif 132 133/* These defines (-1) must match index for fd_types */ 134#define F_TAPE_TYPE 0x020 /* bit for fd_types to indicate tape */ 135#define NO_TYPE 0 /* must match NO_TYPE in ft.c */ 136#ifdef PC98 137#define FDT_NONE 0 /* none present */ 138#define FDT_12M 1 /* 1M/640K FDD */ 139#define FDT_144M 2 /* 1.44M/1M/640K FDD */ 140 141#define FD_1200 1 142#define FD_1232 2 143#define FD_720 3 144#define FD_640 4 145#define FD_1440 5 146#else 147#define FD_1720 1 148#define FD_1480 2 149#define FD_1440 3 150#define FD_1200 4 151#define FD_820 5 152#define FD_800 6 153#define FD_720 7 154#define FD_360 8 155 156#define FD_1480in5_25 9 157#define FD_1440in5_25 10 158#define FD_820in5_25 11 159#define FD_800in5_25 12 160#define FD_720in5_25 13 161#define FD_360in5_25 14 162#endif 163 164 165static struct fd_type fd_types[NUMTYPES] = 166{ 167#ifdef PC98 168{ 15,2,0xFF,0x1B,80,2400,1,0,2,0x54,1 }, /* 1.2 meg HD floppy */ 169{ 8,3,0xFF,0x35,77,1232,1,0,2,0x74,1 }, /* 1.2 meg HD floppy 1024/sec */ 170{ 9,2,0xFF,0x20,80,1440,1,1,2,0x50,1 }, /* 720k floppy in 1.2meg drive */ 171{ 8,2,0xFF,0x2A,80,1280,1,1,2,0x50,1 }, /* 640k floppy in 1.2meg drive */ 172{ 18,2,0xFF,0x1B,80,2880,1,2,2,0x54,1 }, /* 1.44 meg HD 3.5in floppy */ 173#else 174{ 21,2,0xFF,0x04,82,3444,1,FDC_500KBPS,2,0x0C,2 }, /* 1.72M in HD 3.5in */ 175{ 18,2,0xFF,0x1B,82,2952,1,FDC_500KBPS,2,0x6C,1 }, /* 1.48M in HD 3.5in */ 176{ 18,2,0xFF,0x1B,80,2880,1,FDC_500KBPS,2,0x6C,1 }, /* 1.44M in HD 3.5in */ 177{ 15,2,0xFF,0x1B,80,2400,1,FDC_500KBPS,2,0x54,1 }, /* 1.2M in HD 5.25/3.5 */ 178{ 10,2,0xFF,0x10,82,1640,1,FDC_250KBPS,2,0x2E,1 }, /* 820K in HD 3.5in */ 179{ 10,2,0xFF,0x10,80,1600,1,FDC_250KBPS,2,0x2E,1 }, /* 800K in HD 3.5in */ 180{ 9,2,0xFF,0x20,80,1440,1,FDC_250KBPS,2,0x50,1 }, /* 720K in HD 3.5in */ 181{ 9,2,0xFF,0x2A,40, 720,1,FDC_250KBPS,2,0x50,1 }, /* 360K in DD 5.25in */ 182 183{ 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,0x02,2 }, /* 1.48M in HD 5.25in */ 184{ 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,0x02,2 }, /* 1.44M in HD 5.25in */ 185{ 10,2,0xFF,0x10,82,1640,1,FDC_300KBPS,2,0x2E,1 }, /* 820K in HD 5.25in */ 186{ 10,2,0xFF,0x10,80,1600,1,FDC_300KBPS,2,0x2E,1 }, /* 800K in HD 5.25in */ 187{ 9,2,0xFF,0x20,80,1440,1,FDC_300KBPS,2,0x50,1 }, /* 720K in HD 5.25in */ 188{ 9,2,0xFF,0x23,40, 720,2,FDC_300KBPS,2,0x50,1 }, /* 360K in HD 5.25in */ 189#endif 190}; 191 192#ifdef PC98 193#define DRVS_PER_CTLR 4 /* 4 floppies */ 194#else 195#define DRVS_PER_CTLR 2 /* 2 floppies */ 196#endif 197 198/***********************************************************************\ 199* Per controller structure. * 200\***********************************************************************/ 201static devclass_t fdc_devclass; 202 203/***********************************************************************\ 204* Per drive structure. * 205* N per controller (DRVS_PER_CTLR) * 206\***********************************************************************/ 207struct fd_data { 208 struct fdc_data *fdc; /* pointer to controller structure */ 209 int fdsu; /* this units number on this controller */ 210 int type; /* Drive type (FD_1440...) */ 211 struct fd_type *ft; /* pointer to the type descriptor */ 212 int flags; 213#define FD_OPEN 0x01 /* it's open */ 214#define FD_ACTIVE 0x02 /* it's active */ 215#define FD_MOTOR 0x04 /* motor should be on */ 216#define FD_MOTOR_WAIT 0x08 /* motor coming up */ 217 int skip; 218 int hddrv; 219#define FD_NO_TRACK -2 220 int track; /* where we think the head is */ 221 int options; /* user configurable options, see ioctl_fd.h */ 222 struct callout_handle toffhandle; 223 struct callout_handle tohandle; 224 struct devstat device_stats; 225#ifdef DEVFS 226 void *bdevs[1 + NUMDENS + MAXPARTITIONS]; 227 void *cdevs[1 + NUMDENS + MAXPARTITIONS]; 228#endif 229#ifdef PC98 230 int pc98_trans; 231#endif 232 device_t dev; 233 fdu_t fdu; 234}; 235static devclass_t fd_devclass; 236 237#ifdef EPSON_NRDISK 238typedef unsigned int nrd_t; 239 240#define P_NRD_ADDRH 0xc24 241#define P_NRD_ADDRM 0xc22 242#define P_NRD_ADDRL 0xc20 243#define P_NRD_CHECK 0xc20 244#define P_NRD_DATA 0xc26 245#define P_NRD_LED 0xc36 246#define B_NRD_CHK 0x80 247#define B_NRD_LED 0x40 248#define A_NRD_INFO 0x2 249#define A_NRD_BASE 0x400 250#define NRD_STATUS 0x0 251#define NRD_ST0_HD 0x04 252 253static fdu_t nrdu=-1; 254static int nrdsec=0; 255static nrd_t nrdblkn=0; 256static nrd_t nrdaddr=0x0; 257 258#define nrd_check_ready() ({ \ 259 (epson_inb(P_NRD_CHECK) & B_NRD_CHK) ? 0 : 1; \ 260 }) 261#define nrd_LED_on() epson_outb(P_NRD_LED, B_NRD_LED) 262#define nrd_LED_off() epson_outb(P_NRD_LED, ~B_NRD_LED) 263#define nrd_trac() ((int)(nrd_info(nrdaddr) & 0xff)) 264#define nrd_head() ((int)((nrd_info(nrdaddr) >> 8) & 0xff)) 265#define nrd_sec() ((int)(nrd_info(nrdaddr + 2) & 0xff)) 266#define nrd_secsize() ((int)((nrd_info(A_NRD_INFO) >> 8) & 0xff)) 267#define nrd_addrset(p) nrd_addr((nrd_t)((nrd_t)p+A_NRD_BASE)) 268 269static inline void 270nrd_addr(addr) 271 nrd_t addr; 272{ 273 epson_outb(P_NRD_ADDRH, (u_char)((addr >> 16) & 0x1f)); 274 epson_outb(P_NRD_ADDRM, (u_char)((addr >> 8) & 0xff)); 275 epson_outb(P_NRD_ADDRL, (u_char)(addr & 0xff)); 276} 277 278static inline u_short 279nrd_info(addr) 280 nrd_t addr; 281{ 282 u_short tmp; 283 284 nrd_addr(addr); 285 outb(0x43f, 0x42); 286 tmp = (short)inw(P_NRD_DATA); 287 outb(0x43f, 0x40); 288 return ((u_short)tmp); 289} 290#endif /* EPSON_NRDISK */ 291 292/***********************************************************************\ 293* Throughout this file the following conventions will be used: * 294* fd is a pointer to the fd_data struct for the drive in question * 295* fdc is a pointer to the fdc_data struct for the controller * 296* fdu is the floppy drive unit number * 297* fdcu is the floppy controller unit number * 298* fdsu is the floppy drive unit number on that controller. (sub-unit) * 299\***********************************************************************/ 300 301#ifdef FDC_YE 302#include "card.h" 303static int yeattach(struct isa_device *); 304#endif 305 306/* needed for ft driver, thus exported */ 307int in_fdc(struct fdc_data *); 308int out_fdc(struct fdc_data *, int); 309 310/* internal functions */ 311static void fdc_add_device(device_t, const char *, int); 312static void fdc_intr(void *); 313static void set_motor(struct fdc_data *, int, int); 314# define TURNON 1 315# define TURNOFF 0 316static timeout_t fd_turnoff; 317static timeout_t fd_motor_on; 318static void fd_turnon(struct fd_data *); 319static void fdc_reset(fdc_p); 320static int fd_in(struct fdc_data *, int *); 321static void fdstart(struct fdc_data *); 322static timeout_t fd_iotimeout; 323static timeout_t fd_pseudointr; 324static int fdstate(struct fdc_data *); 325static int retrier(struct fdc_data *); 326static int fdformat(dev_t, struct fd_formb *, struct proc *); 327 328static int enable_fifo(fdc_p fdc); 329 330static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */ 331 332 333#define DEVIDLE 0 334#define FINDWORK 1 335#define DOSEEK 2 336#define SEEKCOMPLETE 3 337#define IOCOMPLETE 4 338#define RECALCOMPLETE 5 339#define STARTRECAL 6 340#define RESETCTLR 7 341#define SEEKWAIT 8 342#define RECALWAIT 9 343#define MOTORWAIT 10 344#define IOTIMEDOUT 11 345#define RESETCOMPLETE 12 346#ifdef FDC_YE 347#define PIOREAD 13 348#endif 349 350#ifdef FDC_DEBUG 351static char const * const fdstates[] = 352{ 353"DEVIDLE", 354"FINDWORK", 355"DOSEEK", 356"SEEKCOMPLETE", 357"IOCOMPLETE", 358"RECALCOMPLETE", 359"STARTRECAL", 360"RESETCTLR", 361"SEEKWAIT", 362"RECALWAIT", 363"MOTORWAIT", 364"IOTIMEDOUT", 365"RESETCOMPLETE", 366#ifdef FDC_YE 367"PIOREAD", 368#endif 369}; 370 371/* CAUTION: fd_debug causes huge amounts of logging output */ 372static int volatile fd_debug = 0; 373#define TRACE0(arg) if(fd_debug) printf(arg) 374#define TRACE1(arg1, arg2) if(fd_debug) printf(arg1, arg2) 375#else /* FDC_DEBUG */ 376#define TRACE0(arg) 377#define TRACE1(arg1, arg2) 378#endif /* FDC_DEBUG */ 379 380#ifdef FDC_YE 381#if NCARD > 0 382#include <sys/select.h> 383#include <sys/module.h> 384#include <pccard/cardinfo.h> 385#include <pccard/driver.h> 386#include <pccard/slot.h> 387 388/* 389 * PC-Card (PCMCIA) specific code. 390 */ 391static int yeinit(struct pccard_devinfo *); /* init device */ 392static void yeunload(struct pccard_devinfo *); /* Disable driver */ 393static int yeintr(struct pccard_devinfo *); /* Interrupt handler */ 394 395PCCARD_MODULE(fdc, yeinit, yeunload, yeintr, 0, bio_imask); 396 397/* 398 * this is the secret PIO data port (offset from base) 399 */ 400#define FDC_YE_DATAPORT 6 401 402/* 403 * Initialize the device - called from Slot manager. 404 */ 405static int yeinit(struct pccard_devinfo *devi) 406{ 407 fdc_p fdc = &fdc_data[devi->isahd.id_unit]; 408 409 /* validate unit number. */ 410 if (devi->isahd.id_unit >= NFDC) 411 return(ENODEV); 412 fdc->baseport = devi->isahd.id_iobase; 413 /* 414 * reset controller 415 */ 416 outb(fdc->baseport+FDOUT, 0); 417 DELAY(100); 418 outb(fdc->baseport+FDOUT, FDO_FRST); 419 420 /* 421 * wire into system 422 */ 423 if (yeattach(&devi->isahd) == 0) 424 return(ENXIO); 425 426 return(0); 427} 428 429/* 430 * yeunload - unload the driver and clear the table. 431 * XXX TODO: 432 * This is usually called when the card is ejected, but 433 * can be caused by a modunload of a controller driver. 434 * The idea is to reset the driver's view of the device 435 * and ensure that any driver entry points such as 436 * read and write do not hang. 437 */ 438static void yeunload(struct pccard_devinfo *devi) 439{ 440 if (fd_data[devi->isahd.id_unit].type == NO_TYPE) 441 return; 442 443 /* 444 * this prevents Fdopen() and fdstrategy() from attempting 445 * to access unloaded controller 446 */ 447 fd_data[devi->isahd.id_unit].type = NO_TYPE; 448 449 printf("fdc%d: unload\n", devi->isahd.id_unit); 450} 451 452/* 453 * yeintr - Shared interrupt called from 454 * front end of PC-Card handler. 455 */ 456static int yeintr(struct pccard_devinfo *devi) 457{ 458 fdintr((fdcu_t)devi->isahd.id_unit); 459 return(1); 460} 461#endif /* NCARD > 0 */ 462#endif /* FDC_YE */ 463 464static d_open_t Fdopen; /* NOTE, not fdopen */ 465static d_close_t fdclose; 466static d_ioctl_t fdioctl; 467static d_strategy_t fdstrategy; 468 469#define CDEV_MAJOR 9 470#define BDEV_MAJOR 2 471 472static struct cdevsw fd_cdevsw = { 473 /* open */ Fdopen, 474 /* close */ fdclose, 475 /* read */ physread, 476 /* write */ physwrite, 477 /* ioctl */ fdioctl, 478 /* stop */ nostop, 479 /* reset */ noreset, 480 /* devtotty */ nodevtotty, 481 /* poll */ nopoll, 482 /* mmap */ nommap, 483 /* strategy */ fdstrategy, 484 /* name */ "fd", 485 /* parms */ noparms, 486 /* maj */ CDEV_MAJOR, 487 /* dump */ nodump, 488 /* psize */ nopsize, 489 /* flags */ D_DISK, 490 /* maxio */ 0, 491 /* bmaj */ BDEV_MAJOR 492}; 493 494static int 495fdc_err(struct fdc_data *fdc, const char *s) 496{ 497 fdc->fdc_errs++; 498 if (s) { 499 if (fdc->fdc_errs < FDC_ERRMAX) { 500 device_print_prettyname(fdc->fdc_dev); 501 printf("%s", s); 502 } else if (fdc->fdc_errs == FDC_ERRMAX) { 503 device_print_prettyname(fdc->fdc_dev); 504 printf("too many errors, not logging any more\n"); 505 } 506 } 507 508 return FD_FAILED; 509} 510 511/* 512 * fd_cmd: Send a command to the chip. Takes a varargs with this structure: 513 * Unit number, 514 * # of output bytes, output bytes as ints ..., 515 * # of input bytes, input bytes as ints ... 516 */ 517static int 518fd_cmd(struct fdc_data *fdc, int n_out, ...) 519{ 520 u_char cmd; 521 int n_in; 522 int n; 523 va_list ap; 524 525 va_start(ap, n_out); 526 cmd = (u_char)(va_arg(ap, int)); 527 va_end(ap); 528 va_start(ap, n_out); 529 for (n = 0; n < n_out; n++) 530 { 531 if (out_fdc(fdc, va_arg(ap, int)) < 0) 532 { 533 char msg[50]; 534 snprintf(msg, sizeof(msg), 535 "cmd %x failed at out byte %d of %d\n", 536 cmd, n + 1, n_out); 537 return fdc_err(fdc, msg); 538 } 539 } 540 n_in = va_arg(ap, int); 541 for (n = 0; n < n_in; n++) 542 { 543 int *ptr = va_arg(ap, int *); 544 if (fd_in(fdc, ptr) < 0) 545 { 546 char msg[50]; 547 snprintf(msg, sizeof(msg), 548 "cmd %02x failed at in byte %d of %d\n", 549 cmd, n + 1, n_in); 550 return fdc_err(fdc, msg); 551 } 552 } 553 554 return 0; 555} 556 557static int 558enable_fifo(fdc_p fdc) 559{ 560 int i, j; 561 562 if ((fdc->flags & FDC_HAS_FIFO) == 0) { 563 564 /* 565 * XXX: 566 * Cannot use fd_cmd the normal way here, since 567 * this might be an invalid command. Thus we send the 568 * first byte, and check for an early turn of data directon. 569 */ 570 571 if (out_fdc(fdc, I8207X_CONFIGURE) < 0) 572 return fdc_err(fdc, "Enable FIFO failed\n"); 573 574 /* If command is invalid, return */ 575 j = 100000; 576 while ((i = inb(fdc->baseport + FDSTS) & (NE7_DIO | NE7_RQM)) 577 != NE7_RQM && j-- > 0) 578 if (i == (NE7_DIO | NE7_RQM)) { 579 fdc_reset(fdc); 580 return FD_FAILED; 581 } 582 if (j<0 || 583 fd_cmd(fdc, 3, 584 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) { 585 fdc_reset(fdc); 586 return fdc_err(fdc, "Enable FIFO failed\n"); 587 } 588 fdc->flags |= FDC_HAS_FIFO; 589 return 0; 590 } 591 if (fd_cmd(fdc, 4, 592 I8207X_CONFIGURE, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) 593 return fdc_err(fdc, "Re-enable FIFO failed\n"); 594 return 0; 595} 596 597static int 598fd_sense_drive_status(fdc_p fdc, int *st3p) 599{ 600 int st3; 601 602 if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) 603 { 604 return fdc_err(fdc, "Sense Drive Status failed\n"); 605 } 606 if (st3p) 607 *st3p = st3; 608 609 return 0; 610} 611 612static int 613fd_sense_int(fdc_p fdc, int *st0p, int *cylp) 614{ 615 int cyl, st0, ret; 616 617#ifdef EPSON_NRDISK 618 if (fdc->fdu == nrdu) { 619 if (fdc->fd->track >= 0) nrdaddr = (fdc->fd->track + 1) * 8; 620 else nrdaddr = 0x0; 621 *st0p = nrd_head() ? NRD_ST0_HD : NRD_STATUS; 622 *cylp = nrd_trac(); 623 } 624 else { 625#endif /* EPSON_NRDISK */ 626 ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0); 627 if (ret) { 628 (void)fdc_err(fdc, 629 "sense intr err reading stat reg 0\n"); 630 return ret; 631 } 632 633 if (st0p) 634 *st0p = st0; 635 636 if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) { 637 /* 638 * There doesn't seem to have been an interrupt. 639 */ 640 return FD_NOT_VALID; 641 } 642 643 if (fd_in(fdc, &cyl) < 0) { 644 return fdc_err(fdc, "can't get cyl num\n"); 645 } 646 647 if (cylp) 648 *cylp = cyl; 649 650#ifdef EPSON_NRDISK 651 } 652#endif /* EPSON_NRDISK */ 653 return 0; 654} 655 656 657static int 658fd_read_status(fdc_p fdc, int fdsu) 659{ 660 int i, ret; 661 662 for (i = 0; i < 7; i++) { 663 /* 664 * XXX types are poorly chosen. Only bytes can by read 665 * from the hardware, but fdc->status[] wants u_ints and 666 * fd_in() gives ints. 667 */ 668 int status; 669 670#ifdef EPSON_NRDISK 671 if (fdc->fdu == nrdu) { 672 switch (i) { 673 case 0: fdc->status[i] = nrd_head() 674 ? NRD_ST0_HD : NRD_STATUS; break; 675 case 1: fdc->status[i] = NRD_STATUS; break; 676 case 2: fdc->status[i] = NRD_STATUS; break; 677 case 3: fdc->status[i] = nrd_trac(); break; 678 case 4: fdc->status[i] = nrd_head(); break; 679 case 5: fdc->status[i] = nrdsec; break; 680 case 6: fdc->status[i] = nrd_secsize(); break; 681 } 682 ret = 0; 683 } 684 else { 685#endif /* EPSON_NRDISK */ 686 ret = fd_in(fdc, &status); 687 fdc->status[i] = status; 688 if (ret != 0) 689 break; 690#ifdef EPSON_NRDISK 691 } 692#endif /* EPSON_NRDISK */ 693 } 694 695 if (ret == 0) 696 fdc->flags |= FDC_STAT_VALID; 697 else 698 fdc->flags &= ~FDC_STAT_VALID; 699 700 return ret; 701} 702 703/****************************************************************************/ 704/* autoconfiguration stuff */ 705/****************************************************************************/ 706#ifdef PC98 707static int pc98_trans = 0; /* 0 : HD , 1 : DD , 2 : 1.44 */ 708static int pc98_trans_prev = 0; 709 710static void set_density(fdc_p fdc) 711{ 712 /* always motor on */ 713 outb(IO_FDPORT, (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC); 714 DELAY(100); 715 outb(fdc->baseport + FDOUT, FDO_RST | FDO_DMAE); 716 /* in the case of note W, always inhibit 100ms timer */ 717} 718 719static int pc98_fd_check_ready(fdu_t fdu) 720{ 721 fd_p fd = devclass_get_softc(fd_devclass, fdu); 722 struct fdc_data *fdc = fd->fdc; 723 int retry = 0; 724 725#ifdef EPSON_NRDISK 726 if (fdu == nrdu) { 727 if (nrd_check_ready()) return 0; 728 else return -1; 729 } 730#endif 731 while (retry++ < 30000) { 732 set_motor(fdc, fd->fdsu, TURNON); 733 out_fdc(fdc, NE7CMD_SENSED); /* Sense Drive Status */ 734 DELAY(100); 735 out_fdc(fdc, fdu); /* Drive number */ 736 DELAY(100); 737 if ((in_fdc(fdc) & NE7_ST3_RD)){ 738 outb(fdc->baseport + FDOUT, 739 FDO_DMAE | FDO_MTON); 740 DELAY(10); 741 return 0; 742 } 743 } 744 return -1; 745} 746#endif 747 748static int 749fdc_probe(device_t dev) 750{ 751 int error, i, ic_type; 752 struct fdc_data *fdc; 753 char myname[8]; /* better be long enough */ 754 755 fdc = device_get_softc(dev); 756 bzero(fdc, sizeof *fdc); 757 fdc->fdc_dev = dev; 758 fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0; 759 fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0; 760 761 fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, 762 &fdc->rid_ioport, 0ul, ~0ul, 763 IO_FDCSIZE, RF_ACTIVE); 764 if (fdc->res_ioport == 0) { 765 device_print_prettyname(dev); 766 printf("cannot reserve I/O port range\n"); 767 error = ENXIO; 768 goto out; 769 } 770 fdc->baseport = fdc->res_ioport->r_start; 771 772 fdc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, 773 &fdc->rid_irq, 0ul, ~0ul, 1, 774 RF_ACTIVE); 775 if (fdc->res_irq == 0) { 776 device_print_prettyname(dev); 777 printf("cannot reserve interrupt line\n"); 778 error = ENXIO; 779 goto out; 780 } 781 fdc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, 782 &fdc->rid_drq, 0ul, ~0ul, 1, 783 RF_ACTIVE); 784 if (fdc->res_drq == 0) { 785 device_print_prettyname(dev); 786 printf("cannot reserve DMA request line\n"); 787 error = ENXIO; 788 goto out; 789 } 790 fdc->dmachan = fdc->res_drq->r_start; 791 error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq, 792 INTR_TYPE_BIO, fdc_intr, fdc, &fdc->fdc_intr); 793 794#ifndef PC98 795 /* First - lets reset the floppy controller */ 796 outb(fdc->baseport + FDOUT, 0); 797 DELAY(100); 798 outb(fdc->baseport + FDOUT, FDO_FRST); 799#endif 800 801 /* see if it can handle a command */ 802#ifdef PC98 803 if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240), 804 NE7_SPEC_2(2, 0), 0)) { 805 error = ENXIO; 806 goto out; 807 } 808#else 809 if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), 810 NE7_SPEC_2(2, 0), 0)) { 811 error = ENXIO; 812 goto out; 813 } 814#endif 815 816#ifndef PC98 817 if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) { 818 ic_type = (u_char)ic_type; 819 switch (ic_type) { 820 case 0x80: 821 device_set_desc(dev, "NEC 765 or clone"); 822 fdc->fdct = FDC_NE765; 823 break; 824 case 0x81: 825 device_set_desc(dev, "Intel 82077 or clone"); 826 fdc->fdct = FDC_I82077; 827 break; 828 case 0x90: 829 device_set_desc(dev, "NEC 72065B or clone"); 830 fdc->fdct = FDC_NE72065; 831 break; 832 default: 833 device_set_desc(dev, "generic floppy controller"); 834 fdc->fdct = FDC_UNKNOWN; 835 break; 836 } 837 } 838#endif 839 840 snprintf(myname, sizeof(myname), "%s%d", device_get_name(dev), 841 device_get_unit(dev)); 842 for (i = resource_query_string(-1, "at", myname); i != -1; 843 i = resource_query_string(i, "at", myname)) 844 fdc_add_device(dev, resource_query_name(i), 845 resource_query_unit(i)); 846#ifdef FDC_YE 847 /* 848 * don't succeed on probe; wait 849 * for PCCARD subsystem to do it 850 */ 851 if (dev->id_flags & FDC_IS_PCMCIA) 852 return(0); 853#endif 854 return (0); 855 856out: 857 if (fdc->fdc_intr) 858 BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq, 859 fdc->fdc_intr); 860 if (fdc->res_irq != 0) { 861 bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq, 862 fdc->res_irq); 863 bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq, 864 fdc->res_irq); 865 } 866 if (fdc->res_ioport != 0) { 867 bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, 868 fdc->res_ioport); 869 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, 870 fdc->res_ioport); 871 } 872 if (fdc->res_drq != 0) { 873 bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq, 874 fdc->res_drq); 875 bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq, 876 fdc->res_drq); 877 } 878 return (error); 879} 880 881/* 882 * Aped dfr@freebsd.org's isa_add_device(). 883 */ 884static void 885fdc_add_device(device_t dev, const char *name, int unit) 886{ 887 int disabled, *ivar; 888 device_t child; 889 890 ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT); 891 if (ivar == 0) 892 return; 893 if (resource_int_value(name, unit, "drive", ivar) == 0) 894 *ivar = 0; 895 child = device_add_child(dev, name, unit, ivar); 896 if (child == 0) 897 return; 898 if (resource_int_value(name, unit, "disabled", &disabled) == 0) 899 device_disable(child); 900} 901 902static int 903fdc_attach(device_t dev) 904{ 905 struct fdc_data *fdc = device_get_softc(dev); 906 fdcu_t fdcu = device_get_unit(dev); 907 908 fdc->fdcu = fdcu; 909 fdc->flags |= FDC_ATTACHED; 910 911 /* Acquire the DMA channel forever, The driver will do the rest */ 912 /* XXX should integrate with rman */ 913 isa_dma_acquire(fdc->dmachan); 914 isa_dmainit(fdc->dmachan, 128 << 3 /* XXX max secsize */); 915 fdc->state = DEVIDLE; 916 917#ifdef PC98 918 /* reset controller, turn motor off, clear fdout mirror reg */ 919 fdc_reset(fdc); 920#else 921 /* reset controller, turn motor off, clear fdout mirror reg */ 922 outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); 923#endif 924 bufq_init(&fdc->head); 925 926#ifdef FIFO_BEFORE_MOTORON 927 /* Hmm, this doesn't work here - is set_motor() magic? -Peter */ 928 if (fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN 929 && enable_fifo(fdc) == 0) { 930 device_print_prettyname(dev); 931 printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); 932 } 933#endif 934 /* 935 * Probe and attach any children as were configured above. 936 */ 937 return (bus_generic_attach(dev)); 938} 939 940static void 941fdc_print_child(device_t me, device_t child) 942{ 943 printf(" at %s%d drive %d", device_get_name(me), device_get_unit(me), 944 *(int *)device_get_ivars(child)); 945} 946 947static int 948fd_probe(device_t dev) 949{ 950 int i; 951 u_int fdt, st0, st3; 952 struct fd_data *fd; 953 struct fdc_data *fdc; 954 fdsu_t fdsu; 955#ifndef FIFO_BEFORE_MOTORON 956 static int fd_fifo = 0; 957#endif 958 959 fdsu = *(int *)device_get_ivars(dev); /* xxx cheat a bit... */ 960 fd = device_get_softc(dev); 961 fdc = device_get_softc(device_get_parent(dev)); 962 963 bzero(fd, sizeof *fd); 964 fd->dev = dev; 965 fd->fdc = fdc; 966 fd->fdsu = fdsu; 967 fd->fdu = device_get_unit(dev); 968 969#ifdef PC98 970 /* look up what bios thinks we have */ 971 switch (fd->fdu) { 972 case 0: case 1: case 2: case 3: 973 if ((PC98_SYSTEM_PARAMETER(0x5ae) >> fd->fdu) & 0x01) 974 fdt = FDT_144M; 975#ifdef EPSON_NRDISK 976 else if ((PC98_SYSTEM_PARAMETER(0x55c) >> fd->fdu) & 0x01) { 977 fdt = FDT_12M; 978 switch (epson_machine_id) { 979 case 0x20: case 0x27: 980 if ((PC98_SYSTEM_PARAMETER(0x488) >> fd->fdu) & 0x01) { 981 if (nrd_check_ready()) { 982 nrd_LED_on(); 983 nrdu = fd->fdu; 984 } else { 985 fdt = FDT_NONE; 986 } 987 } 988 } 989 } 990#else /* !EPSON_NRDISK */ 991 else if ((PC98_SYSTEM_PARAMETER(0x55c) >> fd->fdu) & 0x01) { 992 fdt = FDT_12M; 993 switch (epson_machine_id) { 994 case 0x20: case 0x27: 995 if ((PC98_SYSTEM_PARAMETER(0x488) >> fd->fdu) & 0x01) 996 fdt = FDT_NONE; 997 } 998 } 999#endif /* EPSON_NRDISK */ 1000 else 1001 fdt = FDT_NONE; 1002 break; 1003 default: 1004 fdt = FDT_NONE; 1005 break; 1006 } 1007#else 1008 /* look up what bios thinks we have */ 1009 switch (fd->fdu) { 1010 case 0: 1011 if (isa_get_flags(fdc->fdc_dev) & FDC_PRETEND_D0) 1012 fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED; 1013 else 1014 fdt = (rtcin(RTC_FDISKETTE) & 0xf0); 1015 break; 1016 case 1: 1017 fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); 1018 break; 1019 default: 1020 fdt = RTCFDT_NONE; 1021 break; 1022 } 1023#endif 1024 1025 /* is there a unit? */ 1026#ifdef PC98 1027 if (fdt == FDT_NONE) 1028 return (ENXIO); 1029#else 1030 if (fdt == RTCFDT_NONE) 1031 return (ENXIO); 1032#endif 1033 1034#ifndef PC98 1035 /* select it */ 1036 set_motor(fdc, fdsu, TURNON); 1037 DELAY(1000000); /* 1 sec */ 1038 1039#ifndef FIFO_BEFORE_MOTORON 1040 if (fd_fifo == 0 && fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN 1041 && enable_fifo(fdc) == 0) { 1042 device_print_prettyname(device_get_parent(dev)); 1043 printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); 1044 } 1045 fd_fifo = 1; 1046#endif 1047 1048 if ((fd_cmd(fdc, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) 1049 && (st3 & NE7_ST3_T0)) { 1050 /* if at track 0, first seek inwards */ 1051 /* seek some steps: */ 1052 fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0); 1053 DELAY(300000); /* ...wait a moment... */ 1054 fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ 1055 } 1056 1057 /* If we're at track 0 first seek inwards. */ 1058 if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) { 1059 /* Seek some steps... */ 1060 if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { 1061 /* ...wait a moment... */ 1062 DELAY(300000); 1063 /* make ctrlr happy: */ 1064 fd_sense_int(fdc, 0, 0); 1065 } 1066 } 1067 1068 for (i = 0; i < 2; i++) { 1069 /* 1070 * we must recalibrate twice, just in case the 1071 * heads have been beyond cylinder 76, since most 1072 * FDCs still barf when attempting to recalibrate 1073 * more than 77 steps 1074 */ 1075 /* go back to 0: */ 1076 if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) { 1077 /* a second being enough for full stroke seek*/ 1078 DELAY(i == 0 ? 1000000 : 300000); 1079 1080 /* anything responding? */ 1081 if (fd_sense_int(fdc, &st0, 0) == 0 && 1082 (st0 & NE7_ST0_EC) == 0) 1083 break; /* already probed succesfully */ 1084 } 1085 } 1086 1087 set_motor(fdc, fdsu, TURNOFF); 1088 1089 if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ 1090 return (ENXIO); 1091#endif /* PC98 */ 1092 1093 fd->track = FD_NO_TRACK; 1094 fd->fdc = fdc; 1095 fd->fdsu = fdsu; 1096 fd->options = 0; 1097 callout_handle_init(&fd->toffhandle); 1098 callout_handle_init(&fd->tohandle); 1099 1100#ifdef PC98 1101 switch (fdt) { 1102 case FDT_12M: 1103#ifdef EPSON_NRDISK 1104 if (fdu == nrdu) { 1105 device_set_desc(dev, "EPSON RAM DRIVE"); 1106 nrd_LED_off(); 1107 } else 1108 device_set_desc(dev, "1M/640M FDD"); 1109#else 1110 device_set_desc(dev, "1M/640M FDD"); 1111#endif 1112 fd->type = FD_1200; 1113 fd->pc98_trans = 0; 1114 break; 1115 case FDT_144M: 1116 device_set_desc(dev, "1.44M FDD"); 1117 fd->type = FD_1200; 1118 fd->pc98_trans = 0; 1119 outb(0x4be, (fd->fdu << 5) | 0x10); 1120 break; 1121 default: 1122 return (ENXIO); 1123 } 1124#else 1125 switch (fdt) { 1126 case RTCFDT_12M: 1127 device_set_desc(dev, "1200-KB 5.25\" drive"); 1128 fd->type = FD_1200; 1129 break; 1130 case RTCFDT_144M | RTCFDT_144M_PRETENDED: 1131 device_set_desc(dev, "config-pretended 1440-MB 3.5\" drive"); 1132 fdt = RTCFDT_144M; 1133 fd->type = FD_1440; 1134 case RTCFDT_144M: 1135 device_set_desc(dev, "1440-KB 3.5\" drive"); 1136 fd->type = FD_1440; 1137 break; 1138 case RTCFDT_288M: 1139 case RTCFDT_288M_1: 1140 device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)"); 1141 fd->type = FD_1440; 1142 break; 1143 case RTCFDT_360K: 1144 device_set_desc(dev, "360-KB 5.25\" drive"); 1145 fd->type = FD_360; 1146 break; 1147 case RTCFDT_720K: 1148 printf("720-KB 3.5\" drive"); 1149 fd->type = FD_720; 1150 break; 1151 default: 1152 return (ENXIO); 1153 } 1154#endif 1155 return (0); 1156} 1157 1158static int 1159fd_attach(device_t dev) 1160{ 1161 struct fd_data *fd; 1162#ifdef DEVFS 1163 int i; 1164 int mynor; 1165 int typemynor; 1166 int typesize; 1167#endif 1168 1169 fd = device_get_softc(dev); 1170 1171#ifdef DEVFS /* XXX bitrot */ 1172 mynor = fd->fdu << 6; 1173 fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, 1174 UID_ROOT, GID_OPERATOR, 0640, 1175 "fd%d", fd->fdu); 1176 fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, 1177 UID_ROOT, GID_OPERATOR, 0640, 1178 "rfd%d", fd->fdu); 1179 for (i = 1; i < 1 + NUMDENS; i++) { 1180 /* 1181 * XXX this and the lookup in Fdopen() should be 1182 * data driven. 1183 */ 1184#ifdef PC98 1185 switch (fd->type) { 1186 case FDT_12M: 1187 if (i != FD_1200 && i != FD_1232 1188 && i != FD_720 && i != FD_640) 1189 continue; 1190 break; 1191 case FDT_144M: 1192 if (i != FD_1200 && i != FD_1232 1193 && i != FD_720 && i != FD_640 1194 && i != FD_1440) 1195 continue; 1196 break; 1197 } 1198#else 1199 switch (fd->type) { 1200 case FD_360: 1201 if (i != FD_360) 1202 continue; 1203 break; 1204 case FD_720: 1205 if (i != FD_720 && i != FD_800 && i != FD_820) 1206 continue; 1207 break; 1208 case FD_1200: 1209 if (i != FD_360 && i != FD_720 && i != FD_800 1210 && i != FD_820 && i != FD_1200 1211 && i != FD_1440 && i != FD_1480) 1212 continue; 1213 break; 1214 case FD_1440: 1215 if (i != FD_720 && i != FD_800 && i != FD_820 1216 && i != FD_1200 && i != FD_1440 1217 && i != FD_1480 && i != FD_1720) 1218 continue; 1219 break; 1220 } 1221#endif 1222#ifdef PC98 1223 if (i == FD_1232) 1224 typesize = fd_types[i - 1].size; 1225 else 1226 typesize = fd_types[i - 1].size / 2; 1227#else 1228 typesize = fd_types[i - 1].size / 2; 1229 /* 1230 * XXX all these conversions give bloated code and 1231 * confusing names. 1232 */ 1233 if (typesize == 1476) 1234 typesize = 1480; 1235 if (typesize == 1722) 1236 typesize = 1720; 1237#endif 1238 typemynor = mynor | i; 1239 fd->bdevs[i] = 1240 devfs_add_devswf(&fd_cdevsw, typemynor, DV_BLK, 1241 UID_ROOT, GID_OPERATOR, 0640, 1242 "fd%d.%d", fd->fdu, typesize); 1243 fd->cdevs[i] = 1244 devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, 1245 UID_ROOT, GID_OPERATOR, 0640, 1246 "rfd%d.%d", fd->fdu, typesize); 1247 } 1248 1249 for (i = 0; i < MAXPARTITIONS; i++) { 1250 fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], 1251 "fd%d%c", fd->fdu, 'a' + i); 1252 fd->cdevs[1 + NUMDENS + i] = 1253 devfs_makelink(fd->cdevs[0], 1254 "rfd%d%c", fd->fdu, 'a' + i); 1255 } 1256#endif /* DEVFS */ 1257 /* 1258 * Export the drive to the devstat interface. 1259 */ 1260 devstat_add_entry(&fd->device_stats, device_get_name(dev), 1261 device_get_unit(dev), 512, DEVSTAT_NO_ORDERED_TAGS, 1262 DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, 1263 DEVSTAT_PRIORITY_FD); 1264 return (0); 1265} 1266 1267#ifdef FDC_YE 1268/* 1269 * this is a subset of fdattach() optimized for the Y-E Data 1270 * PCMCIA floppy drive. 1271 */ 1272static int yeattach(struct isa_device *dev) 1273{ 1274 fdcu_t fdcu = dev->id_unit; 1275 fdc_p fdc = fdc_data + fdcu; 1276 fdsu_t fdsu = 0; /* assume 1 drive per YE controller */ 1277 fdu_t fdu; 1278 fd_p fd; 1279 int st0, st3, i; 1280#ifdef DEVFS 1281 int mynor; 1282 int typemynor; 1283 int typesize; 1284#endif 1285 fdc->fdcu = fdcu; 1286 /* 1287 * the FDC_PCMCIA flag is used to to indicate special PIO is used 1288 * instead of DMA 1289 */ 1290 fdc->flags = FDC_ATTACHED|FDC_PCMCIA; 1291 fdc->state = DEVIDLE; 1292 /* reset controller, turn motor off, clear fdout mirror reg */ 1293 outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); 1294 bufq_init(&fdc->head); 1295 /* 1296 * assume 2 drives/ "normal" controller 1297 */ 1298 fdu = fdcu * 2; 1299 if (fdu >= NFD) { 1300 printf("fdu %d >= NFD\n",fdu); 1301 return(0); 1302 }; 1303 fd = &fd_data[fdu]; 1304 1305 set_motor(fdcu, fdsu, TURNON); 1306 DELAY(1000000); /* 1 sec */ 1307 fdc->fdct = FDC_NE765; 1308 1309 if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && 1310 (st3 & NE7_ST3_T0)) { 1311 /* if at track 0, first seek inwards */ 1312 /* seek some steps: */ 1313 (void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0); 1314 DELAY(300000); /* ...wait a moment... */ 1315 (void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ 1316 } 1317 1318 /* If we're at track 0 first seek inwards. */ 1319 if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) { 1320 /* Seek some steps... */ 1321 if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { 1322 /* ...wait a moment... */ 1323 DELAY(300000); 1324 /* make ctrlr happy: */ 1325 (void)fd_sense_int(fdc, 0, 0); 1326 } 1327 } 1328 1329 for(i = 0; i < 2; i++) { 1330 /* 1331 * we must recalibrate twice, just in case the 1332 * heads have been beyond cylinder 76, since most 1333 * FDCs still barf when attempting to recalibrate 1334 * more than 77 steps 1335 */ 1336 /* go back to 0: */ 1337 if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) { 1338 /* a second being enough for full stroke seek*/ 1339 DELAY(i == 0? 1000000: 300000); 1340 1341 /* anything responding? */ 1342 if (fd_sense_int(fdc, &st0, 0) == 0 && 1343 (st0 & NE7_ST0_EC) == 0) 1344 break; /* already probed succesfully */ 1345 } 1346 } 1347 1348 set_motor(fdcu, fdsu, TURNOFF); 1349 1350 if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ 1351 return(0); 1352 1353 fd->track = FD_NO_TRACK; 1354 fd->fdc = fdc; 1355 fd->fdsu = fdsu; 1356 fd->options = 0; 1357 printf("fdc%d: 1.44MB 3.5in PCMCIA\n", fdcu); 1358 fd->type = FD_1440; 1359 1360#ifdef DEVFS 1361 mynor = fdcu << 6; 1362 fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, 1363 UID_ROOT, GID_OPERATOR, 0640, 1364 "fd%d", fdu); 1365 fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, 1366 UID_ROOT, GID_OPERATOR, 0640, 1367 "rfd%d", fdu); 1368 /* 1369 * XXX this and the lookup in Fdopen() should be 1370 * data driven. 1371 */ 1372 typemynor = mynor | FD_1440; 1373 typesize = fd_types[FD_1440 - 1].size / 2; 1374 /* 1375 * XXX all these conversions give bloated code and 1376 * confusing names. 1377 */ 1378 if (typesize == 1476) 1379 typesize = 1480; 1380 if (typesize == 1722) 1381 typesize = 1720; 1382 fd->bdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor, 1383 DV_BLK, UID_ROOT, GID_OPERATOR, 1384 0640, "fd%d.%d", fdu, typesize); 1385 fd->cdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor, 1386 DV_CHR, UID_ROOT, GID_OPERATOR, 1387 0640,"rfd%d.%d", fdu, typesize); 1388 for (i = 0; i < MAXPARTITIONS; i++) { 1389 fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], 1390 "fd%d%c", fdu, 'a' + i); 1391 fd->cdevs[1 + NUMDENS + i] = devfs_makelink(fd->cdevs[0], 1392 "rfd%d%c", fdu, 'a' + i); 1393 } 1394#endif /* DEVFS */ 1395 return (1); 1396} 1397#endif 1398 1399/****************************************************************************/ 1400/* motor control stuff */ 1401/* remember to not deselect the drive we're working on */ 1402/****************************************************************************/ 1403static void 1404set_motor(struct fdc_data *fdc, int fdsu, int turnon) 1405{ 1406 int fdout = fdc->fdout; 1407 int needspecify = 0; 1408 1409#ifdef PC98 1410 outb(IO_FDPORT, (pc98_trans != 1 ? FDP_FDDEXC : 0)|FDP_PORTEXC); 1411 DELAY(10); 1412 fdout = FDO_DMAE|FDO_MTON; 1413#else 1414 if(turnon) { 1415 fdout &= ~FDO_FDSEL; 1416 fdout |= (FDO_MOEN0 << fdsu) + fdsu; 1417 } else 1418 fdout &= ~(FDO_MOEN0 << fdsu); 1419 1420 if(!turnon 1421 && (fdout & (FDO_MOEN0+FDO_MOEN1+FDO_MOEN2+FDO_MOEN3)) == 0) 1422 /* gonna turn off the last drive, put FDC to bed */ 1423 fdout &= ~ (FDO_FRST|FDO_FDMAEN); 1424 else { 1425 /* make sure controller is selected and specified */ 1426 if((fdout & (FDO_FRST|FDO_FDMAEN)) == 0) 1427 needspecify = 1; 1428 fdout |= (FDO_FRST|FDO_FDMAEN); 1429 } 1430#endif 1431 1432 outb(fdc->baseport+FDOUT, fdout); 1433 fdc->fdout = fdout; 1434 TRACE1("[0x%x->FDOUT]", fdout); 1435 1436 if (needspecify) { 1437 /* 1438 * XXX 1439 * special case: since we have just woken up the FDC 1440 * from its sleep, we silently assume the command will 1441 * be accepted, and do not test for a timeout 1442 */ 1443#ifdef PC98 1444 (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, 1445 NE7_SPEC_1(4, 240), NE7_SPEC_2(2, 0), 1446 0); 1447#else 1448 (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, 1449 NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 1450 0); 1451#endif 1452 if (fdc->flags & FDC_HAS_FIFO) 1453 (void) enable_fifo(fdc); 1454 } 1455} 1456 1457static void 1458fd_turnoff(void *xfd) 1459{ 1460 int s; 1461 fd_p fd = xfd; 1462 1463 TRACE1("[fd%d: turnoff]", fd->fdu); 1464 1465 /* 1466 * Don't turn off the motor yet if the drive is active. 1467 * XXX shouldn't even schedule turnoff until drive is inactive 1468 * and nothing is queued on it. 1469 */ 1470 if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) { 1471 fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); 1472 return; 1473 } 1474 1475 s = splbio(); 1476 fd->flags &= ~FD_MOTOR; 1477 set_motor(fd->fdc, fd->fdsu, TURNOFF); 1478 splx(s); 1479} 1480 1481static void 1482fd_motor_on(void *xfd) 1483{ 1484 int s; 1485 fd_p fd = xfd; 1486 1487 s = splbio(); 1488 fd->flags &= ~FD_MOTOR_WAIT; 1489 if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) 1490 { 1491 fdc_intr(fd->fdc); 1492 } 1493 splx(s); 1494} 1495 1496static void 1497fd_turnon(fd_p fd) 1498{ 1499 if(!(fd->flags & FD_MOTOR)) 1500 { 1501 fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT); 1502 set_motor(fd->fdc, fd->fdsu, TURNON); 1503 timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */ 1504 } 1505} 1506 1507static void 1508fdc_reset(fdc_p fdc) 1509{ 1510 /* Try a reset, keep motor on */ 1511#ifdef PC98 1512 set_density(fdc); 1513 if (pc98_machine_type & M_EPSON_PC98) 1514 outb(fdc->baseport + FDOUT, 0xe8); 1515 else 1516 outb(fdc->baseport + FDOUT, 0xd8); 1517 DELAY(200); 1518 outb(fdc->baseport + FDOUT, 0x18); 1519 DELAY(10); 1520#else 1521 outb(fdc->baseport + FDOUT, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); 1522 TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); 1523 DELAY(100); 1524 /* enable FDC, but defer interrupts a moment */ 1525 outb(fdc->baseport + FDOUT, fdc->fdout & ~FDO_FDMAEN); 1526 TRACE1("[0x%x->FDOUT]", fdc->fdout & ~FDO_FDMAEN); 1527 DELAY(100); 1528 outb(fdc->baseport + FDOUT, fdc->fdout); 1529 TRACE1("[0x%x->FDOUT]", fdc->fdout); 1530#endif 1531 1532 /* XXX after a reset, silently believe the FDC will accept commands */ 1533#ifdef PC98 1534 (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, 1535 NE7_SPEC_1(4, 240), NE7_SPEC_2(2, 0), 1536 0); 1537#else 1538 (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, 1539 NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 1540 0); 1541#endif 1542 if (fdc->flags & FDC_HAS_FIFO) 1543 (void) enable_fifo(fdc); 1544} 1545 1546/****************************************************************************/ 1547/* fdc in/out */ 1548/****************************************************************************/ 1549int 1550in_fdc(struct fdc_data *fdc) 1551{ 1552 int baseport = fdc->baseport; 1553 int i, j = 100000; 1554 while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) 1555 != (NE7_DIO|NE7_RQM) && j-- > 0) 1556 if (i == NE7_RQM) 1557 return fdc_err(fdc, "ready for output in input\n"); 1558 if (j <= 0) 1559 return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); 1560#ifdef FDC_DEBUG 1561 i = inb(baseport+FDDATA); 1562 TRACE1("[FDDATA->0x%x]", (unsigned char)i); 1563 return(i); 1564#else /* !FDC_DEBUG */ 1565 return inb(baseport+FDDATA); 1566#endif /* FDC_DEBUG */ 1567} 1568 1569/* 1570 * fd_in: Like in_fdc, but allows you to see if it worked. 1571 */ 1572static int 1573fd_in(struct fdc_data *fdc, int *ptr) 1574{ 1575 int baseport = fdc->baseport; 1576 int i, j = 100000; 1577 while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) 1578 != (NE7_DIO|NE7_RQM) && j-- > 0) 1579 if (i == NE7_RQM) 1580 return fdc_err(fdc, "ready for output in input\n"); 1581 if (j <= 0) 1582 return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); 1583#ifdef FDC_DEBUG 1584 i = inb(baseport+FDDATA); 1585 TRACE1("[FDDATA->0x%x]", (unsigned char)i); 1586 *ptr = i; 1587 return 0; 1588#else /* !FDC_DEBUG */ 1589 i = inb(baseport+FDDATA); 1590 if (ptr) 1591 *ptr = i; 1592 return 0; 1593#endif /* FDC_DEBUG */ 1594} 1595 1596int 1597out_fdc(struct fdc_data *fdc, int x) 1598{ 1599 int baseport = fdc->baseport; 1600 int i; 1601 1602 /* Check that the direction bit is set */ 1603 i = 100000; 1604 while ((inb(baseport+FDSTS) & NE7_DIO) && i-- > 0); 1605 if (i <= 0) return fdc_err(fdc, "direction bit not set\n"); 1606 1607 /* Check that the floppy controller is ready for a command */ 1608 i = 100000; 1609 while ((inb(baseport+FDSTS) & NE7_RQM) == 0 && i-- > 0); 1610 if (i <= 0) 1611 return fdc_err(fdc, bootverbose? "output ready timeout\n": 0); 1612 1613 /* Send the command and return */ 1614 outb(baseport+FDDATA, x); 1615 TRACE1("[0x%x->FDDATA]", x); 1616 return (0); 1617} 1618 1619/****************************************************************************/ 1620/* fdopen/fdclose */ 1621/****************************************************************************/ 1622int 1623Fdopen(dev_t dev, int flags, int mode, struct proc *p) 1624{ 1625 fdu_t fdu = FDUNIT(minor(dev)); 1626 int type = FDTYPE(minor(dev)); 1627 fd_p fd; 1628 fdc_p fdc; 1629 1630 /* check bounds */ 1631 if ((fd = devclass_get_softc(fd_devclass, fdu)) == 0) 1632 return (ENXIO); 1633 fdc = fd->fdc; 1634 if ((fdc == NULL) || (fd->type == NO_TYPE)) 1635 return (ENXIO); 1636 if (type > NUMDENS) 1637 return (ENXIO); 1638#ifdef PC98 1639 if (pc98_fd_check_ready(fdu) == -1) 1640 return(EIO); 1641#endif 1642 if (type == 0) 1643 type = fd->type; 1644#ifndef PC98 1645 else { 1646 /* 1647 * For each type of basic drive, make sure we are trying 1648 * to open a type it can do, 1649 */ 1650 if (type != fd->type) { 1651 switch (fd->type) { 1652 case FD_360: 1653 return (ENXIO); 1654 case FD_720: 1655 if ( type != FD_820 1656 && type != FD_800 1657 ) 1658 return (ENXIO); 1659 break; 1660 case FD_1200: 1661 switch (type) { 1662 case FD_1480: 1663 type = FD_1480in5_25; 1664 break; 1665 case FD_1440: 1666 type = FD_1440in5_25; 1667 break; 1668 case FD_820: 1669 type = FD_820in5_25; 1670 break; 1671 case FD_800: 1672 type = FD_800in5_25; 1673 break; 1674 case FD_720: 1675 type = FD_720in5_25; 1676 break; 1677 case FD_360: 1678 type = FD_360in5_25; 1679 break; 1680 default: 1681 return(ENXIO); 1682 } 1683 break; 1684 case FD_1440: 1685 if ( type != FD_1720 1686 && type != FD_1480 1687 && type != FD_1200 1688 && type != FD_820 1689 && type != FD_800 1690 && type != FD_720 1691 ) 1692 return(ENXIO); 1693 break; 1694 } 1695 } 1696 } 1697#endif 1698 fd->ft = fd_types + type - 1; 1699 fd->flags |= FD_OPEN; 1700 device_busy(fd->dev); 1701 device_busy(fd->fdc->fdc_dev); 1702 return 0; 1703} 1704 1705int 1706fdclose(dev_t dev, int flags, int mode, struct proc *p) 1707{ 1708 fdu_t fdu = FDUNIT(minor(dev)); 1709 struct fd_data *fd; 1710 1711 fd = devclass_get_softc(fd_devclass, fdu); 1712 fd->flags &= ~FD_OPEN; 1713 fd->options &= ~FDOPT_NORETRY; 1714 1715 return (0); 1716} 1717 1718/****************************************************************************/ 1719/* fdstrategy */ 1720/****************************************************************************/ 1721void 1722fdstrategy(struct buf *bp) 1723{ 1724 unsigned nblocks, blknum, cando; 1725 int s; 1726 fdu_t fdu; 1727 fdc_p fdc; 1728 fd_p fd; 1729 size_t fdblk; 1730 1731 fdu = FDUNIT(minor(bp->b_dev)); 1732 fd = devclass_get_softc(fd_devclass, fdu); 1733 if (fd == 0) 1734 panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)", 1735 (u_long)major(bp->b_dev), (u_long)minor(bp->b_dev)); 1736 fdc = fd->fdc; 1737#ifdef FDC_YE 1738 if (fd->type == NO_TYPE) { 1739 bp->b_error = ENXIO; 1740 bp->b_flags |= B_ERROR; 1741 /* 1742 * I _refuse_ to use a goto 1743 */ 1744 biodone(bp); 1745 return; 1746 }; 1747#endif 1748 1749 fdblk = 128 << (fd->ft->secsize); 1750 if (!(bp->b_flags & B_FORMAT)) { 1751 if (bp->b_blkno < 0) { 1752 printf( 1753 "fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n", 1754 fdu, (u_long)bp->b_blkno, bp->b_bcount); 1755 bp->b_error = EINVAL; 1756 bp->b_flags |= B_ERROR; 1757 goto bad; 1758 } 1759 if ((bp->b_bcount % fdblk) != 0) { 1760 bp->b_error = EINVAL; 1761 bp->b_flags |= B_ERROR; 1762 goto bad; 1763 } 1764 } 1765 1766 /* 1767 * Set up block calculations. 1768 */ 1769 if (bp->b_blkno > 20000000) { 1770 /* 1771 * Reject unreasonably high block number, prevent the 1772 * multiplication below from overflowing. 1773 */ 1774 bp->b_error = EINVAL; 1775 bp->b_flags |= B_ERROR; 1776 goto bad; 1777 } 1778 blknum = (unsigned) bp->b_blkno * DEV_BSIZE/fdblk; 1779 nblocks = fd->ft->size; 1780 bp->b_resid = 0; 1781 if (blknum + (bp->b_bcount / fdblk) > nblocks) { 1782 if (blknum <= nblocks) { 1783 cando = (nblocks - blknum) * fdblk; 1784 bp->b_resid = bp->b_bcount - cando; 1785 if (cando == 0) 1786 goto bad; /* not actually bad but EOF */ 1787 } else { 1788 bp->b_error = EINVAL; 1789 bp->b_flags |= B_ERROR; 1790 goto bad; 1791 } 1792 } 1793 bp->b_pblkno = bp->b_blkno; 1794 s = splbio(); 1795 bufqdisksort(&fdc->head, bp); 1796 untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */ 1797 1798 /* Tell devstat we are starting on the transaction */ 1799 devstat_start_transaction(&fd->device_stats); 1800 1801 fdstart(fdc); 1802 splx(s); 1803 return; 1804 1805bad: 1806 biodone(bp); 1807} 1808 1809/***************************************************************\ 1810* fdstart * 1811* We have just queued something.. if the controller is not busy * 1812* then simulate the case where it has just finished a command * 1813* So that it (the interrupt routine) looks on the queue for more* 1814* work to do and picks up what we just added. * 1815* If the controller is already busy, we need do nothing, as it * 1816* will pick up our work when the present work completes * 1817\***************************************************************/ 1818static void 1819fdstart(struct fdc_data *fdc) 1820{ 1821 int s; 1822 1823 s = splbio(); 1824 if(fdc->state == DEVIDLE) 1825 { 1826 fdc_intr(fdc); 1827 } 1828 splx(s); 1829} 1830 1831static void 1832fd_iotimeout(void *xfdc) 1833{ 1834 fdc_p fdc; 1835 int s; 1836 1837 fdc = xfdc; 1838 TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); 1839 1840 /* 1841 * Due to IBM's brain-dead design, the FDC has a faked ready 1842 * signal, hardwired to ready == true. Thus, any command 1843 * issued if there's no diskette in the drive will _never_ 1844 * complete, and must be aborted by resetting the FDC. 1845 * Many thanks, Big Blue! 1846 * The FDC must not be reset directly, since that would 1847 * interfere with the state machine. Instead, pretend that 1848 * the command completed but was invalid. The state machine 1849 * will reset the FDC and retry once. 1850 */ 1851 s = splbio(); 1852 fdc->status[0] = NE7_ST0_IC_IV; 1853 fdc->flags &= ~FDC_STAT_VALID; 1854 fdc->state = IOTIMEDOUT; 1855 fdc_intr(fdc); 1856 splx(s); 1857} 1858 1859/* just ensure it has the right spl */ 1860static void 1861fd_pseudointr(void *xfdc) 1862{ 1863 int s; 1864 1865 s = splbio(); 1866 fdc_intr(xfdc); 1867 splx(s); 1868} 1869 1870/***********************************************************************\ 1871* fdintr * 1872* keep calling the state machine until it returns a 0 * 1873* ALWAYS called at SPLBIO * 1874\***********************************************************************/ 1875static void 1876fdc_intr(void *xfdc) 1877{ 1878 fdc_p fdc = xfdc; 1879 while(fdstate(fdc)) 1880 ; 1881} 1882 1883#ifdef FDC_YE 1884/* 1885 * magic pseudo-DMA initialization for YE FDC. Sets count and 1886 * direction 1887 */ 1888#define SET_BCDR(wr,cnt,port) outb(port,(((cnt)-1) & 0xff)); \ 1889 outb(port+1,((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f))) 1890 1891/* 1892 * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy 1893 */ 1894static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count) 1895{ 1896 u_char *cptr = (u_char *)addr; 1897 fdc_p fdc = &fdc_data[fdcu]; 1898 int io = fdc->baseport; 1899 1900 if (flags & B_READ) { 1901 if (fdc->state != PIOREAD) { 1902 fdc->state = PIOREAD; 1903 return(0); 1904 }; 1905 SET_BCDR(0,count,io); 1906 insb(io+FDC_YE_DATAPORT,cptr,count); 1907 } else { 1908 outsb(io+FDC_YE_DATAPORT,cptr,count); 1909 SET_BCDR(0,count,io); 1910 }; 1911 return(1); 1912} 1913#endif /* FDC_YE */ 1914 1915/***********************************************************************\ 1916* The controller state machine. * 1917* if it returns a non zero value, it should be called again immediatly * 1918\***********************************************************************/ 1919static int 1920fdstate(fdc_p fdc) 1921{ 1922 int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; 1923 unsigned blknum = 0, b_cylinder = 0; 1924 fdu_t fdu = fdc->fdu; 1925 fd_p fd; 1926 register struct buf *bp; 1927 struct fd_formb *finfo = NULL; 1928 size_t fdblk; 1929 1930 bp = fdc->bp; 1931 if (bp == NULL) { 1932 bp = bufq_first(&fdc->head); 1933 if (bp != NULL) { 1934 bufq_remove(&fdc->head, bp); 1935 fdc->bp = bp; 1936 } 1937 } 1938 if (bp == NULL) { 1939 /***********************************************\ 1940 * nothing left for this controller to do * 1941 * Force into the IDLE state, * 1942 \***********************************************/ 1943 fdc->state = DEVIDLE; 1944 if (fdc->fd) { 1945 device_print_prettyname(fdc->fdc_dev); 1946 printf("unexpected valid fd pointer\n"); 1947 fdc->fd = (fd_p) 0; 1948 fdc->fdu = -1; 1949 } 1950 TRACE1("[fdc%d IDLE]", fdc->fdcu); 1951 return (0); 1952 } 1953 fdu = FDUNIT(minor(bp->b_dev)); 1954 fd = devclass_get_softc(fd_devclass, fdu); 1955 fdblk = 128 << fd->ft->secsize; 1956 if (fdc->fd && (fd != fdc->fd)) { 1957 device_print_prettyname(fd->dev); 1958 printf("confused fd pointers\n"); 1959 } 1960 read = bp->b_flags & B_READ; 1961 format = bp->b_flags & B_FORMAT; 1962 if (format) { 1963 finfo = (struct fd_formb *)bp->b_data; 1964 fd->skip = (char *)&(finfo->fd_formb_cylno(0)) 1965 - (char *)finfo; 1966 } 1967 if (fdc->state == DOSEEK || fdc->state == SEEKCOMPLETE) { 1968 blknum = (unsigned) bp->b_pblkno * DEV_BSIZE/fdblk + 1969 fd->skip/fdblk; 1970 b_cylinder = blknum / (fd->ft->sectrac * fd->ft->heads); 1971 } 1972 TRACE1("fd%d", fdu); 1973 TRACE1("[%s]", fdstates[fdc->state]); 1974 TRACE1("(0x%x)", fd->flags); 1975 untimeout(fd_turnoff, fd, fd->toffhandle); 1976 fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); 1977 switch (fdc->state) 1978 { 1979 case DEVIDLE: 1980 case FINDWORK: /* we have found new work */ 1981 fdc->retry = 0; 1982 fd->skip = 0; 1983 fdc->fd = fd; 1984 fdc->fdu = fdu; 1985#ifdef PC98 1986 pc98_trans = fd->ft->trans; 1987 if (pc98_trans_prev != pc98_trans) { 1988 int i; 1989 set_density(fdc); 1990 for (i = 0; i < 10; i++) { 1991 outb(0x5f, 0); 1992 outb(0x5f, 0); 1993 } 1994 pc98_trans_prev = pc98_trans; 1995 } 1996 if (pc98_trans != fd->pc98_trans) { 1997 if (pc98_trans != 1 && 1998 (PC98_SYSTEM_PARAMETER(0x5ae) >> fdu) & 0x01) { 1999 outb(0x4be, (fdu << 5) | 0x10 | (pc98_trans >> 1)); 2000 outb(0x5f, 0); 2001 outb(0x5f, 0); 2002 } 2003 fd->pc98_trans = pc98_trans; 2004 } 2005#else 2006 outb(fdc->baseport+FDCTL, fd->ft->trans); 2007#endif 2008 TRACE1("[0x%x->FDCTL]", fd->ft->trans); 2009 /*******************************************************\ 2010 * If the next drive has a motor startup pending, then * 2011 * it will start up in its own good time * 2012 \*******************************************************/ 2013 if(fd->flags & FD_MOTOR_WAIT) { 2014 fdc->state = MOTORWAIT; 2015 return (0); /* come back later */ 2016 } 2017 /*******************************************************\ 2018 * Maybe if it's not starting, it SHOULD be starting * 2019 \*******************************************************/ 2020#ifdef EPSON_NRDISK 2021 if (fdu != nrdu) { 2022 if (!(fd->flags & FD_MOTOR)) 2023 { 2024 fdc->state = MOTORWAIT; 2025 fd_turnon(fdu); 2026 return(0); 2027 } 2028 else /* at least make sure we are selected */ 2029 { 2030 set_motor(fdcu, fd->fdsu, TURNON); 2031 } 2032 } 2033#else /* !EPSON_NRDISK */ 2034 if (!(fd->flags & FD_MOTOR)) 2035 { 2036 fdc->state = MOTORWAIT; 2037 fd_turnon(fd); 2038 return (0); 2039 } 2040 else /* at least make sure we are selected */ 2041 { 2042 set_motor(fdc, fd->fdsu, TURNON); 2043 } 2044#endif 2045 if (fdc->flags & FDC_NEEDS_RESET) { 2046 fdc->state = RESETCTLR; 2047 fdc->flags &= ~FDC_NEEDS_RESET; 2048 } else 2049 fdc->state = DOSEEK; 2050 break; 2051 case DOSEEK: 2052 if (b_cylinder == (unsigned)fd->track) 2053 { 2054 fdc->state = SEEKCOMPLETE; 2055 break; 2056 } 2057#ifdef PC98 2058 pc98_fd_check_ready(fdu); 2059#endif 2060 if (fd_cmd(fdc, 3, NE7CMD_SEEK, 2061 fd->fdsu, b_cylinder * fd->ft->steptrac, 2062 0)) 2063 { 2064 /* 2065 * seek command not accepted, looks like 2066 * the FDC went off to the Saints... 2067 */ 2068 fdc->retry = 6; /* try a reset */ 2069 return(retrier(fdc)); 2070 } 2071 fd->track = FD_NO_TRACK; 2072 fdc->state = SEEKWAIT; 2073 return(0); /* will return later */ 2074 case SEEKWAIT: 2075 /* allow heads to settle */ 2076 timeout(fd_pseudointr, fdc, hz / 16); 2077 fdc->state = SEEKCOMPLETE; 2078 return(0); /* will return later */ 2079 case SEEKCOMPLETE : /* SEEK DONE, START DMA */ 2080 /* Make sure seek really happened*/ 2081 if(fd->track == FD_NO_TRACK) { 2082 int descyl = b_cylinder * fd->ft->steptrac; 2083 do { 2084 /* 2085 * This might be a "ready changed" interrupt, 2086 * which cannot really happen since the 2087 * RDY pin is hardwired to + 5 volts. This 2088 * generally indicates a "bouncing" intr 2089 * line, so do one of the following: 2090 * 2091 * When running on an enhanced FDC that is 2092 * known to not go stuck after responding 2093 * with INVALID, fetch all interrupt states 2094 * until seeing either an INVALID or a 2095 * real interrupt condition. 2096 * 2097 * When running on a dumb old NE765, give 2098 * up immediately. The controller will 2099 * provide up to four dummy RC interrupt 2100 * conditions right after reset (for the 2101 * corresponding four drives), so this is 2102 * our only chance to get notice that it 2103 * was not the FDC that caused the interrupt. 2104 */ 2105 if (fd_sense_int(fdc, &st0, &cyl) 2106 == FD_NOT_VALID) 2107 return 0; 2108 if(fdc->fdct == FDC_NE765 2109 && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC) 2110 return 0; /* hope for a real intr */ 2111 } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); 2112 2113 if (0 == descyl) { 2114 int failed = 0; 2115 /* 2116 * seek to cyl 0 requested; make sure we are 2117 * really there 2118 */ 2119 if (fd_sense_drive_status(fdc, &st3)) 2120 failed = 1; 2121#ifdef EPSON_NRDISK 2122 if (fdu == nrdu) st3 = NE7_ST3_T0; 2123#endif /* EPSON_NRDISK */ 2124 if ((st3 & NE7_ST3_T0) == 0) { 2125 printf( 2126 "fd%d: Seek to cyl 0, but not really there (ST3 = %b)\n", 2127 fdu, st3, NE7_ST3BITS); 2128 failed = 1; 2129 } 2130 2131 if (failed) { 2132 if(fdc->retry < 3) 2133 fdc->retry = 3; 2134 return (retrier(fdc)); 2135 } 2136 } 2137#ifdef EPSON_NRDISK 2138 if (fdu == nrdu) cyl = descyl; 2139#endif 2140 2141 if (cyl != descyl) { 2142 printf( 2143 "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", 2144 fdu, descyl, cyl, st0); 2145 if (fdc->retry < 3) 2146 fdc->retry = 3; 2147 return (retrier(fdc)); 2148 } 2149 } 2150 2151 fd->track = b_cylinder; 2152#ifdef EPSON_NRDISK 2153 if (fdu != nrdu) { 2154#endif /* EPSON_NRDISK */ 2155#ifdef FDC_YE 2156 if (!(fdc->flags & FDC_PCMCIA)) 2157#endif 2158 isa_dmastart(bp->b_flags, bp->b_data+fd->skip, 2159 format ? bp->b_bcount : fdblk, fdc->dmachan); 2160 sectrac = fd->ft->sectrac; 2161 sec = blknum % (sectrac * fd->ft->heads); 2162 head = sec / sectrac; 2163 sec = sec % sectrac + 1; 2164 fd->hddrv = ((head&1)<<2)+fdu; 2165 2166 if(format || !read) 2167 { 2168 /* make sure the drive is writable */ 2169 if(fd_sense_drive_status(fdc, &st3) != 0) 2170 { 2171 /* stuck controller? */ 2172 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2173 format ? bp->b_bcount : fdblk, 2174 fdc->dmachan); 2175 fdc->retry = 6; /* reset the beast */ 2176 return (retrier(fdc)); 2177 } 2178 if(st3 & NE7_ST3_WP) 2179 { 2180 /* 2181 * XXX YES! this is ugly. 2182 * in order to force the current operation 2183 * to fail, we will have to fake an FDC 2184 * error - all error handling is done 2185 * by the retrier() 2186 */ 2187 fdc->status[0] = NE7_ST0_IC_AT; 2188 fdc->status[1] = NE7_ST1_NW; 2189 fdc->status[2] = 0; 2190 fdc->status[3] = fd->track; 2191 fdc->status[4] = head; 2192 fdc->status[5] = sec; 2193 fdc->retry = 8; /* break out immediately */ 2194 fdc->state = IOTIMEDOUT; /* not really... */ 2195 return (1); 2196 } 2197 } 2198 2199 if (format) { 2200#ifdef FDC_YE 2201 if (fdc->flags & FDC_PCMCIA) 2202 (void)fdcpio(fdcu,bp->b_flags, 2203 bp->b_data+fd->skip, 2204 bp->b_bcount); 2205#endif 2206 /* formatting */ 2207 if(fd_cmd(fdc, 6, NE7CMD_FORMAT, head << 2 | fdu, 2208 finfo->fd_formb_secshift, 2209 finfo->fd_formb_nsecs, 2210 finfo->fd_formb_gaplen, 2211 finfo->fd_formb_fillbyte, 0)) { 2212 /* controller fell over */ 2213 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2214 format ? bp->b_bcount : fdblk, 2215 fdc->dmachan); 2216 fdc->retry = 6; 2217 return (retrier(fdc)); 2218 } 2219 } else { 2220#ifdef FDC_YE 2221 if (fdc->flags & FDC_PCMCIA) { 2222 /* 2223 * this seems to be necessary even when 2224 * reading data 2225 */ 2226 SET_BCDR(1,fdblk,fdc->baseport); 2227 2228 /* 2229 * perform the write pseudo-DMA before 2230 * the WRITE command is sent 2231 */ 2232 if (!read) 2233 (void)fdcpio(fdcu,bp->b_flags, 2234 bp->b_data+fd->skip, 2235 fdblk); 2236 } 2237#endif 2238 if (fd_cmd(fdc, 9, 2239 (read ? NE7CMD_READ : NE7CMD_WRITE), 2240 head << 2 | fdu, /* head & unit */ 2241 fd->track, /* track */ 2242 head, 2243 sec, /* sector + 1 */ 2244 fd->ft->secsize, /* sector size */ 2245 sectrac, /* sectors/track */ 2246 fd->ft->gap, /* gap size */ 2247 fd->ft->datalen, /* data length */ 2248 0)) { 2249 /* the beast is sleeping again */ 2250 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2251 format ? bp->b_bcount : fdblk, 2252 fdc->dmachan); 2253 fdc->retry = 6; 2254 return (retrier(fdc)); 2255 } 2256 } 2257#ifdef FDC_YE 2258 if (fdc->flags & FDC_PCMCIA) 2259 /* 2260 * if this is a read, then simply await interrupt 2261 * before performing PIO 2262 */ 2263 if (read && !fdcpio(fdcu,bp->b_flags, 2264 bp->b_data+fd->skip,fdblk)) { 2265 fd->tohandle = timeout(fd_iotimeout, 2266 (caddr_t)fdcu, hz); 2267 return(0); /* will return later */ 2268 }; 2269 2270 /* 2271 * write (or format) operation will fall through and 2272 * await completion interrupt 2273 */ 2274#endif 2275 fdc->state = IOCOMPLETE; 2276 fd->tohandle = timeout(fd_iotimeout, fdc, hz); 2277 return (0); /* will return later */ 2278#ifdef EPSON_NRDISK 2279 } 2280 else { 2281 nrdblkn = (nrd_t)((unsigned long)bp->b_blkno*DEV_BSIZE/fdblk 2282 + fd->skip/fdblk); 2283 nrd_LED_on(); 2284 nrd_addrset(fdblk * nrdblkn); 2285 while (!nrd_check_ready()) DELAY(1); 2286 if (read) epson_insw(P_NRD_DATA, 2287 bp->b_data + fd->skip, 2288 fdblk / sizeof(short)); 2289 else epson_outsw(P_NRD_DATA, 2290 bp->b_data + fd->skip, 2291 (format ? bp->b_bcount : fdblk) 2292 / sizeof(short)); 2293 2294 blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/fdblk 2295 + fd->skip/fdblk; 2296 sectrac = fd->ft->sectrac; 2297 sec = blknum % (sectrac * fd->ft->heads); 2298 head = sec / sectrac; 2299 sec = sec % sectrac + 1; 2300 fd->hddrv = ((head&1)<<2)+fdu; 2301 2302 if (nrdsec++ >= nrd_sec()) 2303 nrdaddr = (nrd_t)(fd->track * 8 + head * 4); 2304 nrdsec = sec; 2305 fdc->state = IOCOMPLETE; 2306 } 2307#endif 2308#ifdef FDC_YE 2309 case PIOREAD: 2310 /* 2311 * actually perform the PIO read. The IOCOMPLETE case 2312 * removes the timeout for us. 2313 */ 2314 (void)fdcpio(fdcu,bp->b_flags,bp->b_data+fd->skip,fdblk); 2315 fdc->state = IOCOMPLETE; 2316 /* FALLTHROUGH */ 2317#endif 2318 case IOCOMPLETE: /* IO DONE, post-analyze */ 2319#ifdef EPSON_NRDISK 2320 if (fdu != nrdu) 2321 untimeout(fd_iotimeout, fdc, fd->tohandle); 2322#else 2323 untimeout(fd_iotimeout, fdc, fd->tohandle); 2324#endif 2325 2326 if (fd_read_status(fdc, fd->fdsu)) { 2327 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2328 format ? bp->b_bcount : fdblk, 2329 fdc->dmachan); 2330 if (fdc->retry < 6) 2331 fdc->retry = 6; /* force a reset */ 2332 return (retrier(fdc)); 2333 } 2334 2335 fdc->state = IOTIMEDOUT; 2336 2337 /* FALLTHROUGH */ 2338 2339 case IOTIMEDOUT: 2340#ifdef EPSON_NRDISK 2341 if (fdu != nrdu) { 2342#endif /* EPSON_NRDISK */ 2343#ifdef FDC_YE 2344 if (!(fdc->flags & FDC_PCMCIA)) 2345#endif 2346 isa_dmadone(bp->b_flags, bp->b_data + fd->skip, 2347 format ? bp->b_bcount : fdblk, fdc->dmachan); 2348#ifdef EPSON_NRDISK 2349 } 2350 else nrd_LED_off(); 2351#endif /* EPSON_NRDISK */ 2352 if (fdc->status[0] & NE7_ST0_IC) { 2353 if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT 2354 && fdc->status[1] & NE7_ST1_OR) { 2355 /* 2356 * DMA overrun. Someone hogged the bus 2357 * and didn't release it in time for the 2358 * next FDC transfer. 2359 * Just restart it, don't increment retry 2360 * count. (vak) 2361 */ 2362 fdc->state = SEEKCOMPLETE; 2363 return (1); 2364 } 2365 else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_IV 2366 && fdc->retry < 6) 2367 fdc->retry = 6; /* force a reset */ 2368 else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT 2369 && fdc->status[2] & NE7_ST2_WC 2370 && fdc->retry < 3) 2371 fdc->retry = 3; /* force recalibrate */ 2372 return (retrier(fdc)); 2373 } 2374 /* All OK */ 2375 fd->skip += fdblk; 2376 if (!format && fd->skip < bp->b_bcount - bp->b_resid) { 2377 /* set up next transfer */ 2378 fdc->state = DOSEEK; 2379 } else { 2380 /* ALL DONE */ 2381 fd->skip = 0; 2382 fdc->bp = NULL; 2383 /* Tell devstat we have finished with the transaction */ 2384 devstat_end_transaction(&fd->device_stats, 2385 bp->b_bcount - bp->b_resid, 2386 DEVSTAT_TAG_NONE, 2387 (bp->b_flags & B_READ) ? 2388 DEVSTAT_READ : DEVSTAT_WRITE); 2389 biodone(bp); 2390 fdc->fd = (fd_p) 0; 2391 fdc->fdu = -1; 2392 fdc->state = FINDWORK; 2393 } 2394 return (1); 2395 case RESETCTLR: 2396 fdc_reset(fdc); 2397 fdc->retry++; 2398 fdc->state = RESETCOMPLETE; 2399 return (0); 2400 case RESETCOMPLETE: 2401 /* 2402 * Discard all the results from the reset so that they 2403 * can't cause an unexpected interrupt later. 2404 */ 2405 for (i = 0; i < 4; i++) 2406 (void)fd_sense_int(fdc, &st0, &cyl); 2407 fdc->state = STARTRECAL; 2408 /* Fall through. */ 2409 case STARTRECAL: 2410#ifdef PC98 2411 pc98_fd_check_ready(fdu); 2412#endif 2413 if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) { 2414 /* arrgl */ 2415 fdc->retry = 6; 2416 return (retrier(fdc)); 2417 } 2418 fdc->state = RECALWAIT; 2419 return (0); /* will return later */ 2420 case RECALWAIT: 2421 /* allow heads to settle */ 2422 timeout(fd_pseudointr, fdc, hz / 8); 2423 fdc->state = RECALCOMPLETE; 2424 return (0); /* will return later */ 2425 case RECALCOMPLETE: 2426 do { 2427 /* 2428 * See SEEKCOMPLETE for a comment on this: 2429 */ 2430 if (fd_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID) 2431 return 0; 2432 if(fdc->fdct == FDC_NE765 2433 && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC) 2434 return 0; /* hope for a real intr */ 2435 } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); 2436#ifdef EPSON_NRDISK 2437 if (fdu == nrdu) { 2438 st0 = NE7_ST0_IC_NT; 2439 cyl = 0; 2440 } 2441#endif 2442 if ((st0 & NE7_ST0_IC) != NE7_ST0_IC_NT || cyl != 0) 2443 { 2444 if(fdc->retry > 3) 2445 /* 2446 * a recalibrate from beyond cylinder 77 2447 * will "fail" due to the FDC limitations; 2448 * since people used to complain much about 2449 * the failure message, try not logging 2450 * this one if it seems to be the first 2451 * time in a line 2452 */ 2453 printf("fd%d: recal failed ST0 %b cyl %d\n", 2454 fdu, st0, NE7_ST0BITS, cyl); 2455 if(fdc->retry < 3) fdc->retry = 3; 2456 return (retrier(fdc)); 2457 } 2458 fd->track = 0; 2459 /* Seek (probably) necessary */ 2460 fdc->state = DOSEEK; 2461 return (1); /* will return immediatly */ 2462 case MOTORWAIT: 2463 if(fd->flags & FD_MOTOR_WAIT) 2464 { 2465 return (0); /* time's not up yet */ 2466 } 2467 if (fdc->flags & FDC_NEEDS_RESET) { 2468 fdc->state = RESETCTLR; 2469 fdc->flags &= ~FDC_NEEDS_RESET; 2470 } else { 2471 /* 2472 * If all motors were off, then the controller was 2473 * reset, so it has lost track of the current 2474 * cylinder. Recalibrate to handle this case. 2475 * But first, discard the results of the reset. 2476 */ 2477 fdc->state = RESETCOMPLETE; 2478 } 2479 return (1); /* will return immediatly */ 2480 default: 2481 device_print_prettyname(fdc->fdc_dev); 2482 printf("unexpected FD int->"); 2483 if (fd_read_status(fdc, fd->fdsu) == 0) 2484 printf("FDC status :%x %x %x %x %x %x %x ", 2485 fdc->status[0], 2486 fdc->status[1], 2487 fdc->status[2], 2488 fdc->status[3], 2489 fdc->status[4], 2490 fdc->status[5], 2491 fdc->status[6] ); 2492 else 2493 printf("No status available "); 2494 if (fd_sense_int(fdc, &st0, &cyl) != 0) 2495 { 2496 printf("[controller is dead now]\n"); 2497 return (0); 2498 } 2499 printf("ST0 = %x, PCN = %x\n", st0, cyl); 2500 return (0); 2501 } 2502 /*XXX confusing: some branches return immediately, others end up here*/ 2503 return (1); /* Come back immediatly to new state */ 2504} 2505 2506static int 2507retrier(struct fdc_data *fdc) 2508{ 2509 register struct buf *bp; 2510 struct fd_data *fd; 2511 int fdu; 2512 2513 bp = fdc->bp; 2514 2515 /* XXX shouldn't this be cached somewhere? */ 2516 fdu = FDUNIT(minor(bp->b_dev)); 2517 fd = devclass_get_softc(fd_devclass, fdu); 2518 if (fd->options & FDOPT_NORETRY) 2519 goto fail; 2520 2521 switch (fdc->retry) { 2522 case 0: case 1: case 2: 2523 fdc->state = SEEKCOMPLETE; 2524 break; 2525 case 3: case 4: case 5: 2526 fdc->state = STARTRECAL; 2527 break; 2528 case 6: 2529 fdc->state = RESETCTLR; 2530 break; 2531 case 7: 2532 break; 2533 default: 2534 fail: 2535 { 2536 dev_t sav_b_dev = bp->b_dev; 2537 /* Trick diskerr */ 2538 bp->b_dev = makedev(major(bp->b_dev), 2539 (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART); 2540 diskerr(bp, "fd", "hard error", LOG_PRINTF, 2541 fdc->fd->skip / DEV_BSIZE, 2542 (struct disklabel *)NULL); 2543 bp->b_dev = sav_b_dev; 2544 if (fdc->flags & FDC_STAT_VALID) 2545 { 2546 printf( 2547 " (ST0 %b ST1 %b ST2 %b cyl %u hd %u sec %u)\n", 2548 fdc->status[0], NE7_ST0BITS, 2549 fdc->status[1], NE7_ST1BITS, 2550 fdc->status[2], NE7_ST2BITS, 2551 fdc->status[3], fdc->status[4], 2552 fdc->status[5]); 2553 } 2554 else 2555 printf(" (No status)\n"); 2556 } 2557 bp->b_flags |= B_ERROR; 2558 bp->b_error = EIO; 2559 bp->b_resid += bp->b_bcount - fdc->fd->skip; 2560 fdc->bp = NULL; 2561 2562 /* Tell devstat we have finished with the transaction */ 2563 devstat_end_transaction(&fdc->fd->device_stats, 2564 bp->b_bcount - bp->b_resid, 2565 DEVSTAT_TAG_NONE, 2566 (bp->b_flags & B_READ) ? DEVSTAT_READ : 2567 DEVSTAT_WRITE); 2568 fdc->fd->skip = 0; 2569 biodone(bp); 2570 fdc->state = FINDWORK; 2571 fdc->flags |= FDC_NEEDS_RESET; 2572 fdc->fd = (fd_p) 0; 2573 fdc->fdu = -1; 2574 return (1); 2575 } 2576 fdc->retry++; 2577 return (1); 2578} 2579 2580static int 2581fdformat(dev, finfo, p) 2582 dev_t dev; 2583 struct fd_formb *finfo; 2584 struct proc *p; 2585{ 2586 fdu_t fdu; 2587 fd_p fd; 2588 2589 struct buf *bp; 2590 int rv = 0, s; 2591 size_t fdblk; 2592 2593 fdu = FDUNIT(minor(dev)); 2594 fd = devclass_get_softc(fd_devclass, fdu); 2595 fdblk = 128 << fd->ft->secsize; 2596 2597 /* set up a buffer header for fdstrategy() */ 2598 bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 2599 if(bp == 0) 2600 return ENOBUFS; 2601 /* 2602 * keep the process from being swapped 2603 */ 2604 PHOLD(p); 2605 bzero((void *)bp, sizeof(struct buf));
|