1 /* $NetBSD: fd.c,v 1.62 2008/06/11 14:35:53 tsutsui 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/cdefs.h> 52 __KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.62 2008/06/11 14:35:53 tsutsui Exp $"); 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/callout.h> 57 #include <sys/kernel.h> 58 #include <sys/malloc.h> 59 #include <sys/buf.h> 60 #include <sys/bufq.h> 61 #include <sys/proc.h> 62 #include <sys/device.h> 63 #include <sys/ioctl.h> 64 #include <sys/fcntl.h> 65 #include <sys/conf.h> 66 #include <sys/disklabel.h> 67 #include <sys/disk.h> 68 #include <sys/dkbad.h> 69 #include <atari/atari/device.h> 70 #include <atari/atari/stalloc.h> 71 #include <machine/disklabel.h> 72 #include <machine/iomap.h> 73 #include <machine/mfp.h> 74 #include <machine/dma.h> 75 #include <machine/video.h> 76 #include <machine/cpu.h> 77 #include <atari/dev/ym2149reg.h> 78 #include <atari/dev/fdreg.h> 79 80 /* 81 * Be verbose for debugging 82 */ 83 /*#define FLP_DEBUG 1 */ 84 85 #define FDC_MAX_DMA_AD 0x1000000 /* No DMA possible beyond */ 86 87 /* Parameters for the disk drive. */ 88 #define SECTOR_SIZE 512 /* physical sector size in bytes */ 89 #define NR_DRIVES 2 /* maximum number of drives */ 90 #define NR_TYPES 3 /* number of diskette/drive combinations*/ 91 #define MAX_ERRORS 10 /* how often to try rd/wt before quitting*/ 92 #define STEP_DELAY 6000 /* 6ms (6000us) delay after stepping */ 93 94 95 #define INV_TRK 32000 /* Should fit in unsigned short */ 96 #define INV_PART NR_TYPES 97 98 /* 99 * Driver states 100 */ 101 #define FLP_IDLE 0x00 /* floppy is idle */ 102 #define FLP_MON 0x01 /* idle with motor on */ 103 #define FLP_STAT 0x02 /* determine floppy status */ 104 #define FLP_XFER 0x04 /* read/write data from floppy */ 105 106 /* 107 * Timer delay's 108 */ 109 #define FLP_MONDELAY (3 * hz) /* motor-on delay */ 110 #define FLP_XFERDELAY (2 * hz) /* timeout on transfer */ 111 112 /* 113 * The density codes 114 */ 115 #define FLP_DD 0 /* Double density */ 116 #define FLP_HD 1 /* High density */ 117 118 119 #define b_block b_resid /* FIXME: this is not the place */ 120 121 /* 122 * Global data for all physical floppy devices 123 */ 124 static short selected = 0; /* drive/head currently selected*/ 125 static short motoron = 0; /* motor is spinning */ 126 static short nopens = 0; /* Number of opens executed */ 127 128 static short fd_state = FLP_IDLE; /* Current driver state */ 129 static int lock_stat= 0; /* DMA locking status */ 130 static short fd_cmd = 0; /* command being executed */ 131 static const char *fd_error= NULL; /* error from fd_xfer_ok() */ 132 133 /* 134 * Private per device data 135 */ 136 struct fd_softc { 137 struct device sc_dv; /* generic device info */ 138 struct disk dkdev; /* generic disk info */ 139 struct bufq_state *bufq; /* queue of buf's */ 140 struct callout sc_motor_ch; 141 int unit; /* unit for atari controlling hw*/ 142 int nheads; /* number of heads in use */ 143 int nsectors; /* number of sectors/track */ 144 int density; /* density code */ 145 int nblocks; /* number of blocks on disk */ 146 int curtrk; /* track head positioned on */ 147 short flags; /* misc flags */ 148 short part; /* Current open partition */ 149 int sector; /* logical sector for I/O */ 150 char *io_data; /* KVA for data transfer */ 151 int io_bytes; /* bytes left for I/O */ 152 int io_dir; /* B_READ/B_WRITE */ 153 int errcnt; /* current error count */ 154 u_char *bounceb; /* Bounce buffer */ 155 156 }; 157 158 /* 159 * Flags in fd_softc: 160 */ 161 #define FLPF_NOTRESP 0x001 /* Unit not responding */ 162 #define FLPF_ISOPEN 0x002 /* Unit is open */ 163 #define FLPF_SPARE 0x004 /* Not used */ 164 #define FLPF_HAVELAB 0x008 /* We have a valid label */ 165 #define FLPF_BOUNCE 0x010 /* Now using the bounce buffer */ 166 #define FLPF_WRTPROT 0x020 /* Unit is write-protected */ 167 #define FLPF_EMPTY 0x040 /* Unit is empty */ 168 #define FLPF_INOPEN 0x080 /* Currently being opened */ 169 #define FLPF_GETSTAT 0x100 /* Getting unit status */ 170 171 struct fd_types { 172 int nheads; /* Heads in use */ 173 int nsectors; /* sectors per track */ 174 int nblocks; /* number of blocks */ 175 int density; /* density code */ 176 const char *descr; /* type description */ 177 } fdtypes[NR_TYPES] = { 178 { 1, 9, 720 , FLP_DD , "360KB" }, /* 360 Kb */ 179 { 2, 9, 1440 , FLP_DD , "720KB" }, /* 720 Kb */ 180 { 2, 18, 2880 , FLP_HD , "1.44MB" }, /* 1.44 Mb */ 181 }; 182 183 #define FLP_TYPE_360 0 /* XXX: Please keep these in */ 184 #define FLP_TYPE_720 1 /* sync with the numbering in */ 185 #define FLP_TYPE_144 2 /* 'fdtypes' right above! */ 186 187 /* 188 * This is set only once at attach time. The value is determined by reading 189 * the configuration switches and is one of the FLP_TYPE_*'s. 190 * This is simular to the way Atari handles the _FLP cookie. 191 */ 192 static short def_type = 0; /* Reflects config-switches */ 193 194 #define FLP_DEFTYPE 1 /* 720Kb, reasonable default */ 195 #define FLP_TYPE(dev) ( DISKPART(dev) == 0 ? def_type : DISKPART(dev) - 1 ) 196 197 typedef void (*FPV) __P((void *)); 198 199 dev_type_open(fdopen); 200 dev_type_close(fdclose); 201 dev_type_read(fdread); 202 dev_type_write(fdwrite); 203 dev_type_ioctl(fdioctl); 204 dev_type_strategy(fdstrategy); 205 206 /* 207 * Private drive functions.... 208 */ 209 static void fdstart __P((struct fd_softc *)); 210 static void fddone __P((struct fd_softc *)); 211 static void fdstatus __P((struct fd_softc *)); 212 static void fd_xfer __P((struct fd_softc *)); 213 static void fdcint __P((struct fd_softc *)); 214 static int fd_xfer_ok __P((struct fd_softc *)); 215 static void fdmotoroff __P((struct fd_softc *)); 216 static void fdminphys __P((struct buf *)); 217 static void fdtestdrv __P((struct fd_softc *)); 218 static void fdgetdefaultlabel __P((struct fd_softc *, struct disklabel *, 219 int)); 220 static int fdgetdisklabel __P((struct fd_softc *, dev_t)); 221 static int fdselect __P((int, int, int)); 222 static void fddeselect __P((void)); 223 static void fdmoff __P((struct fd_softc *)); 224 u_char read_fdreg __P((u_short)); 225 void write_fdreg __P((u_short, u_short)); 226 u_char read_dmastat __P((void)); 227 228 extern inline u_char read_fdreg(u_short regno) 229 { 230 DMA->dma_mode = regno; 231 return(DMA->dma_data); 232 } 233 234 extern inline void write_fdreg(u_short regno, u_short val) 235 { 236 DMA->dma_mode = regno; 237 DMA->dma_data = val; 238 } 239 240 extern inline u_char read_dmastat(void) 241 { 242 DMA->dma_mode = FDC_CS | DMA_SCREG; 243 return(DMA->dma_stat); 244 } 245 246 /* 247 * Config switch stuff. Used only for the floppy type for now. That's 248 * why it's here... 249 * XXX: If needed in more places, it should be moved to it's own include file. 250 * Note: This location _must_ be read as an u_short. Failure to do so 251 * will return garbage! 252 */ 253 static u_short rd_cfg_switch __P((void)); 254 static u_short rd_cfg_switch(void) 255 { 256 return(*((u_short*)AD_CFG_SWITCH)); 257 } 258 259 /* 260 * Switch definitions. 261 * Note: ON reads as a zero bit! 262 */ 263 #define CFG_SWITCH_NOHD 0x4000 264 265 /* 266 * Autoconfig stuff.... 267 */ 268 extern struct cfdriver fd_cd; 269 270 static int fdcmatch __P((struct device *, struct cfdata *, void *)); 271 static int fdcprint __P((void *, const char *)); 272 static void fdcattach __P((struct device *, struct device *, void *)); 273 274 CFATTACH_DECL(fdc, sizeof(struct device), 275 fdcmatch, fdcattach, NULL, NULL); 276 277 const struct bdevsw fd_bdevsw = { 278 fdopen, fdclose, fdstrategy, fdioctl, nodump, nosize, D_DISK 279 }; 280 281 const struct cdevsw fd_cdevsw = { 282 fdopen, fdclose, fdread, fdwrite, fdioctl, 283 nostop, notty, nopoll, nommap, nokqfilter, D_DISK 284 }; 285 286 static int 287 fdcmatch(pdp, cfp, auxp) 288 struct device *pdp; 289 struct cfdata *cfp; 290 void *auxp; 291 { 292 static int fdc_matched = 0; 293 294 /* Match only once */ 295 if(strcmp("fdc", auxp) || fdc_matched) 296 return(0); 297 fdc_matched = 1; 298 return(1); 299 } 300 301 static void 302 fdcattach(pdp, dp, auxp) 303 struct device *pdp, *dp; 304 void *auxp; 305 { 306 struct fd_softc fdsoftc; 307 int i, nfound, first_found; 308 309 nfound = first_found = 0; 310 printf("\n"); 311 fddeselect(); 312 for(i = 0; i < NR_DRIVES; i++) { 313 314 /* 315 * Test if unit is present 316 */ 317 fdsoftc.unit = i; 318 fdsoftc.flags = 0; 319 st_dmagrab((dma_farg)fdcint, (dma_farg)fdtestdrv, &fdsoftc, 320 &lock_stat, 0); 321 st_dmafree(&fdsoftc, &lock_stat); 322 323 if(!(fdsoftc.flags & FLPF_NOTRESP)) { 324 if(!nfound) 325 first_found = i; 326 nfound++; 327 config_found(dp, (void*)i, fdcprint); 328 } 329 } 330 331 if(nfound) { 332 struct fd_softc *fdsc = getsoftc(fd_cd, first_found); 333 334 /* 335 * Make sure motor will be turned of when a floppy is 336 * inserted in the first selected drive. 337 */ 338 fdselect(first_found, 0, FLP_DD); 339 fd_state = FLP_MON; 340 callout_reset(&fdsc->sc_motor_ch, 0, (FPV)fdmotoroff, fdsc); 341 342 /* 343 * enable disk related interrupts 344 */ 345 MFP->mf_ierb |= IB_DINT; 346 MFP->mf_iprb = (u_int8_t)~IB_DINT; 347 MFP->mf_imrb |= IB_DINT; 348 } 349 } 350 351 static int 352 fdcprint(auxp, pnp) 353 void *auxp; 354 const char *pnp; 355 { 356 if (pnp != NULL) 357 aprint_normal("fd%d at %s:", (int)auxp, pnp); 358 359 return(UNCONF); 360 } 361 362 static int fdmatch __P((struct device *, struct cfdata *, void *)); 363 static void fdattach __P((struct device *, struct device *, void *)); 364 365 struct dkdriver fddkdriver = { fdstrategy }; 366 367 CFATTACH_DECL(fd, sizeof(struct fd_softc), 368 fdmatch, fdattach, NULL, NULL); 369 370 extern struct cfdriver fd_cd; 371 372 static int 373 fdmatch(pdp, cfp, auxp) 374 struct device *pdp; 375 struct cfdata *cfp; 376 void *auxp; 377 { 378 return(1); 379 } 380 381 static void 382 fdattach(pdp, dp, auxp) 383 struct device *pdp, *dp; 384 void *auxp; 385 { 386 struct fd_softc *sc; 387 struct fd_types *type; 388 u_short swtch; 389 390 sc = device_private(dp); 391 392 callout_init(&sc->sc_motor_ch, 0); 393 394 /* 395 * Find out if an Ajax chip might be installed. Set the default 396 * floppy type accordingly. 397 */ 398 swtch = rd_cfg_switch(); 399 def_type = (swtch & CFG_SWITCH_NOHD) ? FLP_TYPE_720 : FLP_TYPE_144; 400 type = &fdtypes[def_type]; 401 402 printf(": %s %d cyl, %d head, %d sec\n", type->descr, 403 type->nblocks / (type->nsectors * type->nheads), type->nheads, 404 type->nsectors); 405 406 /* 407 * Initialize and attach the disk structure. 408 */ 409 disk_init(&sc->dkdev, sc->sc_dv.dv_xname, &fddkdriver); 410 disk_attach(&sc->dkdev); 411 } 412 413 int 414 fdioctl(dev, cmd, addr, flag, l) 415 dev_t dev; 416 u_long cmd; 417 int flag; 418 void * addr; 419 struct lwp *l; 420 { 421 struct fd_softc *sc; 422 423 sc = getsoftc(fd_cd, DISKUNIT(dev)); 424 425 if((sc->flags & FLPF_HAVELAB) == 0) 426 return(EBADF); 427 428 switch(cmd) { 429 case DIOCSBAD: 430 return(EINVAL); 431 case DIOCGDINFO: 432 *(struct disklabel *)addr = *(sc->dkdev.dk_label); 433 return(0); 434 case DIOCGPART: 435 ((struct partinfo *)addr)->disklab = 436 sc->dkdev.dk_label; 437 ((struct partinfo *)addr)->part = 438 &sc->dkdev.dk_label->d_partitions[RAW_PART]; 439 return(0); 440 #ifdef notyet /* XXX LWP */ 441 case DIOCSRETRIES: 442 case DIOCSSTEP: 443 case DIOCSDINFO: 444 case DIOCWDINFO: 445 case DIOCWLABEL: 446 break; 447 #endif /* notyet */ 448 case DIOCGDEFLABEL: 449 fdgetdefaultlabel(sc, (struct disklabel *)addr, 450 RAW_PART); 451 return(0); 452 } 453 return(ENOTTY); 454 } 455 456 /* 457 * Open the device. If this is the first open on both the floppy devices, 458 * intialize the controller. 459 * Note that partition info on the floppy device is used to distinguise 460 * between 780Kb and 360Kb floppy's. 461 * partition 0: 360Kb 462 * partition 1: 780Kb 463 */ 464 int 465 fdopen(dev, flags, devtype, l) 466 dev_t dev; 467 int flags, devtype; 468 struct lwp *l; 469 { 470 struct fd_softc *sc; 471 int sps; 472 473 #ifdef FLP_DEBUG 474 printf("fdopen dev=0x%x\n", dev); 475 #endif 476 477 if(FLP_TYPE(dev) >= NR_TYPES) 478 return(ENXIO); 479 480 if((sc = getsoftc(fd_cd, DISKUNIT(dev))) == NULL) 481 return(ENXIO); 482 483 /* 484 * If no floppy currently open, reset the controller and select 485 * floppy type. 486 */ 487 if(!nopens) { 488 489 #ifdef FLP_DEBUG 490 printf("fdopen device not yet open\n"); 491 #endif 492 nopens++; 493 write_fdreg(FDC_CS, IRUPT); 494 delay(40); 495 } 496 497 /* 498 * Sleep while other process is opening the device 499 */ 500 sps = splbio(); 501 while(sc->flags & FLPF_INOPEN) 502 tsleep((void *)sc, PRIBIO, "fdopen", 0); 503 splx(sps); 504 505 if(!(sc->flags & FLPF_ISOPEN)) { 506 /* 507 * Initialise some driver values. 508 */ 509 int type; 510 void *addr; 511 512 type = FLP_TYPE(dev); 513 514 bufq_alloc(&sc->bufq, "disksort", BUFQ_SORT_RAWBLOCK); 515 sc->unit = DISKUNIT(dev); 516 sc->part = RAW_PART; 517 sc->nheads = fdtypes[type].nheads; 518 sc->nsectors = fdtypes[type].nsectors; 519 sc->nblocks = fdtypes[type].nblocks; 520 sc->density = fdtypes[type].density; 521 sc->curtrk = INV_TRK; 522 sc->sector = 0; 523 sc->errcnt = 0; 524 sc->bounceb = (u_char*)alloc_stmem(SECTOR_SIZE, &addr); 525 if(sc->bounceb == NULL) 526 return(ENOMEM); /* XXX */ 527 528 /* 529 * Go get write protect + loaded status 530 */ 531 sc->flags |= FLPF_INOPEN|FLPF_GETSTAT; 532 sps = splbio(); 533 st_dmagrab((dma_farg)fdcint, (dma_farg)fdstatus, sc, 534 &lock_stat, 0); 535 while(sc->flags & FLPF_GETSTAT) 536 tsleep((void *)sc, PRIBIO, "fdopen", 0); 537 splx(sps); 538 wakeup((void *)sc); 539 540 if((sc->flags & FLPF_WRTPROT) && (flags & FWRITE)) { 541 sc->flags = 0; 542 return(EPERM); 543 } 544 if(sc->flags & FLPF_EMPTY) { 545 sc->flags = 0; 546 return(ENXIO); 547 } 548 sc->flags &= ~(FLPF_INOPEN|FLPF_GETSTAT); 549 sc->flags |= FLPF_ISOPEN; 550 } 551 else { 552 /* 553 * Multiply opens are granted when accessing the same type of 554 * floppy (eq. the same partition). 555 */ 556 if(sc->density != fdtypes[DISKPART(dev)].density) 557 return(ENXIO); /* XXX temporarely out of business */ 558 } 559 fdgetdisklabel(sc, dev); 560 #ifdef FLP_DEBUG 561 printf("fdopen open succeeded on type %d\n", sc->part); 562 #endif 563 return (0); 564 } 565 566 int 567 fdclose(dev, flags, devtype, l) 568 dev_t dev; 569 int flags, devtype; 570 struct lwp *l; 571 { 572 struct fd_softc *sc; 573 574 sc = getsoftc(fd_cd, DISKUNIT(dev)); 575 free_stmem(sc->bounceb); 576 sc->flags = 0; 577 nopens--; 578 579 #ifdef FLP_DEBUG 580 printf("Closed floppy device -- nopens: %d\n", nopens); 581 #endif 582 return(0); 583 } 584 585 void 586 fdstrategy(bp) 587 struct buf *bp; 588 { 589 struct fd_softc *sc; 590 struct disklabel *lp; 591 int sps, sz; 592 593 sc = getsoftc(fd_cd, DISKUNIT(bp->b_dev)); 594 595 #ifdef FLP_DEBUG 596 printf("fdstrategy: %p, b_bcount: %ld\n", bp, bp->b_bcount); 597 #endif 598 599 /* 600 * check for valid partition and bounds 601 */ 602 lp = sc->dkdev.dk_label; 603 if ((sc->flags & FLPF_HAVELAB) == 0) { 604 bp->b_error = EIO; 605 goto done; 606 } 607 if (bp->b_blkno < 0 || (bp->b_bcount % SECTOR_SIZE)) { 608 bp->b_error = EINVAL; 609 goto done; 610 } 611 if (bp->b_bcount == 0) 612 goto done; 613 614 sz = howmany(bp->b_bcount, SECTOR_SIZE); 615 616 if (bp->b_blkno + sz > sc->nblocks) { 617 sz = sc->nblocks - bp->b_blkno; 618 if (sz == 0) /* Exactly at EndOfDisk */ 619 goto done; 620 if (sz < 0) { /* Past EndOfDisk */ 621 bp->b_error = EINVAL; 622 goto done; 623 } 624 /* Trucate it */ 625 if (bp->b_flags & B_RAW) 626 bp->b_bcount = sz << DEV_BSHIFT; 627 else bp->b_bcount = sz * lp->d_secsize; 628 } 629 630 /* No partition translation. */ 631 bp->b_rawblkno = bp->b_blkno; 632 633 /* 634 * queue the buf and kick the low level code 635 */ 636 sps = splbio(); 637 BUFQ_PUT(sc->bufq, bp); /* XXX disksort_cylinder */ 638 if (!lock_stat) { 639 if (fd_state & FLP_MON) 640 callout_stop(&sc->sc_motor_ch); 641 fd_state = FLP_IDLE; 642 st_dmagrab((dma_farg)fdcint, (dma_farg)fdstart, sc, 643 &lock_stat, 0); 644 } 645 splx(sps); 646 647 return; 648 done: 649 bp->b_resid = bp->b_bcount; 650 biodone(bp); 651 } 652 653 int 654 fdread(dev, uio, flags) 655 dev_t dev; 656 struct uio *uio; 657 int flags; 658 { 659 return(physio(fdstrategy, NULL, dev, B_READ, fdminphys, uio)); 660 } 661 662 int 663 fdwrite(dev, uio, flags) 664 dev_t dev; 665 struct uio *uio; 666 int flags; 667 { 668 return(physio(fdstrategy, NULL, dev, B_WRITE, fdminphys, uio)); 669 } 670 671 /* 672 * Called through DMA-dispatcher, get status. 673 */ 674 static void 675 fdstatus(sc) 676 struct fd_softc *sc; 677 { 678 #ifdef FLP_DEBUG 679 printf("fdstatus\n"); 680 #endif 681 sc->errcnt = 0; 682 fd_state = FLP_STAT; 683 fd_xfer(sc); 684 } 685 686 /* 687 * Called through the DMA-dispatcher. So we know we are the only ones 688 * messing with the floppy-controller. 689 * Initialize some fields in the fdsoftc for the state-machine and get 690 * it going. 691 */ 692 static void 693 fdstart(sc) 694 struct fd_softc *sc; 695 { 696 struct buf *bp; 697 698 bp = BUFQ_PEEK(sc->bufq); 699 sc->sector = bp->b_blkno; /* Start sector for I/O */ 700 sc->io_data = bp->b_data; /* KVA base for I/O */ 701 sc->io_bytes = bp->b_bcount; /* Transfer size in bytes */ 702 sc->io_dir = bp->b_flags & B_READ;/* Direction of transfer */ 703 sc->errcnt = 0; /* No errors yet */ 704 fd_state = FLP_XFER; /* Yes, we're going to transfer */ 705 706 /* Instrumentation. */ 707 disk_busy(&sc->dkdev); 708 709 fd_xfer(sc); 710 } 711 712 /* 713 * The current transaction is finished (for good or bad). Let go of 714 * the DMA-resources. Call biodone() to finish the transaction. 715 * Find a new transaction to work on. 716 */ 717 static void 718 fddone(sc) 719 register struct fd_softc *sc; 720 { 721 struct buf *bp; 722 struct fd_softc *sc1; 723 int i, sps; 724 725 /* 726 * Give others a chance to use the DMA. 727 */ 728 st_dmafree(sc, &lock_stat); 729 730 731 if(fd_state != FLP_STAT) { 732 /* 733 * Finish current transaction. 734 */ 735 sps = splbio(); 736 bp = BUFQ_GET(sc->bufq); 737 if (bp == NULL) 738 panic("fddone"); 739 splx(sps); 740 741 #ifdef FLP_DEBUG 742 printf("fddone: unit: %d, buf: %p, resid: %d\n",sc->unit,bp, 743 sc->io_bytes); 744 #endif 745 bp->b_resid = sc->io_bytes; 746 747 disk_unbusy(&sc->dkdev, (bp->b_bcount - bp->b_resid), 748 (bp->b_flags & B_READ)); 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 = device_lookup_private(&fd_cd, 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"); 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((void *)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((void *)sc); 1002 fddone(sc); 1003 return; 1004 } 1005 1006 bp = BUFQ_PEEK(sc->bufq); 1007 1008 bp->b_error = EIO; 1009 fd_state = FLP_MON; 1010 1011 break; 1012 case X_AGAIN: 1013 /* 1014 * Start next part of state machine. 1015 */ 1016 break; 1017 case X_OK: 1018 /* 1019 * Command ok and finished. Reset error-counter. 1020 * If there are no more bytes to transfer fall back 1021 * to motor-on idle state. 1022 */ 1023 sc->errcnt = 0; 1024 1025 if(fd_state == FLP_STAT) { 1026 sc->flags &= ~FLPF_GETSTAT; 1027 wakeup((void *)sc); 1028 fddone(sc); 1029 return; 1030 } 1031 1032 if((sc->flags & FLPF_BOUNCE) && (sc->io_dir == B_READ)) 1033 bcopy(sc->bounceb, sc->io_data, SECTOR_SIZE); 1034 sc->flags &= ~FLPF_BOUNCE; 1035 1036 sc->sector++; 1037 sc->io_data += SECTOR_SIZE; 1038 sc->io_bytes -= SECTOR_SIZE; 1039 if(sc->io_bytes <= 0) 1040 fd_state = FLP_MON; 1041 } 1042 if(fd_state == FLP_MON) 1043 fddone(sc); 1044 else fd_xfer(sc); 1045 } 1046 1047 /* 1048 * Determine status of last command. Should only be called through 1049 * 'fdcint()'. 1050 * Returns: 1051 * X_ERROR : Error on command; might succeed next time. 1052 * X_FAIL : Error on command; will never succeed. 1053 * X_AGAIN : Part of a command succeeded, call 'fd_xfer()' to complete. 1054 * X_OK : Command succeeded and is complete. 1055 * 1056 * This function only affects sc->curtrk. 1057 */ 1058 static int 1059 fd_xfer_ok(sc) 1060 register struct fd_softc *sc; 1061 { 1062 register int status; 1063 1064 #ifdef FLP_DEBUG 1065 printf("fd_xfer_ok: cmd: 0x%x, state: 0x%x\n", fd_cmd, fd_state); 1066 #endif 1067 switch(fd_cmd) { 1068 case IRUPT: 1069 /* 1070 * Timeout. Force a recalibrate before we try again. 1071 */ 1072 status = read_fdreg(FDC_CS); 1073 1074 fd_error = "Timeout"; 1075 sc->curtrk = INV_TRK; 1076 return(X_ERROR); 1077 case F_READ: 1078 /* 1079 * Test for DMA error 1080 */ 1081 status = read_dmastat(); 1082 if(!(status & DMAOK)) { 1083 fd_error = "DMA error"; 1084 return(X_ERROR); 1085 } 1086 /* 1087 * Get controller status and check for errors. 1088 */ 1089 status = read_fdreg(FDC_CS); 1090 if(status & (RNF | CRCERR | LD_T00)) { 1091 fd_error = "Read error"; 1092 if(status & RNF) 1093 sc->curtrk = INV_TRK; 1094 return(X_ERROR); 1095 } 1096 break; 1097 case F_WRITE: 1098 /* 1099 * Test for DMA error 1100 */ 1101 status = read_dmastat(); 1102 if(!(status & DMAOK)) { 1103 fd_error = "DMA error"; 1104 return(X_ERROR); 1105 } 1106 /* 1107 * Get controller status and check for errors. 1108 */ 1109 status = read_fdreg(FDC_CS); 1110 if(status & WRI_PRO) { 1111 fd_error = "Write protected"; 1112 return(X_FAIL); 1113 } 1114 if(status & (RNF | CRCERR | LD_T00)) { 1115 fd_error = "Write error"; 1116 sc->curtrk = INV_TRK; 1117 return(X_ERROR); 1118 } 1119 break; 1120 case SEEK: 1121 status = read_fdreg(FDC_CS); 1122 if(status & (RNF | CRCERR)) { 1123 fd_error = "Seek error"; 1124 sc->curtrk = INV_TRK; 1125 return(X_ERROR); 1126 } 1127 return(X_AGAIN); 1128 case RESTORE: 1129 /* 1130 * Determine if the recalibration succeeded. 1131 */ 1132 status = read_fdreg(FDC_CS); 1133 if(status & RNF) { 1134 fd_error = "Recalibrate error"; 1135 /* reset controller */ 1136 write_fdreg(FDC_CS, IRUPT); 1137 sc->curtrk = INV_TRK; 1138 return(X_ERROR); 1139 } 1140 sc->curtrk = 0; 1141 if(fd_state == FLP_STAT) { 1142 if(status & WRI_PRO) 1143 sc->flags |= FLPF_WRTPROT; 1144 break; 1145 } 1146 return(X_AGAIN); 1147 default: 1148 fd_error = "Driver error: fd_xfer_ok : Unknown state"; 1149 return(X_FAIL); 1150 } 1151 return(X_OK); 1152 } 1153 1154 /* 1155 * All timeouts will call this function. 1156 */ 1157 static void 1158 fdmotoroff(sc) 1159 struct fd_softc *sc; 1160 { 1161 int sps; 1162 1163 /* 1164 * Get at harware interrupt level 1165 */ 1166 sps = splbio(); 1167 1168 #if FLP_DEBUG 1169 printf("fdmotoroff, state = 0x%x\n", fd_state); 1170 #endif 1171 1172 switch(fd_state) { 1173 case FLP_STAT : 1174 case FLP_XFER : 1175 /* 1176 * Timeout during a transfer; cancel transaction 1177 * set command to 'IRUPT'. 1178 * A drive-interrupt is simulated to trigger the state 1179 * machine. 1180 */ 1181 /* 1182 * Cancel current transaction 1183 */ 1184 fd_cmd = IRUPT; 1185 write_fdreg(FDC_CS, IRUPT); 1186 delay(20); 1187 (void)read_fdreg(FDC_CS); 1188 write_fdreg(FDC_CS, RESTORE); 1189 break; 1190 1191 case FLP_MON : 1192 /* 1193 * Turn motor off. 1194 */ 1195 if(selected) { 1196 int tmp; 1197 1198 st_dmagrab((dma_farg)fdcint, (dma_farg)fdmoff, 1199 sc, &tmp, 0); 1200 } 1201 else fd_state = FLP_IDLE; 1202 break; 1203 } 1204 splx(sps); 1205 } 1206 1207 /* 1208 * min byte count to whats left of the track in question 1209 */ 1210 static void 1211 fdminphys(bp) 1212 struct buf *bp; 1213 { 1214 struct fd_softc *sc; 1215 int sec, toff, tsz; 1216 1217 if((sc = getsoftc(fd_cd, DISKUNIT(bp->b_dev))) == NULL) 1218 panic("fdminphys: couldn't get softc"); 1219 1220 sec = bp->b_blkno % (sc->nsectors * sc->nheads); 1221 toff = sec * SECTOR_SIZE; 1222 tsz = sc->nsectors * sc->nheads * SECTOR_SIZE; 1223 1224 #ifdef FLP_DEBUG 1225 printf("fdminphys: before %ld", bp->b_bcount); 1226 #endif 1227 1228 bp->b_bcount = min(bp->b_bcount, tsz - toff); 1229 1230 #ifdef FLP_DEBUG 1231 printf(" after %ld\n", bp->b_bcount); 1232 #endif 1233 1234 minphys(bp); 1235 } 1236 1237 /* 1238 * Called from fdmotoroff to turn the motor actually off.... 1239 * This can't be done in fdmotoroff itself, because exclusive access to the 1240 * DMA controller is needed to read the FDC-status register. The function 1241 * 'fdmoff()' always runs as the result of a 'dmagrab()'. 1242 * We need to test the status-register because we want to be sure that the 1243 * drive motor is really off before deselecting the drive. The FDC only 1244 * turns off the drive motor after having seen 10 index-pulses. You only 1245 * get index-pulses when a drive is selected....This means that if the 1246 * drive is deselected when the motor is still spinning, it will continue 1247 * to spin _even_ when you insert a floppy later on... 1248 */ 1249 static void 1250 fdmoff(fdsoftc) 1251 struct fd_softc *fdsoftc; 1252 { 1253 int tmp; 1254 1255 if ((fd_state == FLP_MON) && selected) { 1256 tmp = read_fdreg(FDC_CS); 1257 if (!(tmp & MOTORON)) { 1258 fddeselect(); 1259 fd_state = FLP_IDLE; 1260 } 1261 else 1262 callout_reset(&fdsoftc->sc_motor_ch, 10*FLP_MONDELAY, 1263 (FPV)fdmotoroff, fdsoftc); 1264 } 1265 st_dmafree(fdsoftc, &tmp); 1266 } 1267 1268 /* 1269 * Used to find out wich drives are actually connected. We do this by issuing 1270 * is 'RESTORE' command and check if the 'track-0' bit is set. This also works 1271 * if the drive is present but no floppy is inserted. 1272 */ 1273 static void 1274 fdtestdrv(fdsoftc) 1275 struct fd_softc *fdsoftc; 1276 { 1277 int status; 1278 1279 /* 1280 * Select the right unit and head. 1281 */ 1282 fdselect(fdsoftc->unit, 0, FLP_DD); 1283 1284 write_fdreg(FDC_CS, RESTORE|HBIT); 1285 1286 /* 1287 * Wait for about 2 seconds. 1288 */ 1289 delay(2000000); 1290 1291 status = read_fdreg(FDC_CS); 1292 if(status & (RNF|BUSY)) { 1293 write_fdreg(FDC_CS, IRUPT); /* reset controller */ 1294 delay(40); 1295 } 1296 1297 if(!(status & LD_T00)) 1298 fdsoftc->flags |= FLPF_NOTRESP; 1299 1300 fddeselect(); 1301 } 1302 1303 static void 1304 fdgetdefaultlabel(sc, lp, part) 1305 struct fd_softc *sc; 1306 struct disklabel *lp; 1307 int part; 1308 { 1309 1310 bzero(lp, sizeof(struct disklabel)); 1311 1312 lp->d_secsize = SECTOR_SIZE; 1313 lp->d_ntracks = sc->nheads; 1314 lp->d_nsectors = sc->nsectors; 1315 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1316 lp->d_ncylinders = sc->nblocks / lp->d_secpercyl; 1317 lp->d_secperunit = sc->nblocks; 1318 1319 lp->d_type = DTYPE_FLOPPY; 1320 lp->d_rpm = 300; /* good guess I suppose. */ 1321 lp->d_interleave = 1; /* FIXME: is this OK? */ 1322 lp->d_bbsize = 0; 1323 lp->d_sbsize = 0; 1324 lp->d_npartitions = part + 1; 1325 lp->d_trkseek = STEP_DELAY; 1326 lp->d_magic = DISKMAGIC; 1327 lp->d_magic2 = DISKMAGIC; 1328 lp->d_checksum = dkcksum(lp); 1329 lp->d_partitions[part].p_size = lp->d_secperunit; 1330 lp->d_partitions[part].p_fstype = FS_UNUSED; 1331 lp->d_partitions[part].p_fsize = 1024; 1332 lp->d_partitions[part].p_frag = 8; 1333 } 1334 1335 /* 1336 * Build disk label. For now we only create a label from what we know 1337 * from 'sc'. 1338 */ 1339 static int 1340 fdgetdisklabel(sc, dev) 1341 struct fd_softc *sc; 1342 dev_t dev; 1343 { 1344 struct disklabel *lp; 1345 int part; 1346 1347 /* 1348 * If we already got one, get out. 1349 */ 1350 if(sc->flags & FLPF_HAVELAB) 1351 return(0); 1352 1353 #ifdef FLP_DEBUG 1354 printf("fdgetdisklabel()\n"); 1355 #endif 1356 1357 part = RAW_PART; 1358 lp = sc->dkdev.dk_label; 1359 fdgetdefaultlabel(sc, lp, part); 1360 sc->flags |= FLPF_HAVELAB; 1361 1362 return(0); 1363 } 1364