1 /* $NetBSD: fd.c,v 1.48 2004/01/04 16:19:43 wiz 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.48 2004/01/04 16:19:43 wiz 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/proc.h> 61 #include <sys/device.h> 62 #include <sys/ioctl.h> 63 #include <sys/fcntl.h> 64 #include <sys/conf.h> 65 #include <sys/disklabel.h> 66 #include <sys/disk.h> 67 #include <sys/dkbad.h> 68 #include <atari/atari/device.h> 69 #include <atari/atari/stalloc.h> 70 #include <machine/disklabel.h> 71 #include <machine/iomap.h> 72 #include <machine/mfp.h> 73 #include <machine/dma.h> 74 #include <machine/video.h> 75 #include <machine/cpu.h> 76 #include <atari/dev/ym2149reg.h> 77 #include <atari/dev/fdreg.h> 78 79 /* 80 * Be verbose for debugging 81 */ 82 /*#define FLP_DEBUG 1 */ 83 84 #define FDC_MAX_DMA_AD 0x1000000 /* No DMA possible beyond */ 85 86 /* Parameters for the disk drive. */ 87 #define SECTOR_SIZE 512 /* physical sector size in bytes */ 88 #define NR_DRIVES 2 /* maximum number of drives */ 89 #define NR_TYPES 3 /* number of diskette/drive combinations*/ 90 #define MAX_ERRORS 10 /* how often to try rd/wt before quitting*/ 91 #define STEP_DELAY 6000 /* 6ms (6000us) delay after stepping */ 92 93 94 #define INV_TRK 32000 /* Should fit in unsigned short */ 95 #define INV_PART NR_TYPES 96 97 /* 98 * Driver states 99 */ 100 #define FLP_IDLE 0x00 /* floppy is idle */ 101 #define FLP_MON 0x01 /* idle with motor on */ 102 #define FLP_STAT 0x02 /* determine floppy status */ 103 #define FLP_XFER 0x04 /* read/write data from floppy */ 104 105 /* 106 * Timer delay's 107 */ 108 #define FLP_MONDELAY (3 * hz) /* motor-on delay */ 109 #define FLP_XFERDELAY (2 * hz) /* timeout on transfer */ 110 111 /* 112 * The density codes 113 */ 114 #define FLP_DD 0 /* Double density */ 115 #define FLP_HD 1 /* High density */ 116 117 118 #define b_block b_resid /* FIXME: this is not the place */ 119 120 /* 121 * Global data for all physical floppy devices 122 */ 123 static short selected = 0; /* drive/head currently selected*/ 124 static short motoron = 0; /* motor is spinning */ 125 static short nopens = 0; /* Number of opens executed */ 126 127 static short fd_state = FLP_IDLE; /* Current driver state */ 128 static int lock_stat= 0; /* DMA locking status */ 129 static short fd_cmd = 0; /* command being executed */ 130 static char *fd_error= NULL; /* error from fd_xfer_ok() */ 131 132 /* 133 * Private per device data 134 */ 135 struct fd_softc { 136 struct device sc_dv; /* generic device info */ 137 struct disk dkdev; /* generic disk info */ 138 struct bufq_state bufq; /* queue of buf's */ 139 struct callout sc_motor_ch; 140 int unit; /* unit for atari controlling hw*/ 141 int nheads; /* number of heads in use */ 142 int nsectors; /* number of sectors/track */ 143 int density; /* density code */ 144 int nblocks; /* number of blocks on disk */ 145 int curtrk; /* track head positioned on */ 146 short flags; /* misc flags */ 147 short part; /* Current open partition */ 148 int sector; /* logical sector for I/O */ 149 caddr_t io_data; /* KVA for data transfer */ 150 int io_bytes; /* bytes left for I/O */ 151 int io_dir; /* B_READ/B_WRITE */ 152 int errcnt; /* current error count */ 153 u_char *bounceb; /* Bounce buffer */ 154 155 }; 156 157 /* 158 * Flags in fd_softc: 159 */ 160 #define FLPF_NOTRESP 0x001 /* Unit not responding */ 161 #define FLPF_ISOPEN 0x002 /* Unit is open */ 162 #define FLPF_SPARE 0x004 /* Not used */ 163 #define FLPF_HAVELAB 0x008 /* We have a valid label */ 164 #define FLPF_BOUNCE 0x010 /* Now using the bounce buffer */ 165 #define FLPF_WRTPROT 0x020 /* Unit is write-protected */ 166 #define FLPF_EMPTY 0x040 /* Unit is empty */ 167 #define FLPF_INOPEN 0x080 /* Currently being opened */ 168 #define FLPF_GETSTAT 0x100 /* Getting unit status */ 169 170 struct fd_types { 171 int nheads; /* Heads in use */ 172 int nsectors; /* sectors per track */ 173 int nblocks; /* number of blocks */ 174 int density; /* density code */ 175 const char *descr; /* type description */ 176 } fdtypes[NR_TYPES] = { 177 { 1, 9, 720 , FLP_DD , "360KB" }, /* 360 Kb */ 178 { 2, 9, 1440 , FLP_DD , "720KB" }, /* 720 Kb */ 179 { 2, 18, 2880 , FLP_HD , "1.44MB" }, /* 1.44 Mb */ 180 }; 181 182 #define FLP_TYPE_360 0 /* XXX: Please keep these in */ 183 #define FLP_TYPE_720 1 /* sync with the numbering in */ 184 #define FLP_TYPE_144 2 /* 'fdtypes' right above! */ 185 186 /* 187 * This is set only once at attach time. The value is determined by reading 188 * the configuration switches and is one of the FLP_TYPE_*'s. 189 * This is simular to the way Atari handles the _FLP cookie. 190 */ 191 static short def_type = 0; /* Reflects config-switches */ 192 193 #define FLP_DEFTYPE 1 /* 720Kb, reasonable default */ 194 #define FLP_TYPE(dev) ( DISKPART(dev) == 0 ? def_type : DISKPART(dev) - 1 ) 195 196 typedef void (*FPV) __P((void *)); 197 198 dev_type_open(fdopen); 199 dev_type_close(fdclose); 200 dev_type_read(fdread); 201 dev_type_write(fdwrite); 202 dev_type_ioctl(fdioctl); 203 dev_type_strategy(fdstrategy); 204 205 /* 206 * Private drive functions.... 207 */ 208 static void fdstart __P((struct fd_softc *)); 209 static void fddone __P((struct fd_softc *)); 210 static void fdstatus __P((struct fd_softc *)); 211 static void fd_xfer __P((struct fd_softc *)); 212 static void fdcint __P((struct fd_softc *)); 213 static int fd_xfer_ok __P((struct fd_softc *)); 214 static void fdmotoroff __P((struct fd_softc *)); 215 static void fdminphys __P((struct buf *)); 216 static void fdtestdrv __P((struct fd_softc *)); 217 static void fdgetdefaultlabel __P((struct fd_softc *, struct disklabel *, 218 int)); 219 static int fdgetdisklabel __P((struct fd_softc *, dev_t)); 220 static int fdselect __P((int, int, int)); 221 static void fddeselect __P((void)); 222 static void fdmoff __P((struct fd_softc *)); 223 u_char read_fdreg __P((u_short)); 224 void write_fdreg __P((u_short, u_short)); 225 u_char read_dmastat __P((void)); 226 227 extern __inline__ u_char read_fdreg(u_short regno) 228 { 229 DMA->dma_mode = regno; 230 return(DMA->dma_data); 231 } 232 233 extern __inline__ void write_fdreg(u_short regno, u_short val) 234 { 235 DMA->dma_mode = regno; 236 DMA->dma_data = val; 237 } 238 239 extern __inline__ u_char read_dmastat(void) 240 { 241 DMA->dma_mode = FDC_CS | DMA_SCREG; 242 return(DMA->dma_stat); 243 } 244 245 /* 246 * Config switch stuff. Used only for the floppy type for now. That's 247 * why it's here... 248 * XXX: If needed in more places, it should be moved to it's own include file. 249 * Note: This location _must_ be read as an u_short. Failure to do so 250 * will return garbage! 251 */ 252 static u_short rd_cfg_switch __P((void)); 253 static u_short rd_cfg_switch(void) 254 { 255 return(*((u_short*)AD_CFG_SWITCH)); 256 } 257 258 /* 259 * Switch definitions. 260 * Note: ON reads as a zero bit! 261 */ 262 #define CFG_SWITCH_NOHD 0x4000 263 264 /* 265 * Autoconfig stuff.... 266 */ 267 extern struct cfdriver fd_cd; 268 269 static int fdcmatch __P((struct device *, struct cfdata *, void *)); 270 static int fdcprint __P((void *, const char *)); 271 static void fdcattach __P((struct device *, struct device *, void *)); 272 273 CFATTACH_DECL(fdc, sizeof(struct device), 274 fdcmatch, fdcattach, NULL, NULL); 275 276 const struct bdevsw fd_bdevsw = { 277 fdopen, fdclose, fdstrategy, fdioctl, nodump, nosize, D_DISK 278 }; 279 280 const struct cdevsw fd_cdevsw = { 281 fdopen, fdclose, fdread, fdwrite, fdioctl, 282 nostop, notty, nopoll, nommap, nokqfilter, D_DISK 283 }; 284 285 static int 286 fdcmatch(pdp, cfp, auxp) 287 struct device *pdp; 288 struct cfdata *cfp; 289 void *auxp; 290 { 291 static int fdc_matched = 0; 292 293 /* Match only once */ 294 if(strcmp("fdc", auxp) || fdc_matched) 295 return(0); 296 fdc_matched = 1; 297 return(1); 298 } 299 300 static void 301 fdcattach(pdp, dp, auxp) 302 struct device *pdp, *dp; 303 void *auxp; 304 { 305 struct fd_softc fdsoftc; 306 int i, nfound, first_found; 307 308 nfound = first_found = 0; 309 printf("\n"); 310 fddeselect(); 311 for(i = 0; i < NR_DRIVES; i++) { 312 313 /* 314 * Test if unit is present 315 */ 316 fdsoftc.unit = i; 317 fdsoftc.flags = 0; 318 st_dmagrab((dma_farg)fdcint, (dma_farg)fdtestdrv, &fdsoftc, 319 &lock_stat, 0); 320 st_dmafree(&fdsoftc, &lock_stat); 321 322 if(!(fdsoftc.flags & FLPF_NOTRESP)) { 323 if(!nfound) 324 first_found = i; 325 nfound++; 326 config_found(dp, (void*)i, fdcprint); 327 } 328 } 329 330 if(nfound) { 331 struct fd_softc *fdsc = getsoftc(fd_cd, first_found); 332 333 /* 334 * Make sure motor will be turned of when a floppy is 335 * inserted in the first selected drive. 336 */ 337 fdselect(first_found, 0, FLP_DD); 338 fd_state = FLP_MON; 339 callout_reset(&fdsc->sc_motor_ch, 0, (FPV)fdmotoroff, fdsc); 340 341 /* 342 * enable disk related interrupts 343 */ 344 MFP->mf_ierb |= IB_DINT; 345 MFP->mf_iprb = (u_int8_t)~IB_DINT; 346 MFP->mf_imrb |= IB_DINT; 347 } 348 } 349 350 static int 351 fdcprint(auxp, pnp) 352 void *auxp; 353 const char *pnp; 354 { 355 if (pnp != NULL) 356 aprint_normal("fd%d at %s:", (int)auxp, pnp); 357 358 return(UNCONF); 359 } 360 361 static int fdmatch __P((struct device *, struct cfdata *, void *)); 362 static void fdattach __P((struct device *, struct device *, void *)); 363 364 struct dkdriver fddkdriver = { fdstrategy }; 365 366 CFATTACH_DECL(fd, sizeof(struct fd_softc), 367 fdmatch, fdattach, NULL, NULL); 368 369 extern struct cfdriver fd_cd; 370 371 static int 372 fdmatch(pdp, cfp, auxp) 373 struct device *pdp; 374 struct cfdata *cfp; 375 void *auxp; 376 { 377 return(1); 378 } 379 380 static void 381 fdattach(pdp, dp, auxp) 382 struct device *pdp, *dp; 383 void *auxp; 384 { 385 struct fd_softc *sc; 386 struct fd_types *type; 387 u_short swtch; 388 389 sc = (struct fd_softc *)dp; 390 391 callout_init(&sc->sc_motor_ch); 392 393 /* 394 * Find out if an Ajax chip might be installed. Set the default 395 * floppy type accordingly. 396 */ 397 swtch = rd_cfg_switch(); 398 def_type = (swtch & CFG_SWITCH_NOHD) ? FLP_TYPE_720 : FLP_TYPE_144; 399 type = &fdtypes[def_type]; 400 401 printf(": %s %d cyl, %d head, %d sec\n", type->descr, 402 type->nblocks / (type->nsectors * type->nheads), type->nheads, 403 type->nsectors); 404 405 /* 406 * Initialize and attach the disk structure. 407 */ 408 sc->dkdev.dk_name = sc->sc_dv.dv_xname; 409 sc->dkdev.dk_driver = &fddkdriver; 410 disk_attach(&sc->dkdev); 411 } 412 413 int 414 fdioctl(dev, cmd, addr, flag, p) 415 dev_t dev; 416 u_long cmd; 417 int flag; 418 caddr_t addr; 419 struct proc *p; 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, proc) 466 dev_t dev; 467 int flags, devtype; 468 struct proc *proc; 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((caddr_t)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, 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((caddr_t)sc, PRIBIO, "fdopen", 0); 537 splx(sps); 538 wakeup((caddr_t)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, proc) 568 dev_t dev; 569 int flags, devtype; 570 struct proc *proc; 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 bad; 606 } 607 if (bp->b_blkno < 0 || (bp->b_bcount % SECTOR_SIZE)) { 608 bp->b_error = EINVAL; 609 goto bad; 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 bad; 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 bad: 649 bp->b_flags |= B_ERROR; 650 done: 651 bp->b_resid = bp->b_bcount; 652 biodone(bp); 653 } 654 655 int 656 fdread(dev, uio, flags) 657 dev_t dev; 658 struct uio *uio; 659 int flags; 660 { 661 return(physio(fdstrategy, NULL, dev, B_READ, fdminphys, uio)); 662 } 663 664 int 665 fdwrite(dev, uio, flags) 666 dev_t dev; 667 struct uio *uio; 668 int flags; 669 { 670 return(physio(fdstrategy, NULL, dev, B_WRITE, fdminphys, uio)); 671 } 672 673 /* 674 * Called through DMA-dispatcher, get status. 675 */ 676 static void 677 fdstatus(sc) 678 struct fd_softc *sc; 679 { 680 #ifdef FLP_DEBUG 681 printf("fdstatus\n"); 682 #endif 683 sc->errcnt = 0; 684 fd_state = FLP_STAT; 685 fd_xfer(sc); 686 } 687 688 /* 689 * Called through the DMA-dispatcher. So we know we are the only ones 690 * messing with the floppy-controller. 691 * Initialize some fields in the fdsoftc for the state-machine and get 692 * it going. 693 */ 694 static void 695 fdstart(sc) 696 struct fd_softc *sc; 697 { 698 struct buf *bp; 699 700 bp = BUFQ_PEEK(&sc->bufq); 701 sc->sector = bp->b_blkno; /* Start sector for I/O */ 702 sc->io_data = bp->b_data; /* KVA base for I/O */ 703 sc->io_bytes = bp->b_bcount; /* Transfer size in bytes */ 704 sc->io_dir = bp->b_flags & B_READ;/* Direction of transfer */ 705 sc->errcnt = 0; /* No errors yet */ 706 fd_state = FLP_XFER; /* Yes, we're going to transfer */ 707 708 /* Instrumentation. */ 709 disk_busy(&sc->dkdev); 710 711 fd_xfer(sc); 712 } 713 714 /* 715 * The current transaction is finished (for good or bad). Let go of 716 * the DMA-resources. Call biodone() to finish the transaction. 717 * Find a new transaction to work on. 718 */ 719 static void 720 fddone(sc) 721 register struct fd_softc *sc; 722 { 723 struct buf *bp; 724 struct fd_softc *sc1; 725 int i, sps; 726 727 /* 728 * Give others a chance to use the DMA. 729 */ 730 st_dmafree(sc, &lock_stat); 731 732 733 if(fd_state != FLP_STAT) { 734 /* 735 * Finish current transaction. 736 */ 737 sps = splbio(); 738 bp = BUFQ_GET(&sc->bufq); 739 if (bp == NULL) 740 panic("fddone"); 741 splx(sps); 742 743 #ifdef FLP_DEBUG 744 printf("fddone: unit: %d, buf: %p, resid: %d\n",sc->unit,bp, 745 sc->io_bytes); 746 #endif 747 bp->b_resid = sc->io_bytes; 748 749 disk_unbusy(&sc->dkdev, (bp->b_bcount - bp->b_resid), 750 (bp->b_flags & B_READ)); 751 752 biodone(bp); 753 } 754 fd_state = FLP_MON; 755 756 if(lock_stat) 757 return; /* XXX Is this possible? */ 758 759 /* 760 * Find a new transaction on round-robin basis. 761 */ 762 for(i = sc->unit + 1; ;i++) { 763 if(i >= fd_cd.cd_ndevs) 764 i = 0; 765 if((sc1 = fd_cd.cd_devs[i]) == NULL) 766 continue; 767 if (BUFQ_PEEK(&sc1->bufq) != NULL) 768 break; 769 if(i == sc->unit) { 770 callout_reset(&sc->sc_motor_ch, FLP_MONDELAY, 771 (FPV)fdmotoroff, sc); 772 #ifdef FLP_DEBUG 773 printf("fddone: Nothing to do\n"); 774 #endif 775 return; /* No work */ 776 } 777 } 778 fd_state = FLP_IDLE; 779 #ifdef FLP_DEBUG 780 printf("fddone: Staring job on unit %d\n", sc1->unit); 781 #endif 782 st_dmagrab((dma_farg)fdcint, (dma_farg)fdstart, sc1, &lock_stat, 0); 783 } 784 785 static int 786 fdselect(drive, head, dense) 787 int drive, head, dense; 788 { 789 int i, spinning; 790 #ifdef FLP_DEBUG 791 printf("fdselect: drive=%d, head=%d, dense=%d\n", drive, head, dense); 792 #endif 793 i = ((drive == 1) ? PA_FLOP1 : PA_FLOP0) | head; 794 spinning = motoron; 795 motoron = 1; 796 797 switch(dense) { 798 case FLP_DD: 799 DMA->dma_drvmode = 0; 800 break; 801 case FLP_HD: 802 DMA->dma_drvmode = (FDC_HDSET|FDC_HDSIG); 803 break; 804 default: 805 panic("fdselect: unknown density code"); 806 } 807 if(i != selected) { 808 selected = i; 809 ym2149_fd_select((i ^ PA_FDSEL)); 810 } 811 return(spinning); 812 } 813 814 static void 815 fddeselect() 816 { 817 ym2149_fd_select(PA_FDSEL); 818 motoron = selected = 0; 819 DMA->dma_drvmode = 0; 820 } 821 822 /**************************************************************************** 823 * The following functions assume to be running as a result of a * 824 * disk-interrupt (e.q. spl = splbio). * 825 * They form the finit-state machine, the actual driver. * 826 * * 827 * fdstart()/ --> fd_xfer() -> activate hardware * 828 * fdopen() ^ * 829 * | * 830 * +-- not ready -<------------+ * 831 * | * 832 * fdmotoroff()/ --> fdcint() -> fd_xfer_ok() ---+ * 833 * h/w interrupt | * 834 * \|/ * 835 * finished ---> fdone() * 836 * * 837 ****************************************************************************/ 838 static void 839 fd_xfer(sc) 840 struct fd_softc *sc; 841 { 842 register int head; 843 register int track, sector, hbit; 844 u_long phys_addr; 845 846 head = track = 0; 847 switch(fd_state) { 848 case FLP_XFER: 849 /* 850 * Calculate head/track values 851 */ 852 track = sc->sector / sc->nsectors; 853 head = track % sc->nheads; 854 track = track / sc->nheads; 855 #ifdef FLP_DEBUG 856 printf("fd_xfer: sector:%d,head:%d,track:%d\n", sc->sector,head, 857 track); 858 #endif 859 break; 860 861 case FLP_STAT: 862 /* 863 * FLP_STAT only wants to recalibrate 864 */ 865 sc->curtrk = INV_TRK; 866 break; 867 default: 868 panic("fd_xfer: wrong state (0x%x)", fd_state); 869 } 870 871 /* 872 * Select the drive. 873 */ 874 hbit = fdselect(sc->unit, head, sc->density) ? HBIT : 0; 875 876 if(sc->curtrk == INV_TRK) { 877 /* 878 * Recalibrate, since we lost track of head positioning. 879 * The floppy disk controller has no way of determining its 880 * absolute arm position (track). Instead, it steps the 881 * arm a track at a time and keeps track of where it 882 * thinks it is (in software). However, after a SEEK, the 883 * hardware reads information from the diskette telling 884 * where the arm actually is. If the arm is in the wrong place, 885 * a recalibration is done, which forces the arm to track 0. 886 * This way the controller can get back into sync with reality. 887 */ 888 fd_cmd = RESTORE; 889 write_fdreg(FDC_CS, RESTORE|VBIT|hbit); 890 callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY, 891 (FPV)fdmotoroff, sc); 892 893 #ifdef FLP_DEBUG 894 printf("fd_xfer:Recalibrating drive %d\n", sc->unit); 895 #endif 896 return; 897 } 898 899 write_fdreg(FDC_TR, sc->curtrk); 900 901 /* 902 * Issue a SEEK command on the indicated drive unless the arm is 903 * already positioned on the correct track. 904 */ 905 if(track != sc->curtrk) { 906 sc->curtrk = track; /* be optimistic */ 907 write_fdreg(FDC_DR, track); 908 write_fdreg(FDC_CS, SEEK|RATE6|VBIT|hbit); 909 callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY, 910 (FPV)fdmotoroff, sc); 911 fd_cmd = SEEK; 912 #ifdef FLP_DEBUG 913 printf("fd_xfer:Seek to track %d on drive %d\n",track,sc->unit); 914 #endif 915 return; 916 } 917 918 /* 919 * The drive is now on the proper track. Read or write 1 block. 920 */ 921 sector = sc->sector % sc->nsectors; 922 sector++; /* start numbering at 1 */ 923 924 write_fdreg(FDC_SR, sector); 925 926 phys_addr = (u_long)kvtop(sc->io_data); 927 if(phys_addr >= FDC_MAX_DMA_AD) { 928 /* 929 * We _must_ bounce this address 930 */ 931 phys_addr = (u_long)kvtop(sc->bounceb); 932 if(sc->io_dir == B_WRITE) 933 bcopy(sc->io_data, sc->bounceb, SECTOR_SIZE); 934 sc->flags |= FLPF_BOUNCE; 935 } 936 st_dmaaddr_set((caddr_t)phys_addr); /* DMA address setup */ 937 938 #ifdef FLP_DEBUG 939 printf("fd_xfer:Start io (io_addr:%lx)\n", (u_long)kvtop(sc->io_data)); 940 #endif 941 942 if(sc->io_dir == B_READ) { 943 /* Issue the command */ 944 st_dmacomm(DMA_FDC | DMA_SCREG, 1); 945 write_fdreg(FDC_CS, F_READ|hbit); 946 fd_cmd = F_READ; 947 } 948 else { 949 /* Issue the command */ 950 st_dmacomm(DMA_WRBIT | DMA_FDC | DMA_SCREG, 1); 951 write_fdreg(DMA_WRBIT | FDC_CS, F_WRITE|hbit|EBIT|PBIT); 952 fd_cmd = F_WRITE; 953 } 954 callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY, (FPV)fdmotoroff, sc); 955 } 956 957 /* return values of fd_xfer_ok(): */ 958 #define X_OK 0 959 #define X_AGAIN 1 960 #define X_ERROR 2 961 #define X_FAIL 3 962 963 /* 964 * Hardware interrupt function. 965 */ 966 static void 967 fdcint(sc) 968 struct fd_softc *sc; 969 { 970 struct buf *bp; 971 972 #ifdef FLP_DEBUG 973 printf("fdcint: unit = %d\n", sc->unit); 974 #endif 975 976 /* 977 * Cancel timeout (we made it, didn't we) 978 */ 979 callout_stop(&sc->sc_motor_ch); 980 981 switch(fd_xfer_ok(sc)) { 982 case X_ERROR : 983 if(++(sc->errcnt) < MAX_ERRORS) { 984 /* 985 * Command failed but still retries left. 986 */ 987 break; 988 } 989 /* FALL THROUGH */ 990 case X_FAIL : 991 /* 992 * Non recoverable error. Fall back to motor-on 993 * idle-state. 994 */ 995 if(fd_error != NULL) { 996 printf("Floppy error: %s\n", fd_error); 997 fd_error = NULL; 998 } 999 1000 if(fd_state == FLP_STAT) { 1001 sc->flags |= FLPF_EMPTY; 1002 sc->flags &= ~FLPF_GETSTAT; 1003 wakeup((caddr_t)sc); 1004 fddone(sc); 1005 return; 1006 } 1007 1008 bp = BUFQ_PEEK(&sc->bufq); 1009 1010 bp->b_error = EIO; 1011 bp->b_flags |= B_ERROR; 1012 fd_state = FLP_MON; 1013 1014 break; 1015 case X_AGAIN: 1016 /* 1017 * Start next part of state machine. 1018 */ 1019 break; 1020 case X_OK: 1021 /* 1022 * Command ok and finished. Reset error-counter. 1023 * If there are no more bytes to transfer fall back 1024 * to motor-on idle state. 1025 */ 1026 sc->errcnt = 0; 1027 1028 if(fd_state == FLP_STAT) { 1029 sc->flags &= ~FLPF_GETSTAT; 1030 wakeup((caddr_t)sc); 1031 fddone(sc); 1032 return; 1033 } 1034 1035 if((sc->flags & FLPF_BOUNCE) && (sc->io_dir == B_READ)) 1036 bcopy(sc->bounceb, sc->io_data, SECTOR_SIZE); 1037 sc->flags &= ~FLPF_BOUNCE; 1038 1039 sc->sector++; 1040 sc->io_data += SECTOR_SIZE; 1041 sc->io_bytes -= SECTOR_SIZE; 1042 if(sc->io_bytes <= 0) 1043 fd_state = FLP_MON; 1044 } 1045 if(fd_state == FLP_MON) 1046 fddone(sc); 1047 else fd_xfer(sc); 1048 } 1049 1050 /* 1051 * Determine status of last command. Should only be called through 1052 * 'fdcint()'. 1053 * Returns: 1054 * X_ERROR : Error on command; might succeed next time. 1055 * X_FAIL : Error on command; will never succeed. 1056 * X_AGAIN : Part of a command succeeded, call 'fd_xfer()' to complete. 1057 * X_OK : Command succeeded and is complete. 1058 * 1059 * This function only affects sc->curtrk. 1060 */ 1061 static int 1062 fd_xfer_ok(sc) 1063 register struct fd_softc *sc; 1064 { 1065 register int status; 1066 1067 #ifdef FLP_DEBUG 1068 printf("fd_xfer_ok: cmd: 0x%x, state: 0x%x\n", fd_cmd, fd_state); 1069 #endif 1070 switch(fd_cmd) { 1071 case IRUPT: 1072 /* 1073 * Timeout. Force a recalibrate before we try again. 1074 */ 1075 status = read_fdreg(FDC_CS); 1076 1077 fd_error = "Timeout"; 1078 sc->curtrk = INV_TRK; 1079 return(X_ERROR); 1080 case F_READ: 1081 /* 1082 * Test for DMA error 1083 */ 1084 status = read_dmastat(); 1085 if(!(status & DMAOK)) { 1086 fd_error = "DMA error"; 1087 return(X_ERROR); 1088 } 1089 /* 1090 * Get controller status and check for errors. 1091 */ 1092 status = read_fdreg(FDC_CS); 1093 if(status & (RNF | CRCERR | LD_T00)) { 1094 fd_error = "Read error"; 1095 if(status & RNF) 1096 sc->curtrk = INV_TRK; 1097 return(X_ERROR); 1098 } 1099 break; 1100 case F_WRITE: 1101 /* 1102 * Test for DMA error 1103 */ 1104 status = read_dmastat(); 1105 if(!(status & DMAOK)) { 1106 fd_error = "DMA error"; 1107 return(X_ERROR); 1108 } 1109 /* 1110 * Get controller status and check for errors. 1111 */ 1112 status = read_fdreg(FDC_CS); 1113 if(status & WRI_PRO) { 1114 fd_error = "Write protected"; 1115 return(X_FAIL); 1116 } 1117 if(status & (RNF | CRCERR | LD_T00)) { 1118 fd_error = "Write error"; 1119 sc->curtrk = INV_TRK; 1120 return(X_ERROR); 1121 } 1122 break; 1123 case SEEK: 1124 status = read_fdreg(FDC_CS); 1125 if(status & (RNF | CRCERR)) { 1126 fd_error = "Seek error"; 1127 sc->curtrk = INV_TRK; 1128 return(X_ERROR); 1129 } 1130 return(X_AGAIN); 1131 case RESTORE: 1132 /* 1133 * Determine if the recalibration succeeded. 1134 */ 1135 status = read_fdreg(FDC_CS); 1136 if(status & RNF) { 1137 fd_error = "Recalibrate error"; 1138 /* reset controller */ 1139 write_fdreg(FDC_CS, IRUPT); 1140 sc->curtrk = INV_TRK; 1141 return(X_ERROR); 1142 } 1143 sc->curtrk = 0; 1144 if(fd_state == FLP_STAT) { 1145 if(status & WRI_PRO) 1146 sc->flags |= FLPF_WRTPROT; 1147 break; 1148 } 1149 return(X_AGAIN); 1150 default: 1151 fd_error = "Driver error: fd_xfer_ok : Unknown state"; 1152 return(X_FAIL); 1153 } 1154 return(X_OK); 1155 } 1156 1157 /* 1158 * All timeouts will call this function. 1159 */ 1160 static void 1161 fdmotoroff(sc) 1162 struct fd_softc *sc; 1163 { 1164 int sps; 1165 1166 /* 1167 * Get at harware interrupt level 1168 */ 1169 sps = splbio(); 1170 1171 #if FLP_DEBUG 1172 printf("fdmotoroff, state = 0x%x\n", fd_state); 1173 #endif 1174 1175 switch(fd_state) { 1176 case FLP_STAT : 1177 case FLP_XFER : 1178 /* 1179 * Timeout during a transfer; cancel transaction 1180 * set command to 'IRUPT'. 1181 * A drive-interrupt is simulated to trigger the state 1182 * machine. 1183 */ 1184 /* 1185 * Cancel current transaction 1186 */ 1187 fd_cmd = IRUPT; 1188 write_fdreg(FDC_CS, IRUPT); 1189 delay(20); 1190 (void)read_fdreg(FDC_CS); 1191 write_fdreg(FDC_CS, RESTORE); 1192 break; 1193 1194 case FLP_MON : 1195 /* 1196 * Turn motor off. 1197 */ 1198 if(selected) { 1199 int tmp; 1200 1201 st_dmagrab((dma_farg)fdcint, (dma_farg)fdmoff, 1202 sc, &tmp, 0); 1203 } 1204 else fd_state = FLP_IDLE; 1205 break; 1206 } 1207 splx(sps); 1208 } 1209 1210 /* 1211 * min byte count to whats left of the track in question 1212 */ 1213 static void 1214 fdminphys(bp) 1215 struct buf *bp; 1216 { 1217 struct fd_softc *sc; 1218 int sec, toff, tsz; 1219 1220 if((sc = getsoftc(fd_cd, DISKUNIT(bp->b_dev))) == NULL) 1221 panic("fdminphys: couldn't get softc"); 1222 1223 sec = bp->b_blkno % (sc->nsectors * sc->nheads); 1224 toff = sec * SECTOR_SIZE; 1225 tsz = sc->nsectors * sc->nheads * SECTOR_SIZE; 1226 1227 #ifdef FLP_DEBUG 1228 printf("fdminphys: before %ld", bp->b_bcount); 1229 #endif 1230 1231 bp->b_bcount = min(bp->b_bcount, tsz - toff); 1232 1233 #ifdef FLP_DEBUG 1234 printf(" after %ld\n", bp->b_bcount); 1235 #endif 1236 1237 minphys(bp); 1238 } 1239 1240 /* 1241 * Called from fdmotoroff to turn the motor actually off.... 1242 * This can't be done in fdmotoroff itself, because exclusive access to the 1243 * DMA controller is needed to read the FDC-status register. The function 1244 * 'fdmoff()' always runs as the result of a 'dmagrab()'. 1245 * We need to test the status-register because we want to be sure that the 1246 * drive motor is really off before deselecting the drive. The FDC only 1247 * turns off the drive motor after having seen 10 index-pulses. You only 1248 * get index-pulses when a drive is selected....This means that if the 1249 * drive is deselected when the motor is still spinning, it will continue 1250 * to spin _even_ when you insert a floppy later on... 1251 */ 1252 static void 1253 fdmoff(fdsoftc) 1254 struct fd_softc *fdsoftc; 1255 { 1256 int tmp; 1257 1258 if ((fd_state == FLP_MON) && selected) { 1259 tmp = read_fdreg(FDC_CS); 1260 if (!(tmp & MOTORON)) { 1261 fddeselect(); 1262 fd_state = FLP_IDLE; 1263 } 1264 else 1265 callout_reset(&fdsoftc->sc_motor_ch, 10*FLP_MONDELAY, 1266 (FPV)fdmotoroff, fdsoftc); 1267 } 1268 st_dmafree(fdsoftc, &tmp); 1269 } 1270 1271 /* 1272 * Used to find out wich drives are actually connected. We do this by issuing 1273 * is 'RESTORE' command and check if the 'track-0' bit is set. This also works 1274 * if the drive is present but no floppy is inserted. 1275 */ 1276 static void 1277 fdtestdrv(fdsoftc) 1278 struct fd_softc *fdsoftc; 1279 { 1280 int status; 1281 1282 /* 1283 * Select the right unit and head. 1284 */ 1285 fdselect(fdsoftc->unit, 0, FLP_DD); 1286 1287 write_fdreg(FDC_CS, RESTORE|HBIT); 1288 1289 /* 1290 * Wait for about 2 seconds. 1291 */ 1292 delay(2000000); 1293 1294 status = read_fdreg(FDC_CS); 1295 if(status & (RNF|BUSY)) { 1296 write_fdreg(FDC_CS, IRUPT); /* reset controller */ 1297 delay(40); 1298 } 1299 1300 if(!(status & LD_T00)) 1301 fdsoftc->flags |= FLPF_NOTRESP; 1302 1303 fddeselect(); 1304 } 1305 1306 static void 1307 fdgetdefaultlabel(sc, lp, part) 1308 struct fd_softc *sc; 1309 struct disklabel *lp; 1310 int part; 1311 { 1312 1313 bzero(lp, sizeof(struct disklabel)); 1314 1315 lp->d_secsize = SECTOR_SIZE; 1316 lp->d_ntracks = sc->nheads; 1317 lp->d_nsectors = sc->nsectors; 1318 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1319 lp->d_ncylinders = sc->nblocks / lp->d_secpercyl; 1320 lp->d_secperunit = sc->nblocks; 1321 1322 lp->d_type = DTYPE_FLOPPY; 1323 lp->d_rpm = 300; /* good guess I suppose. */ 1324 lp->d_interleave = 1; /* FIXME: is this OK? */ 1325 lp->d_bbsize = 0; 1326 lp->d_sbsize = 0; 1327 lp->d_npartitions = part + 1; 1328 lp->d_trkseek = STEP_DELAY; 1329 lp->d_magic = DISKMAGIC; 1330 lp->d_magic2 = DISKMAGIC; 1331 lp->d_checksum = dkcksum(lp); 1332 lp->d_partitions[part].p_size = lp->d_secperunit; 1333 lp->d_partitions[part].p_fstype = FS_UNUSED; 1334 lp->d_partitions[part].p_fsize = 1024; 1335 lp->d_partitions[part].p_frag = 8; 1336 } 1337 1338 /* 1339 * Build disk label. For now we only create a label from what we know 1340 * from 'sc'. 1341 */ 1342 static int 1343 fdgetdisklabel(sc, dev) 1344 struct fd_softc *sc; 1345 dev_t dev; 1346 { 1347 struct disklabel *lp; 1348 int part; 1349 1350 /* 1351 * If we already got one, get out. 1352 */ 1353 if(sc->flags & FLPF_HAVELAB) 1354 return(0); 1355 1356 #ifdef FLP_DEBUG 1357 printf("fdgetdisklabel()\n"); 1358 #endif 1359 1360 part = RAW_PART; 1361 lp = sc->dkdev.dk_label; 1362 fdgetdefaultlabel(sc, lp, part); 1363 sc->flags |= FLPF_HAVELAB; 1364 1365 return(0); 1366 } 1367