1 /* $NetBSD: fd.c,v 1.39 2002/09/06 13:18:43 gehenna Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Leo Weppelman. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Leo Weppelman. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * This file contains a driver for the Floppy Disk Controller (FDC) 35 * on the Atari TT. It uses the WD 1772 chip, modified for steprates. 36 * 37 * The ST floppy disk controller shares the access to the DMA circuitry 38 * with other devices. For this reason the floppy disk controller makes 39 * use of some special DMA accessing code. 40 * 41 * Interrupts from the FDC are in fact DMA interrupts which get their 42 * first level handling in 'dma.c' . If the floppy driver is currently 43 * using DMA the interrupt is signalled to 'fdcint'. 44 * 45 * TODO: 46 * - Test it with 2 drives (I don't have them) 47 * - Test it with an HD-drive (Don't have that either) 48 * - Finish ioctl's 49 */ 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/callout.h> 54 #include <sys/kernel.h> 55 #include <sys/malloc.h> 56 #include <sys/buf.h> 57 #include <sys/proc.h> 58 #include <sys/device.h> 59 #include <sys/ioctl.h> 60 #include <sys/fcntl.h> 61 #include <sys/conf.h> 62 #include <sys/disklabel.h> 63 #include <sys/disk.h> 64 #include <sys/dkbad.h> 65 #include <atari/atari/device.h> 66 #include <atari/atari/stalloc.h> 67 #include <machine/disklabel.h> 68 #include <machine/iomap.h> 69 #include <machine/mfp.h> 70 #include <machine/dma.h> 71 #include <machine/video.h> 72 #include <machine/cpu.h> 73 #include <atari/dev/ym2149reg.h> 74 #include <atari/dev/fdreg.h> 75 76 /* 77 * Be verbose for debugging 78 */ 79 /*#define FLP_DEBUG 1 */ 80 81 #define FDC_MAX_DMA_AD 0x1000000 /* No DMA possible beyond */ 82 83 /* Parameters for the disk drive. */ 84 #define SECTOR_SIZE 512 /* physical sector size in bytes */ 85 #define NR_DRIVES 2 /* maximum number of drives */ 86 #define NR_TYPES 3 /* number of diskette/drive combinations*/ 87 #define MAX_ERRORS 10 /* how often to try rd/wt before quitting*/ 88 #define STEP_DELAY 6000 /* 6ms (6000us) delay after stepping */ 89 90 91 #define INV_TRK 32000 /* Should fit in unsigned short */ 92 #define INV_PART NR_TYPES 93 94 /* 95 * Driver states 96 */ 97 #define FLP_IDLE 0x00 /* floppy is idle */ 98 #define FLP_MON 0x01 /* idle with motor on */ 99 #define FLP_STAT 0x02 /* determine floppy status */ 100 #define FLP_XFER 0x04 /* read/write data from floppy */ 101 102 /* 103 * Timer delay's 104 */ 105 #define FLP_MONDELAY (3 * hz) /* motor-on delay */ 106 #define FLP_XFERDELAY (2 * hz) /* timeout on transfer */ 107 108 /* 109 * The density codes 110 */ 111 #define FLP_DD 0 /* Double density */ 112 #define FLP_HD 1 /* High density */ 113 114 115 #define b_block b_resid /* FIXME: this is not the place */ 116 117 /* 118 * Global data for all physical floppy devices 119 */ 120 static short selected = 0; /* drive/head currently selected*/ 121 static short motoron = 0; /* motor is spinning */ 122 static short nopens = 0; /* Number of opens executed */ 123 124 static short fd_state = FLP_IDLE; /* Current driver state */ 125 static int lock_stat= 0; /* dma locking status */ 126 static short fd_cmd = 0; /* command being executed */ 127 static char *fd_error= NULL; /* error from fd_xfer_ok() */ 128 129 /* 130 * Private per device data 131 */ 132 struct fd_softc { 133 struct device sc_dv; /* generic device info */ 134 struct disk dkdev; /* generic disk info */ 135 struct bufq_state bufq; /* queue of buf's */ 136 struct callout sc_motor_ch; 137 int unit; /* unit for atari controlling hw*/ 138 int nheads; /* number of heads in use */ 139 int nsectors; /* number of sectors/track */ 140 int density; /* density code */ 141 int nblocks; /* number of blocks on disk */ 142 int curtrk; /* track head positioned on */ 143 short flags; /* misc flags */ 144 short part; /* Current open partition */ 145 int sector; /* logical sector for I/O */ 146 caddr_t io_data; /* KVA for data transfer */ 147 int io_bytes; /* bytes left for I/O */ 148 int io_dir; /* B_READ/B_WRITE */ 149 int errcnt; /* current error count */ 150 u_char *bounceb; /* Bounce buffer */ 151 152 }; 153 154 /* 155 * Flags in fd_softc: 156 */ 157 #define FLPF_NOTRESP 0x001 /* Unit not responding */ 158 #define FLPF_ISOPEN 0x002 /* Unit is open */ 159 #define FLPF_SPARE 0x004 /* Not used */ 160 #define FLPF_HAVELAB 0x008 /* We have a valid label */ 161 #define FLPF_BOUNCE 0x010 /* Now using the bounce buffer */ 162 #define FLPF_WRTPROT 0x020 /* Unit is write-protected */ 163 #define FLPF_EMPTY 0x040 /* Unit is empty */ 164 #define FLPF_INOPEN 0x080 /* Currently being opened */ 165 #define FLPF_GETSTAT 0x100 /* Getting unit status */ 166 167 struct fd_types { 168 int nheads; /* Heads in use */ 169 int nsectors; /* sectors per track */ 170 int nblocks; /* number of blocks */ 171 int density; /* density code */ 172 const char *descr; /* type description */ 173 } fdtypes[NR_TYPES] = { 174 { 1, 9, 720 , FLP_DD , "360KB" }, /* 360 Kb */ 175 { 2, 9, 1440 , FLP_DD , "720KB" }, /* 720 Kb */ 176 { 2, 18, 2880 , FLP_HD , "1.44MB" }, /* 1.44 Mb */ 177 }; 178 179 #define FLP_TYPE_360 0 /* XXX: Please keep these in */ 180 #define FLP_TYPE_720 1 /* sync with the numbering in */ 181 #define FLP_TYPE_144 2 /* 'fdtypes' right above! */ 182 183 /* 184 * This is set only once at attach time. The value is determined by reading 185 * the configuration switches and is one of the FLP_TYPE_*'s. 186 * This is simular to the way Atari handles the _FLP cookie. 187 */ 188 static short def_type = 0; /* Reflects config-switches */ 189 190 #define FLP_DEFTYPE 1 /* 720Kb, reasonable default */ 191 #define FLP_TYPE(dev) ( DISKPART(dev) == 0 ? def_type : DISKPART(dev) - 1 ) 192 193 typedef void (*FPV) __P((void *)); 194 195 dev_type_open(fdopen); 196 dev_type_close(fdclose); 197 dev_type_read(fdread); 198 dev_type_write(fdwrite); 199 dev_type_ioctl(fdioctl); 200 dev_type_strategy(fdstrategy); 201 202 /* 203 * Private drive functions.... 204 */ 205 static void fdstart __P((struct fd_softc *)); 206 static void fddone __P((struct fd_softc *)); 207 static void fdstatus __P((struct fd_softc *)); 208 static void fd_xfer __P((struct fd_softc *)); 209 static void fdcint __P((struct fd_softc *)); 210 static int fd_xfer_ok __P((struct fd_softc *)); 211 static void fdmotoroff __P((struct fd_softc *)); 212 static void fdminphys __P((struct buf *)); 213 static void fdtestdrv __P((struct fd_softc *)); 214 static void fdgetdefaultlabel __P((struct fd_softc *, struct disklabel *, 215 int)); 216 static int fdgetdisklabel __P((struct fd_softc *, dev_t)); 217 static int fdselect __P((int, int, int)); 218 static void fddeselect __P((void)); 219 static void fdmoff __P((struct fd_softc *)); 220 u_char read_fdreg __P((u_short)); 221 void write_fdreg __P((u_short, u_short)); 222 u_char read_dmastat __P((void)); 223 224 extern __inline__ u_char read_fdreg(u_short regno) 225 { 226 DMA->dma_mode = regno; 227 return(DMA->dma_data); 228 } 229 230 extern __inline__ void write_fdreg(u_short regno, u_short val) 231 { 232 DMA->dma_mode = regno; 233 DMA->dma_data = val; 234 } 235 236 extern __inline__ u_char read_dmastat(void) 237 { 238 DMA->dma_mode = FDC_CS | DMA_SCREG; 239 return(DMA->dma_stat); 240 } 241 242 /* 243 * Config switch stuff. Used only for the floppy type for now. That's 244 * why it's here... 245 * XXX: If needed in more places, it should be moved to it's own include file. 246 * Note: This location _must_ be read as an u_short. Failure to do so 247 * will return garbage! 248 */ 249 static u_short rd_cfg_switch __P((void)); 250 static u_short rd_cfg_switch(void) 251 { 252 return(*((u_short*)AD_CFG_SWITCH)); 253 } 254 255 /* 256 * Switch definitions. 257 * Note: ON reads as a zero bit! 258 */ 259 #define CFG_SWITCH_NOHD 0x4000 260 261 /* 262 * Autoconfig stuff.... 263 */ 264 extern struct cfdriver fd_cd; 265 266 static int fdcmatch __P((struct device *, struct cfdata *, void *)); 267 static int fdcprint __P((void *, const char *)); 268 static void fdcattach __P((struct device *, struct device *, void *)); 269 270 struct cfattach fdc_ca = { 271 sizeof(struct device), fdcmatch, fdcattach 272 }; 273 274 const struct bdevsw fd_bdevsw = { 275 fdopen, fdclose, fdstrategy, fdioctl, nodump, nosize, D_DISK 276 }; 277 278 const struct cdevsw fd_cdevsw = { 279 fdopen, fdclose, fdread, fdwrite, fdioctl, 280 nostop, notty, nopoll, nommap, D_DISK 281 }; 282 283 static int 284 fdcmatch(pdp, cfp, auxp) 285 struct device *pdp; 286 struct cfdata *cfp; 287 void *auxp; 288 { 289 static int fdc_matched = 0; 290 291 /* Match only once */ 292 if(strcmp("fdc", auxp) || fdc_matched) 293 return(0); 294 fdc_matched = 1; 295 return(1); 296 } 297 298 static void 299 fdcattach(pdp, dp, auxp) 300 struct device *pdp, *dp; 301 void *auxp; 302 { 303 struct fd_softc fdsoftc; 304 int i, nfound, first_found; 305 306 nfound = first_found = 0; 307 printf("\n"); 308 fddeselect(); 309 for(i = 0; i < NR_DRIVES; i++) { 310 311 /* 312 * Test if unit is present 313 */ 314 fdsoftc.unit = i; 315 fdsoftc.flags = 0; 316 st_dmagrab((dma_farg)fdcint, (dma_farg)fdtestdrv, &fdsoftc, 317 &lock_stat, 0); 318 st_dmafree(&fdsoftc, &lock_stat); 319 320 if(!(fdsoftc.flags & FLPF_NOTRESP)) { 321 if(!nfound) 322 first_found = i; 323 nfound++; 324 config_found(dp, (void*)i, fdcprint); 325 } 326 } 327 328 if(nfound) { 329 struct fd_softc *fdsc = getsoftc(fd_cd, first_found); 330 331 /* 332 * Make sure motor will be turned of when a floppy is 333 * inserted in the first selected drive. 334 */ 335 fdselect(first_found, 0, FLP_DD); 336 fd_state = FLP_MON; 337 callout_reset(&fdsc->sc_motor_ch, 0, (FPV)fdmotoroff, fdsc); 338 339 /* 340 * enable disk related interrupts 341 */ 342 MFP->mf_ierb |= IB_DINT; 343 MFP->mf_iprb = (u_int8_t)~IB_DINT; 344 MFP->mf_imrb |= IB_DINT; 345 } 346 } 347 348 static int 349 fdcprint(auxp, pnp) 350 void *auxp; 351 const char *pnp; 352 { 353 if (pnp != NULL) 354 printf("fd%d at %s:", (int)auxp, pnp); 355 356 return(UNCONF); 357 } 358 359 static int fdmatch __P((struct device *, struct cfdata *, void *)); 360 static void fdattach __P((struct device *, struct device *, void *)); 361 362 struct dkdriver fddkdriver = { fdstrategy }; 363 364 struct cfattach fd_ca = { 365 sizeof(struct fd_softc), fdmatch, fdattach 366 }; 367 368 extern struct cfdriver fd_cd; 369 370 static int 371 fdmatch(pdp, cfp, auxp) 372 struct device *pdp; 373 struct cfdata *cfp; 374 void *auxp; 375 { 376 return(1); 377 } 378 379 static void 380 fdattach(pdp, dp, auxp) 381 struct device *pdp, *dp; 382 void *auxp; 383 { 384 struct fd_softc *sc; 385 struct fd_types *type; 386 u_short swtch; 387 388 sc = (struct fd_softc *)dp; 389 390 callout_init(&sc->sc_motor_ch); 391 392 /* 393 * Find out if an Ajax chip might be installed. Set the default 394 * floppy type accordingly. 395 */ 396 swtch = rd_cfg_switch(); 397 def_type = (swtch & CFG_SWITCH_NOHD) ? FLP_TYPE_720 : FLP_TYPE_144; 398 type = &fdtypes[def_type]; 399 400 printf(": %s %d cyl, %d head, %d sec\n", type->descr, 401 type->nblocks / (type->nsectors * type->nheads), type->nheads, 402 type->nsectors); 403 404 /* 405 * Initialize and attach the disk structure. 406 */ 407 sc->dkdev.dk_name = sc->sc_dv.dv_xname; 408 sc->dkdev.dk_driver = &fddkdriver; 409 disk_attach(&sc->dkdev); 410 } 411 412 int 413 fdioctl(dev, cmd, addr, flag, p) 414 dev_t dev; 415 u_long cmd; 416 int flag; 417 caddr_t addr; 418 struct proc *p; 419 { 420 struct fd_softc *sc; 421 422 sc = getsoftc(fd_cd, DISKUNIT(dev)); 423 424 if((sc->flags & FLPF_HAVELAB) == 0) 425 return(EBADF); 426 427 switch(cmd) { 428 case DIOCSBAD: 429 return(EINVAL); 430 case DIOCGDINFO: 431 *(struct disklabel *)addr = *(sc->dkdev.dk_label); 432 return(0); 433 case DIOCGPART: 434 ((struct partinfo *)addr)->disklab = 435 sc->dkdev.dk_label; 436 ((struct partinfo *)addr)->part = 437 &sc->dkdev.dk_label->d_partitions[RAW_PART]; 438 return(0); 439 #ifdef notyet /* XXX LWP */ 440 case DIOCSRETRIES: 441 case DIOCSSTEP: 442 case DIOCSDINFO: 443 case DIOCWDINFO: 444 case DIOCWLABEL: 445 break; 446 #endif /* notyet */ 447 case DIOCGDEFLABEL: 448 fdgetdefaultlabel(sc, (struct disklabel *)addr, 449 RAW_PART); 450 return(0); 451 } 452 return(ENOTTY); 453 } 454 455 /* 456 * Open the device. If this is the first open on both the floppy devices, 457 * intialize the controller. 458 * Note that partition info on the floppy device is used to distinguise 459 * between 780Kb and 360Kb floppy's. 460 * partition 0: 360Kb 461 * partition 1: 780Kb 462 */ 463 int 464 fdopen(dev, flags, devtype, proc) 465 dev_t dev; 466 int flags, devtype; 467 struct proc *proc; 468 { 469 struct fd_softc *sc; 470 int sps; 471 472 #ifdef FLP_DEBUG 473 printf("fdopen dev=0x%x\n", dev); 474 #endif 475 476 if(FLP_TYPE(dev) >= NR_TYPES) 477 return(ENXIO); 478 479 if((sc = getsoftc(fd_cd, DISKUNIT(dev))) == NULL) 480 return(ENXIO); 481 482 /* 483 * If no floppy currently open, reset the controller and select 484 * floppy type. 485 */ 486 if(!nopens) { 487 488 #ifdef FLP_DEBUG 489 printf("fdopen device not yet open\n"); 490 #endif 491 nopens++; 492 write_fdreg(FDC_CS, IRUPT); 493 delay(40); 494 } 495 496 /* 497 * Sleep while other process is opening the device 498 */ 499 sps = splbio(); 500 while(sc->flags & FLPF_INOPEN) 501 tsleep((caddr_t)sc, PRIBIO, "fdopen", 0); 502 splx(sps); 503 504 if(!(sc->flags & FLPF_ISOPEN)) { 505 /* 506 * Initialise some driver values. 507 */ 508 int type; 509 void *addr; 510 511 type = FLP_TYPE(dev); 512 513 bufq_alloc(&sc->bufq, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK); 514 sc->unit = DISKUNIT(dev); 515 sc->part = RAW_PART; 516 sc->nheads = fdtypes[type].nheads; 517 sc->nsectors = fdtypes[type].nsectors; 518 sc->nblocks = fdtypes[type].nblocks; 519 sc->density = fdtypes[type].density; 520 sc->curtrk = INV_TRK; 521 sc->sector = 0; 522 sc->errcnt = 0; 523 sc->bounceb = (u_char*)alloc_stmem(SECTOR_SIZE, &addr); 524 if(sc->bounceb == NULL) 525 return(ENOMEM); /* XXX */ 526 527 /* 528 * Go get write protect + loaded status 529 */ 530 sc->flags |= FLPF_INOPEN|FLPF_GETSTAT; 531 sps = splbio(); 532 st_dmagrab((dma_farg)fdcint, (dma_farg)fdstatus, sc, 533 &lock_stat, 0); 534 while(sc->flags & FLPF_GETSTAT) 535 tsleep((caddr_t)sc, PRIBIO, "fdopen", 0); 536 splx(sps); 537 wakeup((caddr_t)sc); 538 539 if((sc->flags & FLPF_WRTPROT) && (flags & FWRITE)) { 540 sc->flags = 0; 541 return(EPERM); 542 } 543 if(sc->flags & FLPF_EMPTY) { 544 sc->flags = 0; 545 return(ENXIO); 546 } 547 sc->flags &= ~(FLPF_INOPEN|FLPF_GETSTAT); 548 sc->flags |= FLPF_ISOPEN; 549 } 550 else { 551 /* 552 * Multiply opens are granted when accessing the same type of 553 * floppy (eq. the same partition). 554 */ 555 if(sc->density != fdtypes[DISKPART(dev)].density) 556 return(ENXIO); /* XXX temporarely out of business */ 557 } 558 fdgetdisklabel(sc, dev); 559 #ifdef FLP_DEBUG 560 printf("fdopen open succeeded on type %d\n", sc->part); 561 #endif 562 return (0); 563 } 564 565 int 566 fdclose(dev, flags, devtype, proc) 567 dev_t dev; 568 int flags, devtype; 569 struct proc *proc; 570 { 571 struct fd_softc *sc; 572 573 sc = getsoftc(fd_cd, DISKUNIT(dev)); 574 free_stmem(sc->bounceb); 575 sc->flags = 0; 576 nopens--; 577 578 #ifdef FLP_DEBUG 579 printf("Closed floppy device -- nopens: %d\n", nopens); 580 #endif 581 return(0); 582 } 583 584 void 585 fdstrategy(bp) 586 struct buf *bp; 587 { 588 struct fd_softc *sc; 589 struct disklabel *lp; 590 int sps, sz; 591 592 sc = getsoftc(fd_cd, DISKUNIT(bp->b_dev)); 593 594 #ifdef FLP_DEBUG 595 printf("fdstrategy: %p, b_bcount: %ld\n", bp, bp->b_bcount); 596 #endif 597 598 /* 599 * check for valid partition and bounds 600 */ 601 lp = sc->dkdev.dk_label; 602 if ((sc->flags & FLPF_HAVELAB) == 0) { 603 bp->b_error = EIO; 604 goto bad; 605 } 606 if (bp->b_blkno < 0 || (bp->b_bcount % SECTOR_SIZE)) { 607 bp->b_error = EINVAL; 608 goto bad; 609 } 610 if (bp->b_bcount == 0) 611 goto done; 612 613 sz = howmany(bp->b_bcount, SECTOR_SIZE); 614 615 if (bp->b_blkno + sz > sc->nblocks) { 616 sz = sc->nblocks - bp->b_blkno; 617 if (sz == 0) /* Exactly at EndOfDisk */ 618 goto done; 619 if (sz < 0) { /* Past EndOfDisk */ 620 bp->b_error = EINVAL; 621 goto bad; 622 } 623 /* Trucate it */ 624 if (bp->b_flags & B_RAW) 625 bp->b_bcount = sz << DEV_BSHIFT; 626 else bp->b_bcount = sz * lp->d_secsize; 627 } 628 629 /* No partition translation. */ 630 bp->b_rawblkno = bp->b_blkno; 631 632 /* 633 * queue the buf and kick the low level code 634 */ 635 sps = splbio(); 636 BUFQ_PUT(&sc->bufq, bp); /* XXX disksort_cylinder */ 637 if (!lock_stat) { 638 if (fd_state & FLP_MON) 639 callout_stop(&sc->sc_motor_ch); 640 fd_state = FLP_IDLE; 641 st_dmagrab((dma_farg)fdcint, (dma_farg)fdstart, sc, 642 &lock_stat, 0); 643 } 644 splx(sps); 645 646 return; 647 bad: 648 bp->b_flags |= B_ERROR; 649 done: 650 bp->b_resid = bp->b_bcount; 651 biodone(bp); 652 } 653 654 int 655 fdread(dev, uio, flags) 656 dev_t dev; 657 struct uio *uio; 658 int flags; 659 { 660 return(physio(fdstrategy, NULL, dev, B_READ, fdminphys, uio)); 661 } 662 663 int 664 fdwrite(dev, uio, flags) 665 dev_t dev; 666 struct uio *uio; 667 int flags; 668 { 669 return(physio(fdstrategy, NULL, dev, B_WRITE, fdminphys, uio)); 670 } 671 672 /* 673 * Called through DMA-dispatcher, get status. 674 */ 675 static void 676 fdstatus(sc) 677 struct fd_softc *sc; 678 { 679 #ifdef FLP_DEBUG 680 printf("fdstatus\n"); 681 #endif 682 sc->errcnt = 0; 683 fd_state = FLP_STAT; 684 fd_xfer(sc); 685 } 686 687 /* 688 * Called through the dma-dispatcher. So we know we are the only ones 689 * messing with the floppy-controler. 690 * Initialize some fields in the fdsoftc for the state-machine and get 691 * it going. 692 */ 693 static void 694 fdstart(sc) 695 struct fd_softc *sc; 696 { 697 struct buf *bp; 698 699 bp = BUFQ_PEEK(&sc->bufq); 700 sc->sector = bp->b_blkno; /* Start sector for I/O */ 701 sc->io_data = bp->b_data; /* KVA base for I/O */ 702 sc->io_bytes = bp->b_bcount; /* Transfer size in bytes */ 703 sc->io_dir = bp->b_flags & B_READ;/* Direction of transfer */ 704 sc->errcnt = 0; /* No errors yet */ 705 fd_state = FLP_XFER; /* Yes, we're going to transfer */ 706 707 /* Instrumentation. */ 708 disk_busy(&sc->dkdev); 709 710 fd_xfer(sc); 711 } 712 713 /* 714 * The current transaction is finished (for good or bad). Let go of 715 * the dma-resources. Call biodone() to finish the transaction. 716 * Find a new transaction to work on. 717 */ 718 static void 719 fddone(sc) 720 register struct fd_softc *sc; 721 { 722 struct buf *bp; 723 struct fd_softc *sc1; 724 int i, sps; 725 726 /* 727 * Give others a chance to use the dma. 728 */ 729 st_dmafree(sc, &lock_stat); 730 731 732 if(fd_state != FLP_STAT) { 733 /* 734 * Finish current transaction. 735 */ 736 sps = splbio(); 737 bp = BUFQ_GET(&sc->bufq); 738 if (bp == NULL) 739 panic("fddone"); 740 splx(sps); 741 742 #ifdef FLP_DEBUG 743 printf("fddone: unit: %d, buf: %p, resid: %d\n",sc->unit,bp, 744 sc->io_bytes); 745 #endif 746 bp->b_resid = sc->io_bytes; 747 748 disk_unbusy(&sc->dkdev, (bp->b_bcount - bp->b_resid)); 749 750 biodone(bp); 751 } 752 fd_state = FLP_MON; 753 754 if(lock_stat) 755 return; /* XXX Is this possible? */ 756 757 /* 758 * Find a new transaction on round-robin basis. 759 */ 760 for(i = sc->unit + 1; ;i++) { 761 if(i >= fd_cd.cd_ndevs) 762 i = 0; 763 if((sc1 = fd_cd.cd_devs[i]) == NULL) 764 continue; 765 if (BUFQ_PEEK(&sc1->bufq) != NULL) 766 break; 767 if(i == sc->unit) { 768 callout_reset(&sc->sc_motor_ch, FLP_MONDELAY, 769 (FPV)fdmotoroff, sc); 770 #ifdef FLP_DEBUG 771 printf("fddone: Nothing to do\n"); 772 #endif 773 return; /* No work */ 774 } 775 } 776 fd_state = FLP_IDLE; 777 #ifdef FLP_DEBUG 778 printf("fddone: Staring job on unit %d\n", sc1->unit); 779 #endif 780 st_dmagrab((dma_farg)fdcint, (dma_farg)fdstart, sc1, &lock_stat, 0); 781 } 782 783 static int 784 fdselect(drive, head, dense) 785 int drive, head, dense; 786 { 787 int i, spinning; 788 #ifdef FLP_DEBUG 789 printf("fdselect: drive=%d, head=%d, dense=%d\n", drive, head, dense); 790 #endif 791 i = ((drive == 1) ? PA_FLOP1 : PA_FLOP0) | head; 792 spinning = motoron; 793 motoron = 1; 794 795 switch(dense) { 796 case FLP_DD: 797 DMA->dma_drvmode = 0; 798 break; 799 case FLP_HD: 800 DMA->dma_drvmode = (FDC_HDSET|FDC_HDSIG); 801 break; 802 default: 803 panic("fdselect: unknown density code\n"); 804 } 805 if(i != selected) { 806 selected = i; 807 ym2149_fd_select((i ^ PA_FDSEL)); 808 } 809 return(spinning); 810 } 811 812 static void 813 fddeselect() 814 { 815 ym2149_fd_select(PA_FDSEL); 816 motoron = selected = 0; 817 DMA->dma_drvmode = 0; 818 } 819 820 /**************************************************************************** 821 * The following functions assume to be running as a result of a * 822 * disk-interrupt (e.q. spl = splbio). * 823 * They form the finit-state machine, the actual driver. * 824 * * 825 * fdstart()/ --> fd_xfer() -> activate hardware * 826 * fdopen() ^ * 827 * | * 828 * +-- not ready -<------------+ * 829 * | * 830 * fdmotoroff()/ --> fdcint() -> fd_xfer_ok() ---+ * 831 * h/w interrupt | * 832 * \|/ * 833 * finished ---> fdone() * 834 * * 835 ****************************************************************************/ 836 static void 837 fd_xfer(sc) 838 struct fd_softc *sc; 839 { 840 register int head; 841 register int track, sector, hbit; 842 u_long phys_addr; 843 844 head = track = 0; 845 switch(fd_state) { 846 case FLP_XFER: 847 /* 848 * Calculate head/track values 849 */ 850 track = sc->sector / sc->nsectors; 851 head = track % sc->nheads; 852 track = track / sc->nheads; 853 #ifdef FLP_DEBUG 854 printf("fd_xfer: sector:%d,head:%d,track:%d\n", sc->sector,head, 855 track); 856 #endif 857 break; 858 859 case FLP_STAT: 860 /* 861 * FLP_STAT only wants to recalibrate 862 */ 863 sc->curtrk = INV_TRK; 864 break; 865 default: 866 panic("fd_xfer: wrong state (0x%x)", fd_state); 867 } 868 869 /* 870 * Select the drive. 871 */ 872 hbit = fdselect(sc->unit, head, sc->density) ? HBIT : 0; 873 874 if(sc->curtrk == INV_TRK) { 875 /* 876 * Recalibrate, since we lost track of head positioning. 877 * The floppy disk controller has no way of determining its 878 * absolute arm position (track). Instead, it steps the 879 * arm a track at a time and keeps track of where it 880 * thinks it is (in software). However, after a SEEK, the 881 * hardware reads information from the diskette telling 882 * where the arm actually is. If the arm is in the wrong place, 883 * a recalibration is done, which forces the arm to track 0. 884 * This way the controller can get back into sync with reality. 885 */ 886 fd_cmd = RESTORE; 887 write_fdreg(FDC_CS, RESTORE|VBIT|hbit); 888 callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY, 889 (FPV)fdmotoroff, sc); 890 891 #ifdef FLP_DEBUG 892 printf("fd_xfer:Recalibrating drive %d\n", sc->unit); 893 #endif 894 return; 895 } 896 897 write_fdreg(FDC_TR, sc->curtrk); 898 899 /* 900 * Issue a SEEK command on the indicated drive unless the arm is 901 * already positioned on the correct track. 902 */ 903 if(track != sc->curtrk) { 904 sc->curtrk = track; /* be optimistic */ 905 write_fdreg(FDC_DR, track); 906 write_fdreg(FDC_CS, SEEK|RATE6|VBIT|hbit); 907 callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY, 908 (FPV)fdmotoroff, sc); 909 fd_cmd = SEEK; 910 #ifdef FLP_DEBUG 911 printf("fd_xfer:Seek to track %d on drive %d\n",track,sc->unit); 912 #endif 913 return; 914 } 915 916 /* 917 * The drive is now on the proper track. Read or write 1 block. 918 */ 919 sector = sc->sector % sc->nsectors; 920 sector++; /* start numbering at 1 */ 921 922 write_fdreg(FDC_SR, sector); 923 924 phys_addr = (u_long)kvtop(sc->io_data); 925 if(phys_addr >= FDC_MAX_DMA_AD) { 926 /* 927 * We _must_ bounce this address 928 */ 929 phys_addr = (u_long)kvtop(sc->bounceb); 930 if(sc->io_dir == B_WRITE) 931 bcopy(sc->io_data, sc->bounceb, SECTOR_SIZE); 932 sc->flags |= FLPF_BOUNCE; 933 } 934 st_dmaaddr_set((caddr_t)phys_addr); /* DMA address setup */ 935 936 #ifdef FLP_DEBUG 937 printf("fd_xfer:Start io (io_addr:%lx)\n", (u_long)kvtop(sc->io_data)); 938 #endif 939 940 if(sc->io_dir == B_READ) { 941 /* Issue the command */ 942 st_dmacomm(DMA_FDC | DMA_SCREG, 1); 943 write_fdreg(FDC_CS, F_READ|hbit); 944 fd_cmd = F_READ; 945 } 946 else { 947 /* Issue the command */ 948 st_dmacomm(DMA_WRBIT | DMA_FDC | DMA_SCREG, 1); 949 write_fdreg(DMA_WRBIT | FDC_CS, F_WRITE|hbit|EBIT|PBIT); 950 fd_cmd = F_WRITE; 951 } 952 callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY, (FPV)fdmotoroff, sc); 953 } 954 955 /* return values of fd_xfer_ok(): */ 956 #define X_OK 0 957 #define X_AGAIN 1 958 #define X_ERROR 2 959 #define X_FAIL 3 960 961 /* 962 * Hardware interrupt function. 963 */ 964 static void 965 fdcint(sc) 966 struct fd_softc *sc; 967 { 968 struct buf *bp; 969 970 #ifdef FLP_DEBUG 971 printf("fdcint: unit = %d\n", sc->unit); 972 #endif 973 974 /* 975 * Cancel timeout (we made it, didn't we) 976 */ 977 callout_stop(&sc->sc_motor_ch); 978 979 switch(fd_xfer_ok(sc)) { 980 case X_ERROR : 981 if(++(sc->errcnt) < MAX_ERRORS) { 982 /* 983 * Command failed but still retries left. 984 */ 985 break; 986 } 987 /* FALL THROUGH */ 988 case X_FAIL : 989 /* 990 * Non recoverable error. Fall back to motor-on 991 * idle-state. 992 */ 993 if(fd_error != NULL) { 994 printf("Floppy error: %s\n", fd_error); 995 fd_error = NULL; 996 } 997 998 if(fd_state == FLP_STAT) { 999 sc->flags |= FLPF_EMPTY; 1000 sc->flags &= ~FLPF_GETSTAT; 1001 wakeup((caddr_t)sc); 1002 fddone(sc); 1003 return; 1004 } 1005 1006 bp = BUFQ_PEEK(&sc->bufq); 1007 1008 bp->b_error = EIO; 1009 bp->b_flags |= B_ERROR; 1010 fd_state = FLP_MON; 1011 1012 break; 1013 case X_AGAIN: 1014 /* 1015 * Start next part of state machine. 1016 */ 1017 break; 1018 case X_OK: 1019 /* 1020 * Command ok and finished. Reset error-counter. 1021 * If there are no more bytes to transfer fall back 1022 * to motor-on idle state. 1023 */ 1024 sc->errcnt = 0; 1025 1026 if(fd_state == FLP_STAT) { 1027 sc->flags &= ~FLPF_GETSTAT; 1028 wakeup((caddr_t)sc); 1029 fddone(sc); 1030 return; 1031 } 1032 1033 if((sc->flags & FLPF_BOUNCE) && (sc->io_dir == B_READ)) 1034 bcopy(sc->bounceb, sc->io_data, SECTOR_SIZE); 1035 sc->flags &= ~FLPF_BOUNCE; 1036 1037 sc->sector++; 1038 sc->io_data += SECTOR_SIZE; 1039 sc->io_bytes -= SECTOR_SIZE; 1040 if(sc->io_bytes <= 0) 1041 fd_state = FLP_MON; 1042 } 1043 if(fd_state == FLP_MON) 1044 fddone(sc); 1045 else fd_xfer(sc); 1046 } 1047 1048 /* 1049 * Determine status of last command. Should only be called through 1050 * 'fdcint()'. 1051 * Returns: 1052 * X_ERROR : Error on command; might succeed next time. 1053 * X_FAIL : Error on command; will never succeed. 1054 * X_AGAIN : Part of a command succeeded, call 'fd_xfer()' to complete. 1055 * X_OK : Command succeeded and is complete. 1056 * 1057 * This function only affects sc->curtrk. 1058 */ 1059 static int 1060 fd_xfer_ok(sc) 1061 register struct fd_softc *sc; 1062 { 1063 register int status; 1064 1065 #ifdef FLP_DEBUG 1066 printf("fd_xfer_ok: cmd: 0x%x, state: 0x%x\n", fd_cmd, fd_state); 1067 #endif 1068 switch(fd_cmd) { 1069 case IRUPT: 1070 /* 1071 * Timeout. Force a recalibrate before we try again. 1072 */ 1073 status = read_fdreg(FDC_CS); 1074 1075 fd_error = "Timeout"; 1076 sc->curtrk = INV_TRK; 1077 return(X_ERROR); 1078 case F_READ: 1079 /* 1080 * Test for DMA error 1081 */ 1082 status = read_dmastat(); 1083 if(!(status & DMAOK)) { 1084 fd_error = "Dma error"; 1085 return(X_ERROR); 1086 } 1087 /* 1088 * Get controller status and check for errors. 1089 */ 1090 status = read_fdreg(FDC_CS); 1091 if(status & (RNF | CRCERR | LD_T00)) { 1092 fd_error = "Read error"; 1093 if(status & RNF) 1094 sc->curtrk = INV_TRK; 1095 return(X_ERROR); 1096 } 1097 break; 1098 case F_WRITE: 1099 /* 1100 * Test for DMA error 1101 */ 1102 status = read_dmastat(); 1103 if(!(status & DMAOK)) { 1104 fd_error = "Dma error"; 1105 return(X_ERROR); 1106 } 1107 /* 1108 * Get controller status and check for errors. 1109 */ 1110 status = read_fdreg(FDC_CS); 1111 if(status & WRI_PRO) { 1112 fd_error = "Write protected"; 1113 return(X_FAIL); 1114 } 1115 if(status & (RNF | CRCERR | LD_T00)) { 1116 fd_error = "Write error"; 1117 sc->curtrk = INV_TRK; 1118 return(X_ERROR); 1119 } 1120 break; 1121 case SEEK: 1122 status = read_fdreg(FDC_CS); 1123 if(status & (RNF | CRCERR)) { 1124 fd_error = "Seek error"; 1125 sc->curtrk = INV_TRK; 1126 return(X_ERROR); 1127 } 1128 return(X_AGAIN); 1129 case RESTORE: 1130 /* 1131 * Determine if the recalibration succeeded. 1132 */ 1133 status = read_fdreg(FDC_CS); 1134 if(status & RNF) { 1135 fd_error = "Recalibrate error"; 1136 /* reset controller */ 1137 write_fdreg(FDC_CS, IRUPT); 1138 sc->curtrk = INV_TRK; 1139 return(X_ERROR); 1140 } 1141 sc->curtrk = 0; 1142 if(fd_state == FLP_STAT) { 1143 if(status & WRI_PRO) 1144 sc->flags |= FLPF_WRTPROT; 1145 break; 1146 } 1147 return(X_AGAIN); 1148 default: 1149 fd_error = "Driver error: fd_xfer_ok : Unknown state"; 1150 return(X_FAIL); 1151 } 1152 return(X_OK); 1153 } 1154 1155 /* 1156 * All timeouts will call this function. 1157 */ 1158 static void 1159 fdmotoroff(sc) 1160 struct fd_softc *sc; 1161 { 1162 int sps; 1163 1164 /* 1165 * Get at harware interrupt level 1166 */ 1167 sps = splbio(); 1168 1169 #if FLP_DEBUG 1170 printf("fdmotoroff, state = 0x%x\n", fd_state); 1171 #endif 1172 1173 switch(fd_state) { 1174 case FLP_STAT : 1175 case FLP_XFER : 1176 /* 1177 * Timeout during a transfer; cancel transaction 1178 * set command to 'IRUPT'. 1179 * A drive-interrupt is simulated to trigger the state 1180 * machine. 1181 */ 1182 /* 1183 * Cancel current transaction 1184 */ 1185 fd_cmd = IRUPT; 1186 write_fdreg(FDC_CS, IRUPT); 1187 delay(20); 1188 (void)read_fdreg(FDC_CS); 1189 write_fdreg(FDC_CS, RESTORE); 1190 break; 1191 1192 case FLP_MON : 1193 /* 1194 * Turn motor off. 1195 */ 1196 if(selected) { 1197 int tmp; 1198 1199 st_dmagrab((dma_farg)fdcint, (dma_farg)fdmoff, 1200 sc, &tmp, 0); 1201 } 1202 else fd_state = FLP_IDLE; 1203 break; 1204 } 1205 splx(sps); 1206 } 1207 1208 /* 1209 * min byte count to whats left of the track in question 1210 */ 1211 static void 1212 fdminphys(bp) 1213 struct buf *bp; 1214 { 1215 struct fd_softc *sc; 1216 int sec, toff, tsz; 1217 1218 if((sc = getsoftc(fd_cd, DISKUNIT(bp->b_dev))) == NULL) 1219 panic("fdminphys: couldn't get softc"); 1220 1221 sec = bp->b_blkno % (sc->nsectors * sc->nheads); 1222 toff = sec * SECTOR_SIZE; 1223 tsz = sc->nsectors * sc->nheads * SECTOR_SIZE; 1224 1225 #ifdef FLP_DEBUG 1226 printf("fdminphys: before %ld", bp->b_bcount); 1227 #endif 1228 1229 bp->b_bcount = min(bp->b_bcount, tsz - toff); 1230 1231 #ifdef FLP_DEBUG 1232 printf(" after %ld\n", bp->b_bcount); 1233 #endif 1234 1235 minphys(bp); 1236 } 1237 1238 /* 1239 * Called from fdmotoroff to turn the motor actually off.... 1240 * This can't be done in fdmotoroff itself, because exclusive access to the 1241 * DMA controller is needed to read the FDC-status register. The function 1242 * 'fdmoff()' always runs as the result of a 'dmagrab()'. 1243 * We need to test the status-register because we want to be sure that the 1244 * drive motor is really off before deselecting the drive. The FDC only 1245 * turns off the drive motor after having seen 10 index-pulses. You only 1246 * get index-pulses when a drive is selected....This means that if the 1247 * drive is deselected when the motor is still spinning, it will continue 1248 * to spin _even_ when you insert a floppy later on... 1249 */ 1250 static void 1251 fdmoff(fdsoftc) 1252 struct fd_softc *fdsoftc; 1253 { 1254 int tmp; 1255 1256 if ((fd_state == FLP_MON) && selected) { 1257 tmp = read_fdreg(FDC_CS); 1258 if (!(tmp & MOTORON)) { 1259 fddeselect(); 1260 fd_state = FLP_IDLE; 1261 } 1262 else 1263 callout_reset(&fdsoftc->sc_motor_ch, 10*FLP_MONDELAY, 1264 (FPV)fdmotoroff, fdsoftc); 1265 } 1266 st_dmafree(fdsoftc, &tmp); 1267 } 1268 1269 /* 1270 * Used to find out wich drives are actually connected. We do this by issuing 1271 * is 'RESTORE' command and check if the 'track-0' bit is set. This also works 1272 * if the drive is present but no floppy is inserted. 1273 */ 1274 static void 1275 fdtestdrv(fdsoftc) 1276 struct fd_softc *fdsoftc; 1277 { 1278 int status; 1279 1280 /* 1281 * Select the right unit and head. 1282 */ 1283 fdselect(fdsoftc->unit, 0, FLP_DD); 1284 1285 write_fdreg(FDC_CS, RESTORE|HBIT); 1286 1287 /* 1288 * Wait for about 2 seconds. 1289 */ 1290 delay(2000000); 1291 1292 status = read_fdreg(FDC_CS); 1293 if(status & (RNF|BUSY)) { 1294 write_fdreg(FDC_CS, IRUPT); /* reset controller */ 1295 delay(40); 1296 } 1297 1298 if(!(status & LD_T00)) 1299 fdsoftc->flags |= FLPF_NOTRESP; 1300 1301 fddeselect(); 1302 } 1303 1304 static void 1305 fdgetdefaultlabel(sc, lp, part) 1306 struct fd_softc *sc; 1307 struct disklabel *lp; 1308 int part; 1309 { 1310 1311 bzero(lp, sizeof(struct disklabel)); 1312 1313 lp->d_secsize = SECTOR_SIZE; 1314 lp->d_ntracks = sc->nheads; 1315 lp->d_nsectors = sc->nsectors; 1316 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1317 lp->d_ncylinders = sc->nblocks / lp->d_secpercyl; 1318 lp->d_secperunit = sc->nblocks; 1319 1320 lp->d_type = DTYPE_FLOPPY; 1321 lp->d_rpm = 300; /* good guess I suppose. */ 1322 lp->d_interleave = 1; /* FIXME: is this OK? */ 1323 lp->d_bbsize = 0; 1324 lp->d_sbsize = 0; 1325 lp->d_npartitions = part + 1; 1326 lp->d_trkseek = STEP_DELAY; 1327 lp->d_magic = DISKMAGIC; 1328 lp->d_magic2 = DISKMAGIC; 1329 lp->d_checksum = dkcksum(lp); 1330 lp->d_partitions[part].p_size = lp->d_secperunit; 1331 lp->d_partitions[part].p_fstype = FS_UNUSED; 1332 lp->d_partitions[part].p_fsize = 1024; 1333 lp->d_partitions[part].p_frag = 8; 1334 } 1335 1336 /* 1337 * Build disk label. For now we only create a label from what we know 1338 * from 'sc'. 1339 */ 1340 static int 1341 fdgetdisklabel(sc, dev) 1342 struct fd_softc *sc; 1343 dev_t dev; 1344 { 1345 struct disklabel *lp; 1346 int part; 1347 1348 /* 1349 * If we already got one, get out. 1350 */ 1351 if(sc->flags & FLPF_HAVELAB) 1352 return(0); 1353 1354 #ifdef FLP_DEBUG 1355 printf("fdgetdisklabel()\n"); 1356 #endif 1357 1358 part = RAW_PART; 1359 lp = sc->dkdev.dk_label; 1360 fdgetdefaultlabel(sc, lp, part); 1361 sc->flags |= FLPF_HAVELAB; 1362 1363 return(0); 1364 } 1365