15b81b6b3SRodney W. Grimes /*#define DEBUG 1*/ 25b81b6b3SRodney W. Grimes /*- 35b81b6b3SRodney W. Grimes * Copyright (c) 1990 The Regents of the University of California. 45b81b6b3SRodney W. Grimes * All rights reserved. 55b81b6b3SRodney W. Grimes * 65b81b6b3SRodney W. Grimes * This code is derived from software contributed to Berkeley by 75b81b6b3SRodney W. Grimes * Don Ahn. 85b81b6b3SRodney W. Grimes * 95b81b6b3SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 105b81b6b3SRodney W. Grimes * modification, are permitted provided that the following conditions 115b81b6b3SRodney W. Grimes * are met: 125b81b6b3SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 135b81b6b3SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 145b81b6b3SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 155b81b6b3SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 165b81b6b3SRodney W. Grimes * documentation and/or other materials provided with the distribution. 175b81b6b3SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 185b81b6b3SRodney W. Grimes * must display the following acknowledgement: 195b81b6b3SRodney W. Grimes * This product includes software developed by the University of 205b81b6b3SRodney W. Grimes * California, Berkeley and its contributors. 215b81b6b3SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 225b81b6b3SRodney W. Grimes * may be used to endorse or promote products derived from this software 235b81b6b3SRodney W. Grimes * without specific prior written permission. 245b81b6b3SRodney W. Grimes * 255b81b6b3SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 265b81b6b3SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 275b81b6b3SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 285b81b6b3SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 295b81b6b3SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 305b81b6b3SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 315b81b6b3SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 325b81b6b3SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 335b81b6b3SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 345b81b6b3SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 355b81b6b3SRodney W. Grimes * SUCH DAMAGE. 365b81b6b3SRodney W. Grimes * 37dc4ff321SRodney W. Grimes * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 38b2be795bSAndrey A. Chernov * $Id: fd.c,v 1.28 1994/08/23 07:52:09 paul Exp $ 395b81b6b3SRodney W. Grimes * 405b81b6b3SRodney W. Grimes */ 415b81b6b3SRodney W. Grimes 42b99f0a4aSAndrew Moore #include "ft.h" 43b99f0a4aSAndrew Moore #if NFT < 1 44b99f0a4aSAndrew Moore #undef NFDC 45b99f0a4aSAndrew Moore #endif 465b81b6b3SRodney W. Grimes #include "fd.h" 475b81b6b3SRodney W. Grimes 48b99f0a4aSAndrew Moore #if NFDC > 0 49b99f0a4aSAndrew Moore 50b99f0a4aSAndrew Moore #include <sys/param.h> 51b99f0a4aSAndrew Moore #include <sys/dkbad.h> 52b99f0a4aSAndrew Moore #include <sys/systm.h> 53b99f0a4aSAndrew Moore #include <sys/kernel.h> 54b99f0a4aSAndrew Moore #include <sys/conf.h> 55b99f0a4aSAndrew Moore #include <sys/file.h> 56b99f0a4aSAndrew Moore #include <sys/ioctl.h> 57b99f0a4aSAndrew Moore #include <machine/ioctl_fd.h> 58b99f0a4aSAndrew Moore #include <sys/disklabel.h> 59b99f0a4aSAndrew Moore #include <sys/buf.h> 60b99f0a4aSAndrew Moore #include <sys/uio.h> 61b99f0a4aSAndrew Moore #include <sys/malloc.h> 62b99f0a4aSAndrew Moore #include <sys/syslog.h> 63f540b106SGarrett Wollman #include <i386/isa/isa.h> 64f540b106SGarrett Wollman #include <i386/isa/isa_device.h> 65f540b106SGarrett Wollman #include <i386/isa/fdreg.h> 66f540b106SGarrett Wollman #include <i386/isa/fdc.h> 67f540b106SGarrett Wollman #include <i386/isa/icu.h> 68f540b106SGarrett Wollman #include <i386/isa/rtc.h> 695b81b6b3SRodney W. Grimes 70b99f0a4aSAndrew Moore #if NFT > 0 71b99f0a4aSAndrew Moore extern int ftopen(), ftintr(), ftattach(), ftclose(), ftioctl(); 72b99f0a4aSAndrew Moore #endif 735b81b6b3SRodney W. Grimes 74b2be795bSAndrey A. Chernov #define RAW_PART 2 75b2be795bSAndrey A. Chernov 765b81b6b3SRodney W. Grimes #define b_cylin b_resid 775b81b6b3SRodney W. Grimes #define FDBLK 512 785b81b6b3SRodney W. Grimes 79b39c878eSAndrey A. Chernov /* misuse a flag to identify format operation */ 80b39c878eSAndrey A. Chernov #define B_FORMAT B_XXX 815b81b6b3SRodney W. Grimes 82b39c878eSAndrey A. Chernov #define NUMTYPES 14 83b39c878eSAndrey A. Chernov #define NUMDENS (NUMTYPES - 6) 847ca0641bSAndrey A. Chernov 85b99f0a4aSAndrew Moore /* This defines (-1) must match index for fd_types */ 86b99f0a4aSAndrew Moore #define F_TAPE_TYPE 0x020 /* bit for fd_types to indicate tape */ 87b99f0a4aSAndrew Moore #define NO_TYPE 0 /* must match NO_TYPE in ft.c */ 88b99f0a4aSAndrew Moore #define FD_1720 1 89b99f0a4aSAndrew Moore #define FD_1480 2 90b99f0a4aSAndrew Moore #define FD_1440 3 91b99f0a4aSAndrew Moore #define FD_1200 4 92b99f0a4aSAndrew Moore #define FD_820 5 93b99f0a4aSAndrew Moore #define FD_800 6 94b99f0a4aSAndrew Moore #define FD_720 7 95b99f0a4aSAndrew Moore #define FD_360 8 96ed2fa05eSAndrey A. Chernov 97b99f0a4aSAndrew Moore #define FD_1480in5_25 9 98b99f0a4aSAndrew Moore #define FD_1440in5_25 10 99b99f0a4aSAndrew Moore #define FD_820in5_25 11 100b99f0a4aSAndrew Moore #define FD_800in5_25 12 101b99f0a4aSAndrew Moore #define FD_720in5_25 13 102b99f0a4aSAndrew Moore #define FD_360in5_25 14 103b99f0a4aSAndrew Moore 1047ca0641bSAndrey A. Chernov 1055b81b6b3SRodney W. Grimes struct fd_type fd_types[NUMTYPES] = 1065b81b6b3SRodney W. Grimes { 107126518a1SAndrey A. Chernov { 21,2,0xFF,0x04,82,3444,1,FDC_500KBPS,2,0x0C,2 }, /* 1.72M in HD 3.5in */ 108126518a1SAndrey A. Chernov { 18,2,0xFF,0x1B,82,2952,1,FDC_500KBPS,2,0x6C,1 }, /* 1.48M in HD 3.5in */ 109126518a1SAndrey A. Chernov { 18,2,0xFF,0x1B,80,2880,1,FDC_500KBPS,2,0x6C,1 }, /* 1.44M in HD 3.5in */ 110126518a1SAndrey A. Chernov { 15,2,0xFF,0x1B,80,2400,1,FDC_500KBPS,2,0x54,1 }, /* 1.2M in HD 5.25/3.5 */ 111126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,82,1640,1,FDC_250KBPS,2,0x2E,1 }, /* 820K in HD 3.5in */ 112126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,80,1600,1,FDC_250KBPS,2,0x2E,1 }, /* 800K in HD 3.5in */ 113126518a1SAndrey A. Chernov { 9,2,0xFF,0x20,80,1440,1,FDC_250KBPS,2,0x50,1 }, /* 720K in HD 3.5in */ 114b0568305SAndrey A. Chernov { 9,2,0xFF,0x2A,40, 720,1,FDC_250KBPS,2,0x50,1 }, /* 360K in DD 5.25in */ 115ed2fa05eSAndrey A. Chernov 116126518a1SAndrey A. Chernov { 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,0x02,2 }, /* 1.48M in HD 5.25in */ 117126518a1SAndrey A. Chernov { 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,0x02,2 }, /* 1.44M in HD 5.25in */ 118126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,82,1640,1,FDC_300KBPS,2,0x2E,1 }, /* 820K in HD 5.25in */ 119126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,80,1600,1,FDC_300KBPS,2,0x2E,1 }, /* 800K in HD 5.25in */ 120126518a1SAndrey A. Chernov { 9,2,0xFF,0x20,80,1440,1,FDC_300KBPS,2,0x50,1 }, /* 720K in HD 5.25in */ 121126518a1SAndrey A. Chernov { 9,2,0xFF,0x23,40, 720,2,FDC_300KBPS,2,0x50,1 }, /* 360K in HD 5.25in */ 1225b81b6b3SRodney W. Grimes }; 1235b81b6b3SRodney W. Grimes 124b99f0a4aSAndrew Moore #define DRVS_PER_CTLR 2 /* 2 floppies */ 1255b81b6b3SRodney W. Grimes /***********************************************************************\ 1265b81b6b3SRodney W. Grimes * Per controller structure. * 1275b81b6b3SRodney W. Grimes \***********************************************************************/ 128b99f0a4aSAndrew Moore struct fdc_data fdc_data[NFDC]; 1295b81b6b3SRodney W. Grimes 1305b81b6b3SRodney W. Grimes /***********************************************************************\ 1315b81b6b3SRodney W. Grimes * Per drive structure. * 132b99f0a4aSAndrew Moore * N per controller (DRVS_PER_CTLR) * 1335b81b6b3SRodney W. Grimes \***********************************************************************/ 1345b81b6b3SRodney W. Grimes struct fd_data { 135b99f0a4aSAndrew Moore struct fdc_data *fdc; /* pointer to controller structure */ 1365b81b6b3SRodney W. Grimes int fdsu; /* this units number on this controller */ 1375b81b6b3SRodney W. Grimes int type; /* Drive type (HD, DD */ 1385b81b6b3SRodney W. Grimes struct fd_type *ft; /* pointer to the type descriptor */ 1395b81b6b3SRodney W. Grimes int flags; 1405b81b6b3SRodney W. Grimes #define FD_OPEN 0x01 /* it's open */ 1415b81b6b3SRodney W. Grimes #define FD_ACTIVE 0x02 /* it's active */ 1425b81b6b3SRodney W. Grimes #define FD_MOTOR 0x04 /* motor should be on */ 1435b81b6b3SRodney W. Grimes #define FD_MOTOR_WAIT 0x08 /* motor coming up */ 1445b81b6b3SRodney W. Grimes int skip; 1455b81b6b3SRodney W. Grimes int hddrv; 1465b81b6b3SRodney W. Grimes int track; /* where we think the head is */ 1475b81b6b3SRodney W. Grimes } fd_data[NFD]; 1485b81b6b3SRodney W. Grimes 1495b81b6b3SRodney W. Grimes /***********************************************************************\ 1505b81b6b3SRodney W. Grimes * Throughout this file the following conventions will be used: * 1515b81b6b3SRodney W. Grimes * fd is a pointer to the fd_data struct for the drive in question * 1525b81b6b3SRodney W. Grimes * fdc is a pointer to the fdc_data struct for the controller * 1535b81b6b3SRodney W. Grimes * fdu is the floppy drive unit number * 1545b81b6b3SRodney W. Grimes * fdcu is the floppy controller unit number * 1555b81b6b3SRodney W. Grimes * fdsu is the floppy drive unit number on that controller. (sub-unit) * 1565b81b6b3SRodney W. Grimes \***********************************************************************/ 157b99f0a4aSAndrew Moore 158b99f0a4aSAndrew Moore #define id_physid id_scsiid /* this biotab field doubles as a field */ 159b99f0a4aSAndrew Moore /* for the physical unit number on the controller */ 1605b81b6b3SRodney W. Grimes 161aaf08d94SGarrett Wollman static int retrier(fdcu_t); 162aaf08d94SGarrett Wollman 1635b81b6b3SRodney W. Grimes #define DEVIDLE 0 1645b81b6b3SRodney W. Grimes #define FINDWORK 1 1655b81b6b3SRodney W. Grimes #define DOSEEK 2 1665b81b6b3SRodney W. Grimes #define SEEKCOMPLETE 3 1675b81b6b3SRodney W. Grimes #define IOCOMPLETE 4 1685b81b6b3SRodney W. Grimes #define RECALCOMPLETE 5 1695b81b6b3SRodney W. Grimes #define STARTRECAL 6 1705b81b6b3SRodney W. Grimes #define RESETCTLR 7 1715b81b6b3SRodney W. Grimes #define SEEKWAIT 8 1725b81b6b3SRodney W. Grimes #define RECALWAIT 9 1735b81b6b3SRodney W. Grimes #define MOTORWAIT 10 1745b81b6b3SRodney W. Grimes #define IOTIMEDOUT 11 1755b81b6b3SRodney W. Grimes 1765b81b6b3SRodney W. Grimes #ifdef DEBUG 1775b81b6b3SRodney W. Grimes char *fdstates[] = 1785b81b6b3SRodney W. Grimes { 1795b81b6b3SRodney W. Grimes "DEVIDLE", 1805b81b6b3SRodney W. Grimes "FINDWORK", 1815b81b6b3SRodney W. Grimes "DOSEEK", 1825b81b6b3SRodney W. Grimes "SEEKCOMPLETE", 1835b81b6b3SRodney W. Grimes "IOCOMPLETE", 1845b81b6b3SRodney W. Grimes "RECALCOMPLETE", 1855b81b6b3SRodney W. Grimes "STARTRECAL", 1865b81b6b3SRodney W. Grimes "RESETCTLR", 1875b81b6b3SRodney W. Grimes "SEEKWAIT", 1885b81b6b3SRodney W. Grimes "RECALWAIT", 1895b81b6b3SRodney W. Grimes "MOTORWAIT", 1905b81b6b3SRodney W. Grimes "IOTIMEDOUT" 1915b81b6b3SRodney W. Grimes }; 1925b81b6b3SRodney W. Grimes 1935b81b6b3SRodney W. Grimes 1945b81b6b3SRodney W. Grimes int fd_debug = 1; 1955b81b6b3SRodney W. Grimes #define TRACE0(arg) if(fd_debug) printf(arg) 1965b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2) 197381fe1aaSGarrett Wollman #else /* DEBUG */ 1985b81b6b3SRodney W. Grimes #define TRACE0(arg) 1995b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) 200381fe1aaSGarrett Wollman #endif /* DEBUG */ 2015b81b6b3SRodney W. Grimes 202381fe1aaSGarrett Wollman static void fdstart(fdcu_t); 203381fe1aaSGarrett Wollman void fdintr(fdcu_t); 204d0917939SPaul Richards static timeout_t fd_turnoff; 2055b81b6b3SRodney W. Grimes 2065b81b6b3SRodney W. Grimes /****************************************************************************/ 2075b81b6b3SRodney W. Grimes /* autoconfiguration stuff */ 2085b81b6b3SRodney W. Grimes /****************************************************************************/ 209381fe1aaSGarrett Wollman static int fdprobe(struct isa_device *); 210381fe1aaSGarrett Wollman static int fdattach(struct isa_device *); 2115b81b6b3SRodney W. Grimes 212b99f0a4aSAndrew Moore struct isa_driver fdcdriver = { 213b99f0a4aSAndrew Moore fdprobe, fdattach, "fdc", 2145b81b6b3SRodney W. Grimes }; 2155b81b6b3SRodney W. Grimes 2165b81b6b3SRodney W. Grimes /* 2175b81b6b3SRodney W. Grimes * probe for existance of controller 2185b81b6b3SRodney W. Grimes */ 219381fe1aaSGarrett Wollman int 2205b81b6b3SRodney W. Grimes fdprobe(dev) 2215b81b6b3SRodney W. Grimes struct isa_device *dev; 2225b81b6b3SRodney W. Grimes { 2235b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2245b81b6b3SRodney W. Grimes if(fdc_data[fdcu].flags & FDC_ATTACHED) 2255b81b6b3SRodney W. Grimes { 2265b81b6b3SRodney W. Grimes printf("fdc: same unit (%d) used multiple times\n",fdcu); 2275b81b6b3SRodney W. Grimes return 0; 2285b81b6b3SRodney W. Grimes } 2295b81b6b3SRodney W. Grimes 2305b81b6b3SRodney W. Grimes fdc_data[fdcu].baseport = dev->id_iobase; 2315b81b6b3SRodney W. Grimes 23216111cedSAndrew Moore /* First - lets reset the floppy controller */ 23316111cedSAndrew Moore 23416111cedSAndrew Moore outb(dev->id_iobase+fdout,0); 23516111cedSAndrew Moore DELAY(100); 23616111cedSAndrew Moore outb(dev->id_iobase+fdout,FDO_FRST); 23716111cedSAndrew Moore 2385b81b6b3SRodney W. Grimes /* see if it can handle a command */ 2395b81b6b3SRodney W. Grimes if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0) 2405b81b6b3SRodney W. Grimes { 2415b81b6b3SRodney W. Grimes return(0); 2425b81b6b3SRodney W. Grimes } 2435b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 2445b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 2455b81b6b3SRodney W. Grimes return (IO_FDCSIZE); 2465b81b6b3SRodney W. Grimes } 2475b81b6b3SRodney W. Grimes 2485b81b6b3SRodney W. Grimes /* 2495b81b6b3SRodney W. Grimes * wire controller into system, look for floppy units 2505b81b6b3SRodney W. Grimes */ 251381fe1aaSGarrett Wollman int 2525b81b6b3SRodney W. Grimes fdattach(dev) 2535b81b6b3SRodney W. Grimes struct isa_device *dev; 2545b81b6b3SRodney W. Grimes { 2555b81b6b3SRodney W. Grimes unsigned fdt,st0, cyl; 2565b81b6b3SRodney W. Grimes int hdr; 2575b81b6b3SRodney W. Grimes fdu_t fdu; 2585b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2595b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 2605b81b6b3SRodney W. Grimes fd_p fd; 2615b81b6b3SRodney W. Grimes int fdsu; 262b99f0a4aSAndrew Moore struct isa_device *fdup; 2635b81b6b3SRodney W. Grimes 2645b81b6b3SRodney W. Grimes fdc->fdcu = fdcu; 2655b81b6b3SRodney W. Grimes fdc->flags |= FDC_ATTACHED; 2665b81b6b3SRodney W. Grimes fdc->dmachan = dev->id_drq; 2675b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 2685b81b6b3SRodney W. Grimes hdr = 0; 269b99f0a4aSAndrew Moore printf("fdc%d:", fdcu); 2705b81b6b3SRodney W. Grimes 2715b81b6b3SRodney W. Grimes /* check for each floppy drive */ 272b99f0a4aSAndrew Moore for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { 273b99f0a4aSAndrew Moore if (fdup->id_iobase != dev->id_iobase) 274b99f0a4aSAndrew Moore continue; 275b99f0a4aSAndrew Moore fdu = fdup->id_unit; 276b99f0a4aSAndrew Moore fd = &fd_data[fdu]; 277b99f0a4aSAndrew Moore if (fdu >= (NFD+NFT)) 278b99f0a4aSAndrew Moore continue; 279b99f0a4aSAndrew Moore fdsu = fdup->id_physid; 280b99f0a4aSAndrew Moore /* look up what bios thinks we have */ 281b99f0a4aSAndrew Moore switch (fdu) { 282b99f0a4aSAndrew Moore case 0: fdt = (rtcin(RTC_FDISKETTE) & 0xf0); 283b99f0a4aSAndrew Moore break; 284b99f0a4aSAndrew Moore case 1: fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); 285b99f0a4aSAndrew Moore break; 286b99f0a4aSAndrew Moore default: fdt = RTCFDT_NONE; 287b99f0a4aSAndrew Moore break; 288b99f0a4aSAndrew Moore } 2895b81b6b3SRodney W. Grimes /* is there a unit? */ 290b99f0a4aSAndrew Moore if ((fdt == RTCFDT_NONE) 291b99f0a4aSAndrew Moore #if NFT > 0 292b99f0a4aSAndrew Moore || (fdsu >= DRVS_PER_CTLR)) { 293b99f0a4aSAndrew Moore #else 294b99f0a4aSAndrew Moore ) { 29556ef0285SAndrew Moore fd->type = NO_TYPE; 296b99f0a4aSAndrew Moore #endif 297b99f0a4aSAndrew Moore #if NFT > 0 298b99f0a4aSAndrew Moore /* If BIOS says no floppy, or > 2nd device */ 299b99f0a4aSAndrew Moore /* Probe for and attach a floppy tape. */ 300b99f0a4aSAndrew Moore if (ftattach(dev, fdup)) 301b99f0a4aSAndrew Moore continue; 30256ef0285SAndrew Moore if (fdsu < DRVS_PER_CTLR) 303b99f0a4aSAndrew Moore fd->type = NO_TYPE; 30456ef0285SAndrew Moore #endif 3055b81b6b3SRodney W. Grimes continue; 306f5f7ba03SJordan K. Hubbard } 3075b81b6b3SRodney W. Grimes 3085b81b6b3SRodney W. Grimes #ifdef notyet 3095b81b6b3SRodney W. Grimes /* select it */ 3105b81b6b3SRodney W. Grimes fd_turnon1(fdu); 3115b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 3125b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 3135b81b6b3SRodney W. Grimes out_fdc(fdcu,fdsu); 3145b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 3155b81b6b3SRodney W. Grimes 3165b81b6b3SRodney W. Grimes /* anything responding */ 3175b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 3185b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 3195b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 3205b81b6b3SRodney W. Grimes if (st0 & 0xd0) 3215b81b6b3SRodney W. Grimes continue; 3225b81b6b3SRodney W. Grimes 3235b81b6b3SRodney W. Grimes #endif 324b99f0a4aSAndrew Moore fd->track = -2; 325b99f0a4aSAndrew Moore fd->fdc = fdc; 326b99f0a4aSAndrew Moore fd->fdsu = fdsu; 327b99f0a4aSAndrew Moore printf(" [%d: fd%d: ", fdsu, fdu); 3285b81b6b3SRodney W. Grimes 329b99f0a4aSAndrew Moore switch (fdt) { 3307ca0641bSAndrey A. Chernov case RTCFDT_12M: 331b99f0a4aSAndrew Moore printf("1.2MB 5.25in]"); 332b99f0a4aSAndrew Moore fd->type = FD_1200; 3337ca0641bSAndrey A. Chernov break; 3347ca0641bSAndrey A. Chernov case RTCFDT_144M: 335b99f0a4aSAndrew Moore printf("1.44MB 3.5in]"); 336b99f0a4aSAndrew Moore fd->type = FD_1440; 3377ca0641bSAndrey A. Chernov break; 3387ca0641bSAndrey A. Chernov case RTCFDT_360K: 339b99f0a4aSAndrew Moore printf("360KB 5.25in]"); 340b99f0a4aSAndrew Moore fd->type = FD_360; 3417ca0641bSAndrey A. Chernov break; 342ed2fa05eSAndrey A. Chernov case RTCFDT_720K: 343b99f0a4aSAndrew Moore printf("720KB 3.5in]"); 344b99f0a4aSAndrew Moore fd->type = FD_720; 345ed2fa05eSAndrey A. Chernov break; 3467ca0641bSAndrey A. Chernov default: 347b99f0a4aSAndrew Moore printf("unknown]"); 348b99f0a4aSAndrew Moore fd->type = NO_TYPE; 3497ca0641bSAndrey A. Chernov break; 3505b81b6b3SRodney W. Grimes } 3515b81b6b3SRodney W. Grimes 35226f9a767SRodney W. Grimes fd_turnoff((caddr_t)fdu); 3535b81b6b3SRodney W. Grimes hdr = 1; 3545b81b6b3SRodney W. Grimes } 355b99f0a4aSAndrew Moore printf("\n"); 3565b81b6b3SRodney W. Grimes 3575b81b6b3SRodney W. Grimes /* Set transfer to 500kbps */ 3585b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,0); /*XXX*/ 359381fe1aaSGarrett Wollman return 1; 3605b81b6b3SRodney W. Grimes } 3615b81b6b3SRodney W. Grimes 3625b81b6b3SRodney W. Grimes int 3635b81b6b3SRodney W. Grimes fdsize(dev) 3645b81b6b3SRodney W. Grimes dev_t dev; 3655b81b6b3SRodney W. Grimes { 3665b81b6b3SRodney W. Grimes return(0); 3675b81b6b3SRodney W. Grimes } 3685b81b6b3SRodney W. Grimes 3695b81b6b3SRodney W. Grimes /****************************************************************************/ 3705b81b6b3SRodney W. Grimes /* fdstrategy */ 3715b81b6b3SRodney W. Grimes /****************************************************************************/ 372381fe1aaSGarrett Wollman void fdstrategy(struct buf *bp) 3735b81b6b3SRodney W. Grimes { 3745b81b6b3SRodney W. Grimes register struct buf *dp,*dp0,*dp1; 3755b81b6b3SRodney W. Grimes long nblocks,blknum; 3765b81b6b3SRodney W. Grimes int s; 3775b81b6b3SRodney W. Grimes fdcu_t fdcu; 3785b81b6b3SRodney W. Grimes fdu_t fdu; 3795b81b6b3SRodney W. Grimes fdc_p fdc; 3805b81b6b3SRodney W. Grimes fd_p fd; 3815b81b6b3SRodney W. Grimes 3825b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 3835b81b6b3SRodney W. Grimes fd = &fd_data[fdu]; 3845b81b6b3SRodney W. Grimes fdc = fd->fdc; 3855b81b6b3SRodney W. Grimes fdcu = fdc->fdcu; 3865b81b6b3SRodney W. Grimes 387b99f0a4aSAndrew Moore #if NFT > 0 388b99f0a4aSAndrew Moore /* check for controller already busy with tape */ 389b99f0a4aSAndrew Moore if (fdc->flags & FDC_TAPE_BUSY) { 390b99f0a4aSAndrew Moore bp->b_error = EBUSY; 391b99f0a4aSAndrew Moore bp->b_flags |= B_ERROR; 392b99f0a4aSAndrew Moore return; 393b99f0a4aSAndrew Moore } 394b99f0a4aSAndrew Moore #endif 395a60eff27SNate Williams if ((fdu >= NFD) || (bp->b_blkno < 0)) { 3965b81b6b3SRodney W. Grimes printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n", 3975b81b6b3SRodney W. Grimes fdu, bp->b_blkno, bp->b_bcount); 3985b81b6b3SRodney W. Grimes pg("fd:error in fdstrategy"); 3995b81b6b3SRodney W. Grimes bp->b_error = EINVAL; 4005b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 4015b81b6b3SRodney W. Grimes goto bad; 4025b81b6b3SRodney W. Grimes } 4035b81b6b3SRodney W. Grimes /* 4045b81b6b3SRodney W. Grimes * Set up block calculations. 4055b81b6b3SRodney W. Grimes */ 4065b81b6b3SRodney W. Grimes blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK; 4075b81b6b3SRodney W. Grimes nblocks = fd->ft->size; 4085b81b6b3SRodney W. Grimes if (blknum + (bp->b_bcount / FDBLK) > nblocks) { 4095b81b6b3SRodney W. Grimes if (blknum == nblocks) { 4105b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount; 4115b81b6b3SRodney W. Grimes } else { 4125b81b6b3SRodney W. Grimes bp->b_error = ENOSPC; 4135b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 4145b81b6b3SRodney W. Grimes } 4155b81b6b3SRodney W. Grimes goto bad; 4165b81b6b3SRodney W. Grimes } 4175b81b6b3SRodney W. Grimes bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads); 4180e195446SDavid Greenman bp->b_pblkno = bp->b_blkno; 4195b81b6b3SRodney W. Grimes dp = &(fdc->head); 4205b81b6b3SRodney W. Grimes s = splbio(); 4215b81b6b3SRodney W. Grimes disksort(dp, bp); 422d0917939SPaul Richards untimeout(fd_turnoff, (caddr_t)fdu); /* a good idea */ 4235b81b6b3SRodney W. Grimes fdstart(fdcu); 4245b81b6b3SRodney W. Grimes splx(s); 4255b81b6b3SRodney W. Grimes return; 4265b81b6b3SRodney W. Grimes 4275b81b6b3SRodney W. Grimes bad: 4285b81b6b3SRodney W. Grimes biodone(bp); 429b39c878eSAndrey A. Chernov return; 4305b81b6b3SRodney W. Grimes } 4315b81b6b3SRodney W. Grimes 4325b81b6b3SRodney W. Grimes /****************************************************************************/ 4335b81b6b3SRodney W. Grimes /* motor control stuff */ 4345b81b6b3SRodney W. Grimes /* remember to not deselect the drive we're working on */ 4355b81b6b3SRodney W. Grimes /****************************************************************************/ 436381fe1aaSGarrett Wollman void 437f5f7ba03SJordan K. Hubbard set_motor(fdcu, fdu, reset) 438f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 439f5f7ba03SJordan K. Hubbard fdu_t fdu; 440f5f7ba03SJordan K. Hubbard int reset; 4415b81b6b3SRodney W. Grimes { 4425b81b6b3SRodney W. Grimes int m0,m1; 4435b81b6b3SRodney W. Grimes int selunit; 4445b81b6b3SRodney W. Grimes fd_p fd; 4455b81b6b3SRodney W. Grimes if(fd = fdc_data[fdcu].fd)/* yes an assign! */ 4465b81b6b3SRodney W. Grimes { 4475b81b6b3SRodney W. Grimes selunit = fd->fdsu; 4485b81b6b3SRodney W. Grimes } 4495b81b6b3SRodney W. Grimes else 4505b81b6b3SRodney W. Grimes { 4515b81b6b3SRodney W. Grimes selunit = 0; 4525b81b6b3SRodney W. Grimes } 4535b81b6b3SRodney W. Grimes m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR; 4545b81b6b3SRodney W. Grimes m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR; 4555b81b6b3SRodney W. Grimes outb(fdc_data[fdcu].baseport+fdout, 4565b81b6b3SRodney W. Grimes selunit 4575b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4585b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4595b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0)); 4605b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdout]",( 4615b81b6b3SRodney W. Grimes selunit 4625b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4635b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4645b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0))); 4655b81b6b3SRodney W. Grimes } 4665b81b6b3SRodney W. Grimes 467381fe1aaSGarrett Wollman static void 468d0917939SPaul Richards fd_turnoff(void *arg1) 4695b81b6b3SRodney W. Grimes { 470381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 471f5f7ba03SJordan K. Hubbard int s; 472f5f7ba03SJordan K. Hubbard 4735b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 474f5f7ba03SJordan K. Hubbard s = splbio(); 4755b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR; 4765b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 477f5f7ba03SJordan K. Hubbard splx(s); 4785b81b6b3SRodney W. Grimes } 4795b81b6b3SRodney W. Grimes 480381fe1aaSGarrett Wollman void 481d0917939SPaul Richards fd_motor_on(void *arg1) 4825b81b6b3SRodney W. Grimes { 483381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 484f5f7ba03SJordan K. Hubbard int s; 485f5f7ba03SJordan K. Hubbard 4865b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 487f5f7ba03SJordan K. Hubbard s = splbio(); 4885b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR_WAIT; 4895b81b6b3SRodney W. Grimes if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) 4905b81b6b3SRodney W. Grimes { 491f5f7ba03SJordan K. Hubbard fdintr(fd->fdc->fdcu); 4925b81b6b3SRodney W. Grimes } 493f5f7ba03SJordan K. Hubbard splx(s); 4945b81b6b3SRodney W. Grimes } 4955b81b6b3SRodney W. Grimes 496381fe1aaSGarrett Wollman static void fd_turnon1(fdu_t); 497381fe1aaSGarrett Wollman 498381fe1aaSGarrett Wollman void 499f5f7ba03SJordan K. Hubbard fd_turnon(fdu) 500f5f7ba03SJordan K. Hubbard fdu_t fdu; 5015b81b6b3SRodney W. Grimes { 5025b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 5035b81b6b3SRodney W. Grimes if(!(fd->flags & FD_MOTOR)) 5045b81b6b3SRodney W. Grimes { 5055b81b6b3SRodney W. Grimes fd_turnon1(fdu); 5065b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR_WAIT; 507d0917939SPaul Richards timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ 5085b81b6b3SRodney W. Grimes } 5095b81b6b3SRodney W. Grimes } 5105b81b6b3SRodney W. Grimes 511381fe1aaSGarrett Wollman static void 512381fe1aaSGarrett Wollman fd_turnon1(fdu_t fdu) 5135b81b6b3SRodney W. Grimes { 5145b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 5155b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR; 5165b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 5175b81b6b3SRodney W. Grimes } 5185b81b6b3SRodney W. Grimes 5195b81b6b3SRodney W. Grimes /****************************************************************************/ 5205b81b6b3SRodney W. Grimes /* fdc in/out */ 5215b81b6b3SRodney W. Grimes /****************************************************************************/ 5225b81b6b3SRodney W. Grimes int 523f5f7ba03SJordan K. Hubbard in_fdc(fdcu) 524f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 5255b81b6b3SRodney W. Grimes { 5265b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5275b81b6b3SRodney W. Grimes int i, j = 100000; 5285b81b6b3SRodney W. Grimes while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM)) 5295b81b6b3SRodney W. Grimes != (NE7_DIO|NE7_RQM) && j-- > 0) 5305b81b6b3SRodney W. Grimes if (i == NE7_RQM) return -1; 5315b81b6b3SRodney W. Grimes if (j <= 0) 5325b81b6b3SRodney W. Grimes return(-1); 5335b81b6b3SRodney W. Grimes #ifdef DEBUG 5345b81b6b3SRodney W. Grimes i = inb(baseport+fddata); 5355b81b6b3SRodney W. Grimes TRACE1("[fddata->0x%x]",(unsigned char)i); 5365b81b6b3SRodney W. Grimes return(i); 5375b81b6b3SRodney W. Grimes #else 5385b81b6b3SRodney W. Grimes return inb(baseport+fddata); 5395b81b6b3SRodney W. Grimes #endif 5405b81b6b3SRodney W. Grimes } 5415b81b6b3SRodney W. Grimes 542381fe1aaSGarrett Wollman int 543f5f7ba03SJordan K. Hubbard out_fdc(fdcu, x) 544f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 545f5f7ba03SJordan K. Hubbard int x; 5465b81b6b3SRodney W. Grimes { 5475b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5483b3837dbSRodney W. Grimes int i; 5495b81b6b3SRodney W. Grimes 5503b3837dbSRodney W. Grimes /* Check that the direction bit is set */ 5513b3837dbSRodney W. Grimes i = 100000; 5525b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0); 5533b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5543b3837dbSRodney W. Grimes 5553b3837dbSRodney W. Grimes /* Check that the floppy controller is ready for a command */ 5563b3837dbSRodney W. Grimes i = 100000; 5575b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0); 5583b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5593b3837dbSRodney W. Grimes 5603b3837dbSRodney W. Grimes /* Send the command and return */ 5615b81b6b3SRodney W. Grimes outb(baseport+fddata,x); 5625b81b6b3SRodney W. Grimes TRACE1("[0x%x->fddata]",x); 5635b81b6b3SRodney W. Grimes return (0); 5645b81b6b3SRodney W. Grimes } 5655b81b6b3SRodney W. Grimes 5665b81b6b3SRodney W. Grimes /****************************************************************************/ 5675b81b6b3SRodney W. Grimes /* fdopen/fdclose */ 5685b81b6b3SRodney W. Grimes /****************************************************************************/ 569381fe1aaSGarrett Wollman int 5705b81b6b3SRodney W. Grimes Fdopen(dev, flags) 5715b81b6b3SRodney W. Grimes dev_t dev; 5725b81b6b3SRodney W. Grimes int flags; 5735b81b6b3SRodney W. Grimes { 5745b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 57520a29168SAndrey A. Chernov int type = FDTYPE(minor(dev)); 576b99f0a4aSAndrew Moore fdc_p fdc; 5775b81b6b3SRodney W. Grimes 578b99f0a4aSAndrew Moore #if NFT > 0 579b99f0a4aSAndrew Moore /* check for a tape open */ 580b99f0a4aSAndrew Moore if (type & F_TAPE_TYPE) 581b99f0a4aSAndrew Moore return(ftopen(dev, flags)); 582b99f0a4aSAndrew Moore #endif 5835b81b6b3SRodney W. Grimes /* check bounds */ 584b99f0a4aSAndrew Moore if (fdu >= NFD) 585b99f0a4aSAndrew Moore return(ENXIO); 586b99f0a4aSAndrew Moore fdc = fd_data[fdu].fdc; 587b99f0a4aSAndrew Moore if ((fdc == NULL) || (fd_data[fdu].type == NO_TYPE)) 588b99f0a4aSAndrew Moore return(ENXIO); 589b99f0a4aSAndrew Moore if (type > NUMDENS) 590b99f0a4aSAndrew Moore return(ENXIO); 5917ca0641bSAndrey A. Chernov if (type == 0) 5927ca0641bSAndrey A. Chernov type = fd_data[fdu].type; 5937ca0641bSAndrey A. Chernov else { 5947ca0641bSAndrey A. Chernov if (type != fd_data[fdu].type) { 595fa4700b4SAndrey A. Chernov switch (fd_data[fdu].type) { 5967ca0641bSAndrey A. Chernov case FD_360: 5977ca0641bSAndrey A. Chernov return(ENXIO); 598ed2fa05eSAndrey A. Chernov case FD_720: 599b39c878eSAndrey A. Chernov if ( type != FD_820 600b39c878eSAndrey A. Chernov && type != FD_800 601ed2fa05eSAndrey A. Chernov ) 602ed2fa05eSAndrey A. Chernov return(ENXIO); 603ed2fa05eSAndrey A. Chernov break; 6047ca0641bSAndrey A. Chernov case FD_1200: 605b39c878eSAndrey A. Chernov switch (type) { 606b39c878eSAndrey A. Chernov case FD_1480: 607b39c878eSAndrey A. Chernov type = FD_1480in5_25; 608fa4700b4SAndrey A. Chernov break; 6097ca0641bSAndrey A. Chernov case FD_1440: 610b39c878eSAndrey A. Chernov type = FD_1440in5_25; 611b39c878eSAndrey A. Chernov break; 612b39c878eSAndrey A. Chernov case FD_820: 613b39c878eSAndrey A. Chernov type = FD_820in5_25; 614b39c878eSAndrey A. Chernov break; 615b39c878eSAndrey A. Chernov case FD_800: 616b39c878eSAndrey A. Chernov type = FD_800in5_25; 617b39c878eSAndrey A. Chernov break; 618b39c878eSAndrey A. Chernov case FD_720: 619b39c878eSAndrey A. Chernov type = FD_720in5_25; 620b39c878eSAndrey A. Chernov break; 621b39c878eSAndrey A. Chernov case FD_360: 622b39c878eSAndrey A. Chernov type = FD_360in5_25; 623b39c878eSAndrey A. Chernov break; 624b39c878eSAndrey A. Chernov default: 625b39c878eSAndrey A. Chernov return(ENXIO); 626b39c878eSAndrey A. Chernov } 627b39c878eSAndrey A. Chernov break; 628b39c878eSAndrey A. Chernov case FD_1440: 629b39c878eSAndrey A. Chernov if ( type != FD_1720 630b39c878eSAndrey A. Chernov && type != FD_1480 631ed2fa05eSAndrey A. Chernov && type != FD_1200 632b39c878eSAndrey A. Chernov && type != FD_820 633b39c878eSAndrey A. Chernov && type != FD_800 634b39c878eSAndrey A. Chernov && type != FD_720 6357ca0641bSAndrey A. Chernov ) 636dffff499SAndrey A. Chernov return(ENXIO); 637fa4700b4SAndrey A. Chernov break; 6387ca0641bSAndrey A. Chernov } 6397ca0641bSAndrey A. Chernov } 640fa4700b4SAndrey A. Chernov } 641b99f0a4aSAndrew Moore fd_data[fdu].ft = fd_types + type - 1; 6425b81b6b3SRodney W. Grimes fd_data[fdu].flags |= FD_OPEN; 6435b81b6b3SRodney W. Grimes 6445b81b6b3SRodney W. Grimes return 0; 6455b81b6b3SRodney W. Grimes } 6465b81b6b3SRodney W. Grimes 647381fe1aaSGarrett Wollman int 6485b81b6b3SRodney W. Grimes fdclose(dev, flags) 6495b81b6b3SRodney W. Grimes dev_t dev; 650381fe1aaSGarrett Wollman int flags; 6515b81b6b3SRodney W. Grimes { 6525b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 653b99f0a4aSAndrew Moore int type = FDTYPE(minor(dev)); 654b99f0a4aSAndrew Moore 655b99f0a4aSAndrew Moore #if NFT > 0 656b99f0a4aSAndrew Moore if (type & F_TAPE_TYPE) 657b99f0a4aSAndrew Moore return ftclose(0); 658b99f0a4aSAndrew Moore #endif 6595b81b6b3SRodney W. Grimes fd_data[fdu].flags &= ~FD_OPEN; 6605b81b6b3SRodney W. Grimes return(0); 6615b81b6b3SRodney W. Grimes } 6625b81b6b3SRodney W. Grimes 6635b81b6b3SRodney W. Grimes 6645b81b6b3SRodney W. Grimes /***************************************************************\ 6655b81b6b3SRodney W. Grimes * fdstart * 6665b81b6b3SRodney W. Grimes * We have just queued something.. if the controller is not busy * 6675b81b6b3SRodney W. Grimes * then simulate the case where it has just finished a command * 6685b81b6b3SRodney W. Grimes * So that it (the interrupt routine) looks on the queue for more* 6695b81b6b3SRodney W. Grimes * work to do and picks up what we just added. * 6705b81b6b3SRodney W. Grimes * If the controller is already busy, we need do nothing, as it * 6715b81b6b3SRodney W. Grimes * will pick up our work when the present work completes * 6725b81b6b3SRodney W. Grimes \***************************************************************/ 673381fe1aaSGarrett Wollman static void 674f5f7ba03SJordan K. Hubbard fdstart(fdcu) 675f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 6765b81b6b3SRodney W. Grimes { 6775b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 6785b81b6b3SRodney W. Grimes int s; 6795b81b6b3SRodney W. Grimes fdu_t fdu; 6805b81b6b3SRodney W. Grimes 6815b81b6b3SRodney W. Grimes s = splbio(); 6825b81b6b3SRodney W. Grimes if(fdc_data[fdcu].state == DEVIDLE) 6835b81b6b3SRodney W. Grimes { 6845b81b6b3SRodney W. Grimes fdintr(fdcu); 6855b81b6b3SRodney W. Grimes } 6865b81b6b3SRodney W. Grimes splx(s); 6875b81b6b3SRodney W. Grimes } 6885b81b6b3SRodney W. Grimes 689381fe1aaSGarrett Wollman static void 690d0917939SPaul Richards fd_timeout(void *arg1) 6915b81b6b3SRodney W. Grimes { 692381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 6935b81b6b3SRodney W. Grimes fdu_t fdu = fdc_data[fdcu].fdu; 6945b81b6b3SRodney W. Grimes int st0, st3, cyl; 6955b81b6b3SRodney W. Grimes struct buf *dp,*bp; 696f5f7ba03SJordan K. Hubbard int s; 6975b81b6b3SRodney W. Grimes 6985b81b6b3SRodney W. Grimes dp = &fdc_data[fdcu].head; 699f5f7ba03SJordan K. Hubbard s = splbio(); 7005b81b6b3SRodney W. Grimes bp = dp->b_actf; 7015b81b6b3SRodney W. Grimes 7025b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSED); 7035b81b6b3SRodney W. Grimes out_fdc(fdcu,fd_data[fdu].hddrv); 7045b81b6b3SRodney W. Grimes st3 = in_fdc(fdcu); 7055b81b6b3SRodney W. Grimes 7065b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 7075b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 7085b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 7095b81b6b3SRodney W. Grimes printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n", 7105b81b6b3SRodney W. Grimes fdu, 7115b81b6b3SRodney W. Grimes st0, 7125b81b6b3SRodney W. Grimes NE7_ST0BITS, 7135b81b6b3SRodney W. Grimes cyl, 7145b81b6b3SRodney W. Grimes st3, 7155b81b6b3SRodney W. Grimes NE7_ST3BITS); 7165b81b6b3SRodney W. Grimes 7175b81b6b3SRodney W. Grimes if (bp) 7185b81b6b3SRodney W. Grimes { 7195b81b6b3SRodney W. Grimes retrier(fdcu); 7205b81b6b3SRodney W. Grimes fdc_data[fdcu].status[0] = 0xc0; 7215b81b6b3SRodney W. Grimes fdc_data[fdcu].state = IOTIMEDOUT; 7225b81b6b3SRodney W. Grimes if( fdc_data[fdcu].retry < 6) 7235b81b6b3SRodney W. Grimes fdc_data[fdcu].retry = 6; 7245b81b6b3SRodney W. Grimes } 7255b81b6b3SRodney W. Grimes else 7265b81b6b3SRodney W. Grimes { 7275b81b6b3SRodney W. Grimes fdc_data[fdcu].fd = (fd_p) 0; 7285b81b6b3SRodney W. Grimes fdc_data[fdcu].fdu = -1; 7295b81b6b3SRodney W. Grimes fdc_data[fdcu].state = DEVIDLE; 7305b81b6b3SRodney W. Grimes } 731f5f7ba03SJordan K. Hubbard fdintr(fdcu); 732f5f7ba03SJordan K. Hubbard splx(s); 7335b81b6b3SRodney W. Grimes } 7345b81b6b3SRodney W. Grimes 7355b81b6b3SRodney W. Grimes /* just ensure it has the right spl */ 736381fe1aaSGarrett Wollman static void 737d0917939SPaul Richards fd_pseudointr(void *arg1) 7385b81b6b3SRodney W. Grimes { 739381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 7405b81b6b3SRodney W. Grimes int s; 7415b81b6b3SRodney W. Grimes s = splbio(); 7425b81b6b3SRodney W. Grimes fdintr(fdcu); 7435b81b6b3SRodney W. Grimes splx(s); 7445b81b6b3SRodney W. Grimes } 7455b81b6b3SRodney W. Grimes 7465b81b6b3SRodney W. Grimes /***********************************************************************\ 7475b81b6b3SRodney W. Grimes * fdintr * 7485b81b6b3SRodney W. Grimes * keep calling the state machine until it returns a 0 * 7495b81b6b3SRodney W. Grimes * ALWAYS called at SPLBIO * 7505b81b6b3SRodney W. Grimes \***********************************************************************/ 751381fe1aaSGarrett Wollman void 752381fe1aaSGarrett Wollman fdintr(fdcu_t fdcu) 7535b81b6b3SRodney W. Grimes { 7545b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 755b99f0a4aSAndrew Moore #if NFT > 0 756b99f0a4aSAndrew Moore fdu_t fdu = fdc->fdu; 757b99f0a4aSAndrew Moore 758b99f0a4aSAndrew Moore if (fdc->flags & FDC_TAPE_BUSY) 759b99f0a4aSAndrew Moore (ftintr(fdu)); 760b99f0a4aSAndrew Moore else 761b99f0a4aSAndrew Moore #endif 762381fe1aaSGarrett Wollman while(fdstate(fdcu, fdc)) 763381fe1aaSGarrett Wollman ; 7645b81b6b3SRodney W. Grimes } 7655b81b6b3SRodney W. Grimes 7665b81b6b3SRodney W. Grimes /***********************************************************************\ 7675b81b6b3SRodney W. Grimes * The controller state machine. * 7685b81b6b3SRodney W. Grimes * if it returns a non zero value, it should be called again immediatly * 7695b81b6b3SRodney W. Grimes \***********************************************************************/ 770381fe1aaSGarrett Wollman int 771381fe1aaSGarrett Wollman fdstate(fdcu, fdc) 772f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 773f5f7ba03SJordan K. Hubbard fdc_p fdc; 7745b81b6b3SRodney W. Grimes { 775b39c878eSAndrey A. Chernov int read, format, head, trac, sec = 0, i = 0, s, sectrac, cyl, st0; 7765b81b6b3SRodney W. Grimes unsigned long blknum; 7775b81b6b3SRodney W. Grimes fdu_t fdu = fdc->fdu; 7785b81b6b3SRodney W. Grimes fd_p fd; 7795b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 780b39c878eSAndrey A. Chernov struct fd_formb *finfo = NULL; 7815b81b6b3SRodney W. Grimes 7825b81b6b3SRodney W. Grimes dp = &(fdc->head); 7835b81b6b3SRodney W. Grimes bp = dp->b_actf; 7845b81b6b3SRodney W. Grimes if(!bp) 7855b81b6b3SRodney W. Grimes { 7865b81b6b3SRodney W. Grimes /***********************************************\ 7875b81b6b3SRodney W. Grimes * nothing left for this controller to do * 7885b81b6b3SRodney W. Grimes * Force into the IDLE state, * 7895b81b6b3SRodney W. Grimes \***********************************************/ 7905b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 7915b81b6b3SRodney W. Grimes if(fdc->fd) 7925b81b6b3SRodney W. Grimes { 7935b81b6b3SRodney W. Grimes printf("unexpected valid fd pointer (fdu = %d)\n" 7945b81b6b3SRodney W. Grimes ,fdc->fdu); 7955b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 7965b81b6b3SRodney W. Grimes fdc->fdu = -1; 7975b81b6b3SRodney W. Grimes } 7985b81b6b3SRodney W. Grimes TRACE1("[fdc%d IDLE]",fdcu); 7995b81b6b3SRodney W. Grimes return(0); 8005b81b6b3SRodney W. Grimes } 8015b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 8025b81b6b3SRodney W. Grimes fd = fd_data + fdu; 8035b81b6b3SRodney W. Grimes if (fdc->fd && (fd != fdc->fd)) 8045b81b6b3SRodney W. Grimes { 8055b81b6b3SRodney W. Grimes printf("confused fd pointers\n"); 8065b81b6b3SRodney W. Grimes } 8075b81b6b3SRodney W. Grimes read = bp->b_flags & B_READ; 808b39c878eSAndrey A. Chernov format = bp->b_flags & B_FORMAT; 809b39c878eSAndrey A. Chernov if(format) 810b39c878eSAndrey A. Chernov finfo = (struct fd_formb *)bp->b_un.b_addr; 8115b81b6b3SRodney W. Grimes TRACE1("fd%d",fdu); 8125b81b6b3SRodney W. Grimes TRACE1("[%s]",fdstates[fdc->state]); 8135b81b6b3SRodney W. Grimes TRACE1("(0x%x)",fd->flags); 814d0917939SPaul Richards untimeout(fd_turnoff, (caddr_t)fdu); 815d0917939SPaul Richards timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); 8165b81b6b3SRodney W. Grimes switch (fdc->state) 8175b81b6b3SRodney W. Grimes { 8185b81b6b3SRodney W. Grimes case DEVIDLE: 8195b81b6b3SRodney W. Grimes case FINDWORK: /* we have found new work */ 8205b81b6b3SRodney W. Grimes fdc->retry = 0; 8215b81b6b3SRodney W. Grimes fd->skip = 0; 8225b81b6b3SRodney W. Grimes fdc->fd = fd; 8235b81b6b3SRodney W. Grimes fdc->fdu = fdu; 824e7e0afeaSNate Williams outb(fdc->baseport+fdctl, fd->ft->trans); 8255b81b6b3SRodney W. Grimes /*******************************************************\ 8265b81b6b3SRodney W. Grimes * If the next drive has a motor startup pending, then * 8275b81b6b3SRodney W. Grimes * it will start up in it's own good time * 8285b81b6b3SRodney W. Grimes \*******************************************************/ 8295b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 8305b81b6b3SRodney W. Grimes { 8315b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 8325b81b6b3SRodney W. Grimes return(0); /* come back later */ 8335b81b6b3SRodney W. Grimes } 8345b81b6b3SRodney W. Grimes /*******************************************************\ 8355b81b6b3SRodney W. Grimes * Maybe if it's not starting, it SHOULD be starting * 8365b81b6b3SRodney W. Grimes \*******************************************************/ 8375b81b6b3SRodney W. Grimes if (!(fd->flags & FD_MOTOR)) 8385b81b6b3SRodney W. Grimes { 8395b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 8405b81b6b3SRodney W. Grimes fd_turnon(fdu); 8415b81b6b3SRodney W. Grimes return(0); 8425b81b6b3SRodney W. Grimes } 8435b81b6b3SRodney W. Grimes else /* at least make sure we are selected */ 8445b81b6b3SRodney W. Grimes { 8455b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 8465b81b6b3SRodney W. Grimes } 8475b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 8485b81b6b3SRodney W. Grimes break; 8495b81b6b3SRodney W. Grimes case DOSEEK: 8505b81b6b3SRodney W. Grimes if (bp->b_cylin == fd->track) 8515b81b6b3SRodney W. Grimes { 8525b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8535b81b6b3SRodney W. Grimes break; 8545b81b6b3SRodney W. Grimes } 8555b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SEEK); /* Seek function */ 8565b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); /* Drive number */ 8575b81b6b3SRodney W. Grimes out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac); 8585b81b6b3SRodney W. Grimes fd->track = -2; 8595b81b6b3SRodney W. Grimes fdc->state = SEEKWAIT; 860d0917939SPaul Richards timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 8615b81b6b3SRodney W. Grimes return(0); /* will return later */ 8625b81b6b3SRodney W. Grimes case SEEKWAIT: 863d0917939SPaul Richards untimeout(fd_timeout, (caddr_t)fdcu); 8645b81b6b3SRodney W. Grimes /* allow heads to settle */ 865d0917939SPaul Richards timeout(fd_pseudointr, (caddr_t)fdcu, hz / 50); 8665b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8675b81b6b3SRodney W. Grimes return(0); /* will return later */ 8685b81b6b3SRodney W. Grimes break; 8695b81b6b3SRodney W. Grimes 8705b81b6b3SRodney W. Grimes case SEEKCOMPLETE : /* SEEK DONE, START DMA */ 8715b81b6b3SRodney W. Grimes /* Make sure seek really happened*/ 8725b81b6b3SRodney W. Grimes if(fd->track == -2) 8735b81b6b3SRodney W. Grimes { 8745b81b6b3SRodney W. Grimes int descyl = bp->b_cylin * fd->ft->steptrac; 8755b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 8765b81b6b3SRodney W. Grimes i = in_fdc(fdcu); 8775b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 8785b81b6b3SRodney W. Grimes if (cyl != descyl) 8795b81b6b3SRodney W. Grimes { 880b99f0a4aSAndrew Moore printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", 881b99f0a4aSAndrew Moore fdu, descyl, cyl, i, NE7_ST0BITS); 8825b81b6b3SRodney W. Grimes return(retrier(fdcu)); 8835b81b6b3SRodney W. Grimes } 8845b81b6b3SRodney W. Grimes } 8855b81b6b3SRodney W. Grimes 8865b81b6b3SRodney W. Grimes fd->track = bp->b_cylin; 887b39c878eSAndrey A. Chernov if(format) 888b39c878eSAndrey A. Chernov fd->skip = (char *)&(finfo->fd_formb_cylno(0)) 889b39c878eSAndrey A. Chernov - (char *)finfo; 8905b81b6b3SRodney W. Grimes isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip, 891b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 8925b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 8935b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 8945b81b6b3SRodney W. Grimes sectrac = fd->ft->sectrac; 8955b81b6b3SRodney W. Grimes sec = blknum % (sectrac * fd->ft->heads); 8965b81b6b3SRodney W. Grimes head = sec / sectrac; 8975b81b6b3SRodney W. Grimes sec = sec % sectrac + 1; 8985b81b6b3SRodney W. Grimes /*XXX*/ fd->hddrv = ((head&1)<<2)+fdu; 8995b81b6b3SRodney W. Grimes 900b39c878eSAndrey A. Chernov if(format) 901b39c878eSAndrey A. Chernov { 902b39c878eSAndrey A. Chernov /* formatting */ 903b39c878eSAndrey A. Chernov out_fdc(fdcu,/* NE7CMD_FORMAT */ 0x4d); 904b39c878eSAndrey A. Chernov out_fdc(fdcu,head << 2 | fdu); 905b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_secshift); 906b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_nsecs); 907b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_gaplen); 908b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_fillbyte); 909b39c878eSAndrey A. Chernov } 910b39c878eSAndrey A. Chernov else 911b39c878eSAndrey A. Chernov { 9125b81b6b3SRodney W. Grimes if (read) 9135b81b6b3SRodney W. Grimes { 9145b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_READ); /* READ */ 9155b81b6b3SRodney W. Grimes } 9165b81b6b3SRodney W. Grimes else 9175b81b6b3SRodney W. Grimes { 9185b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_WRITE); /* WRITE */ 9195b81b6b3SRodney W. Grimes } 9205b81b6b3SRodney W. Grimes out_fdc(fdcu,head << 2 | fdu); /* head & unit */ 9215b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->track); /* track */ 9225b81b6b3SRodney W. Grimes out_fdc(fdcu,head); 9235b81b6b3SRodney W. Grimes out_fdc(fdcu,sec); /* sector XXX +1? */ 9245b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->secsize); /* sector size */ 9255b81b6b3SRodney W. Grimes out_fdc(fdcu,sectrac); /* sectors/track */ 9265b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->gap); /* gap size */ 9275b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->datalen); /* data length */ 928b39c878eSAndrey A. Chernov } 9295b81b6b3SRodney W. Grimes fdc->state = IOCOMPLETE; 930d0917939SPaul Richards timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 9315b81b6b3SRodney W. Grimes return(0); /* will return later */ 9325b81b6b3SRodney W. Grimes case IOCOMPLETE: /* IO DONE, post-analyze */ 933d0917939SPaul Richards untimeout(fd_timeout, (caddr_t)fdcu); 9345b81b6b3SRodney W. Grimes for(i=0;i<7;i++) 9355b81b6b3SRodney W. Grimes { 9365b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 9375b81b6b3SRodney W. Grimes } 9385b81b6b3SRodney W. Grimes case IOTIMEDOUT: /*XXX*/ 9395b81b6b3SRodney W. Grimes isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, 940b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 9415b81b6b3SRodney W. Grimes if (fdc->status[0]&0xF8) 9425b81b6b3SRodney W. Grimes { 943b39c878eSAndrey A. Chernov if (fdc->status[1] & 0x10) { 944b39c878eSAndrey A. Chernov /* 945b39c878eSAndrey A. Chernov * Operation not completed in reasonable time. 946b39c878eSAndrey A. Chernov * Just restart it, don't increment retry count. 947b39c878eSAndrey A. Chernov * (vak) 948b39c878eSAndrey A. Chernov */ 949b39c878eSAndrey A. Chernov fdc->state = SEEKCOMPLETE; 950b39c878eSAndrey A. Chernov return (1); 951b39c878eSAndrey A. Chernov } 9525b81b6b3SRodney W. Grimes return(retrier(fdcu)); 9535b81b6b3SRodney W. Grimes } 9545b81b6b3SRodney W. Grimes /* All OK */ 9555b81b6b3SRodney W. Grimes fd->skip += FDBLK; 956b39c878eSAndrey A. Chernov if (!format && fd->skip < bp->b_bcount) 9575b81b6b3SRodney W. Grimes { 9585b81b6b3SRodney W. Grimes /* set up next transfer */ 9595b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 9605b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 9615b81b6b3SRodney W. Grimes bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads)); 9625b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9635b81b6b3SRodney W. Grimes } 9645b81b6b3SRodney W. Grimes else 9655b81b6b3SRodney W. Grimes { 9665b81b6b3SRodney W. Grimes /* ALL DONE */ 9675b81b6b3SRodney W. Grimes fd->skip = 0; 9685b81b6b3SRodney W. Grimes bp->b_resid = 0; 96926f9a767SRodney W. Grimes dp->b_actf = bp->b_actf; 9705b81b6b3SRodney W. Grimes biodone(bp); 9715b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 9725b81b6b3SRodney W. Grimes fdc->fdu = -1; 9735b81b6b3SRodney W. Grimes fdc->state = FINDWORK; 9745b81b6b3SRodney W. Grimes } 9755b81b6b3SRodney W. Grimes return(1); 9765b81b6b3SRodney W. Grimes case RESETCTLR: 9775b81b6b3SRodney W. Grimes /* Try a reset, keep motor on */ 9785b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,1); 9795b81b6b3SRodney W. Grimes DELAY(100); 9805b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 9815b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,fd->ft->trans); 9825b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdctl]",fd->ft->trans); 9835b81b6b3SRodney W. Grimes fdc->retry++; 9845b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 9855b81b6b3SRodney W. Grimes break; 9865b81b6b3SRodney W. Grimes case STARTRECAL: 9875b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */ 9885b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 9895b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 9905b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 9915b81b6b3SRodney W. Grimes out_fdc(fdcu,fdu); 9925b81b6b3SRodney W. Grimes fdc->state = RECALWAIT; 9935b81b6b3SRodney W. Grimes return(0); /* will return later */ 9945b81b6b3SRodney W. Grimes case RECALWAIT: 9955b81b6b3SRodney W. Grimes /* allow heads to settle */ 996d0917939SPaul Richards timeout(fd_pseudointr, (caddr_t)fdcu, hz / 30); 9975b81b6b3SRodney W. Grimes fdc->state = RECALCOMPLETE; 9985b81b6b3SRodney W. Grimes return(0); /* will return later */ 9995b81b6b3SRodney W. Grimes case RECALCOMPLETE: 10005b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 10015b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 10025b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 10035b81b6b3SRodney W. Grimes if (cyl != 0) 10045b81b6b3SRodney W. Grimes { 10055b81b6b3SRodney W. Grimes printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, 10065b81b6b3SRodney W. Grimes st0, NE7_ST0BITS, cyl); 10075b81b6b3SRodney W. Grimes return(retrier(fdcu)); 10085b81b6b3SRodney W. Grimes } 10095b81b6b3SRodney W. Grimes fd->track = 0; 10105b81b6b3SRodney W. Grimes /* Seek (probably) necessary */ 10115b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 10125b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 10135b81b6b3SRodney W. Grimes case MOTORWAIT: 10145b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 10155b81b6b3SRodney W. Grimes { 10165b81b6b3SRodney W. Grimes return(0); /* time's not up yet */ 10175b81b6b3SRodney W. Grimes } 10185b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 10195b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 10205b81b6b3SRodney W. Grimes default: 10215b81b6b3SRodney W. Grimes printf("Unexpected FD int->"); 10225b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 10235b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 10245b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 10255b81b6b3SRodney W. Grimes printf("ST0 = %lx, PCN = %lx\n",i,sec); 10265b81b6b3SRodney W. Grimes out_fdc(fdcu,0x4A); 10275b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); 10285b81b6b3SRodney W. Grimes for(i=0;i<7;i++) { 10295b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 10305b81b6b3SRodney W. Grimes } 10315b81b6b3SRodney W. Grimes printf("intr status :%lx %lx %lx %lx %lx %lx %lx ", 10325b81b6b3SRodney W. Grimes fdc->status[0], 10335b81b6b3SRodney W. Grimes fdc->status[1], 10345b81b6b3SRodney W. Grimes fdc->status[2], 10355b81b6b3SRodney W. Grimes fdc->status[3], 10365b81b6b3SRodney W. Grimes fdc->status[4], 10375b81b6b3SRodney W. Grimes fdc->status[5], 10385b81b6b3SRodney W. Grimes fdc->status[6] ); 10395b81b6b3SRodney W. Grimes return(0); 10405b81b6b3SRodney W. Grimes } 10415b81b6b3SRodney W. Grimes return(1); /* Come back immediatly to new state */ 10425b81b6b3SRodney W. Grimes } 10435b81b6b3SRodney W. Grimes 1044aaf08d94SGarrett Wollman static int 1045f5f7ba03SJordan K. Hubbard retrier(fdcu) 1046f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 10475b81b6b3SRodney W. Grimes { 10485b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 10495b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 10505b81b6b3SRodney W. Grimes 10515b81b6b3SRodney W. Grimes dp = &(fdc->head); 10525b81b6b3SRodney W. Grimes bp = dp->b_actf; 10535b81b6b3SRodney W. Grimes 10545b81b6b3SRodney W. Grimes switch(fdc->retry) 10555b81b6b3SRodney W. Grimes { 10565b81b6b3SRodney W. Grimes case 0: case 1: case 2: 10575b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 10585b81b6b3SRodney W. Grimes break; 10595b81b6b3SRodney W. Grimes case 3: case 4: case 5: 10605b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 10615b81b6b3SRodney W. Grimes break; 10625b81b6b3SRodney W. Grimes case 6: 10635b81b6b3SRodney W. Grimes fdc->state = RESETCTLR; 10645b81b6b3SRodney W. Grimes break; 10655b81b6b3SRodney W. Grimes case 7: 10665b81b6b3SRodney W. Grimes break; 10675b81b6b3SRodney W. Grimes default: 10685b81b6b3SRodney W. Grimes { 10697ca0641bSAndrey A. Chernov dev_t sav_b_dev = bp->b_dev; 10707ca0641bSAndrey A. Chernov /* Trick diskerr */ 1071b2be795bSAndrey A. Chernov bp->b_dev = makedev(major(bp->b_dev), (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART); 107292ed385aSRodney W. Grimes diskerr(bp, "fd", "hard error", LOG_PRINTF, 107392ed385aSRodney W. Grimes fdc->fd->skip, (struct disklabel *)NULL); 10747ca0641bSAndrey A. Chernov bp->b_dev = sav_b_dev; 107592ed385aSRodney W. Grimes printf(" (ST0 %b ", fdc->status[0], NE7_ST0BITS); 10765b81b6b3SRodney W. Grimes printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS); 10775b81b6b3SRodney W. Grimes printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS); 10785b81b6b3SRodney W. Grimes printf("cyl %d hd %d sec %d)\n", 107992ed385aSRodney W. Grimes fdc->status[3], fdc->status[4], fdc->status[5]); 10805b81b6b3SRodney W. Grimes } 10815b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 10825b81b6b3SRodney W. Grimes bp->b_error = EIO; 10835b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount - fdc->fd->skip; 108426f9a767SRodney W. Grimes dp->b_actf = bp->b_actf; 10855b81b6b3SRodney W. Grimes fdc->fd->skip = 0; 10865b81b6b3SRodney W. Grimes biodone(bp); 108792ed385aSRodney W. Grimes fdc->state = FINDWORK; 10885b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 10895b81b6b3SRodney W. Grimes fdc->fdu = -1; 1090f5f7ba03SJordan K. Hubbard /* XXX abort current command, if any. */ 109192ed385aSRodney W. Grimes return(1); 10925b81b6b3SRodney W. Grimes } 10935b81b6b3SRodney W. Grimes fdc->retry++; 10945b81b6b3SRodney W. Grimes return(1); 10955b81b6b3SRodney W. Grimes } 10965b81b6b3SRodney W. Grimes 1097b39c878eSAndrey A. Chernov static int 1098b39c878eSAndrey A. Chernov fdformat(dev, finfo, p) 1099b39c878eSAndrey A. Chernov dev_t dev; 1100b39c878eSAndrey A. Chernov struct fd_formb *finfo; 1101b39c878eSAndrey A. Chernov struct proc *p; 1102b39c878eSAndrey A. Chernov { 1103b39c878eSAndrey A. Chernov fdu_t fdu; 1104b39c878eSAndrey A. Chernov fd_p fd; 1105b39c878eSAndrey A. Chernov 1106b39c878eSAndrey A. Chernov struct buf *bp; 1107b39c878eSAndrey A. Chernov int rv = 0, s; 1108b39c878eSAndrey A. Chernov 1109b39c878eSAndrey A. Chernov fdu = FDUNIT(minor(dev)); 1110b39c878eSAndrey A. Chernov fd = &fd_data[fdu]; 1111b39c878eSAndrey A. Chernov 1112b39c878eSAndrey A. Chernov /* set up a buffer header for fdstrategy() */ 1113b39c878eSAndrey A. Chernov bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 1114b39c878eSAndrey A. Chernov if(bp == 0) 1115b39c878eSAndrey A. Chernov return ENOBUFS; 1116b39c878eSAndrey A. Chernov bzero((void *)bp, sizeof(struct buf)); 1117b39c878eSAndrey A. Chernov bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 1118b39c878eSAndrey A. Chernov bp->b_proc = p; 1119b39c878eSAndrey A. Chernov bp->b_dev = dev; 1120b39c878eSAndrey A. Chernov 1121b39c878eSAndrey A. Chernov /* 1122b39c878eSAndrey A. Chernov * calculate a fake blkno, so fdstrategy() would initiate a 1123b39c878eSAndrey A. Chernov * seek to the requested cylinder 1124b39c878eSAndrey A. Chernov */ 1125b39c878eSAndrey A. Chernov bp->b_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) 1126b39c878eSAndrey A. Chernov + finfo->head * fd->ft->sectrac) * FDBLK / DEV_BSIZE; 1127b39c878eSAndrey A. Chernov 1128b39c878eSAndrey A. Chernov bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 1129b39c878eSAndrey A. Chernov bp->b_un.b_addr = (caddr_t)finfo; 1130b39c878eSAndrey A. Chernov 1131b39c878eSAndrey A. Chernov /* now do the format */ 1132b39c878eSAndrey A. Chernov fdstrategy(bp); 1133b39c878eSAndrey A. Chernov 1134b39c878eSAndrey A. Chernov /* ...and wait for it to complete */ 1135b39c878eSAndrey A. Chernov s = splbio(); 1136b39c878eSAndrey A. Chernov while(!(bp->b_flags & B_DONE)) 1137b39c878eSAndrey A. Chernov { 1138b39c878eSAndrey A. Chernov rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 1139b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1140b39c878eSAndrey A. Chernov break; 1141b39c878eSAndrey A. Chernov } 1142b39c878eSAndrey A. Chernov splx(s); 1143b39c878eSAndrey A. Chernov 1144b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1145b39c878eSAndrey A. Chernov { 1146b39c878eSAndrey A. Chernov /* timed out */ 1147b39c878eSAndrey A. Chernov biodone(bp); 1148b39c878eSAndrey A. Chernov rv = EIO; 1149b39c878eSAndrey A. Chernov } 1150b39c878eSAndrey A. Chernov free(bp, M_TEMP); 1151b39c878eSAndrey A. Chernov return rv; 1152b39c878eSAndrey A. Chernov } 1153b39c878eSAndrey A. Chernov 1154f5f7ba03SJordan K. Hubbard /* 1155f5f7ba03SJordan K. Hubbard * fdioctl() from jc@irbs.UUCP (John Capo) 1156f5f7ba03SJordan K. Hubbard * i386/i386/conf.c needs to have fdioctl() declared and remove the line that 1157f5f7ba03SJordan K. Hubbard * defines fdioctl to be enxio. 1158f5f7ba03SJordan K. Hubbard * 1159f5f7ba03SJordan K. Hubbard * TODO: Reformat. 1160f5f7ba03SJordan K. Hubbard * Think about allocating buffer off stack. 1161f5f7ba03SJordan K. Hubbard * Don't pass uncast 0's and NULL's to read/write/setdisklabel(). 1162f5f7ba03SJordan K. Hubbard * Watch out for NetBSD's different *disklabel() interface. 1163b39c878eSAndrey A. Chernov * 1164b39c878eSAndrey A. Chernov * Added functionality for floppy formatting 1165b39c878eSAndrey A. Chernov * joerg_wunsch@uriah.sax.de (Joerg Wunsch) 1166f5f7ba03SJordan K. Hubbard */ 11675b81b6b3SRodney W. Grimes 1168f5f7ba03SJordan K. Hubbard int 1169b39c878eSAndrey A. Chernov fdioctl (dev, cmd, addr, flag, p) 1170f5f7ba03SJordan K. Hubbard dev_t dev; 1171f5f7ba03SJordan K. Hubbard int cmd; 1172f5f7ba03SJordan K. Hubbard caddr_t addr; 1173f5f7ba03SJordan K. Hubbard int flag; 1174b39c878eSAndrey A. Chernov struct proc *p; 1175f5f7ba03SJordan K. Hubbard { 1176f5f7ba03SJordan K. Hubbard struct fd_type *fdt; 1177f5f7ba03SJordan K. Hubbard struct disklabel *dl; 1178f5f7ba03SJordan K. Hubbard char buffer[DEV_BSIZE]; 1179f5f7ba03SJordan K. Hubbard int error; 1180f5f7ba03SJordan K. Hubbard 1181b99f0a4aSAndrew Moore #if NFT > 0 1182a60eff27SNate Williams int type = FDTYPE(minor(dev)); 1183a60eff27SNate Williams 1184a60eff27SNate Williams /* check for a tape ioctl */ 1185a60eff27SNate Williams if (type & F_TAPE_TYPE) 1186b99f0a4aSAndrew Moore return ftioctl(dev, cmd, addr, flag, p); 1187b99f0a4aSAndrew Moore #endif 1188b99f0a4aSAndrew Moore 1189f5f7ba03SJordan K. Hubbard error = 0; 1190f5f7ba03SJordan K. Hubbard 1191f5f7ba03SJordan K. Hubbard switch (cmd) 1192f5f7ba03SJordan K. Hubbard { 1193f5f7ba03SJordan K. Hubbard case DIOCGDINFO: 1194f5f7ba03SJordan K. Hubbard bzero(buffer, sizeof (buffer)); 1195f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)buffer; 1196f5f7ba03SJordan K. Hubbard dl->d_secsize = FDBLK; 119792ed385aSRodney W. Grimes fdt = fd_data[FDUNIT(minor(dev))].ft; 1198f5f7ba03SJordan K. Hubbard dl->d_secpercyl = fdt->size / fdt->tracks; 1199f5f7ba03SJordan K. Hubbard dl->d_type = DTYPE_FLOPPY; 1200f5f7ba03SJordan K. Hubbard 1201f5f7ba03SJordan K. Hubbard if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) 1202f5f7ba03SJordan K. Hubbard error = 0; 1203f5f7ba03SJordan K. Hubbard else 1204f5f7ba03SJordan K. Hubbard error = EINVAL; 1205f5f7ba03SJordan K. Hubbard 1206f5f7ba03SJordan K. Hubbard *(struct disklabel *)addr = *dl; 1207f5f7ba03SJordan K. Hubbard break; 1208f5f7ba03SJordan K. Hubbard 1209f5f7ba03SJordan K. Hubbard case DIOCSDINFO: 1210f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1211f5f7ba03SJordan K. Hubbard error = EBADF; 1212f5f7ba03SJordan K. Hubbard break; 1213f5f7ba03SJordan K. Hubbard 1214f5f7ba03SJordan K. Hubbard case DIOCWLABEL: 1215f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1216f5f7ba03SJordan K. Hubbard error = EBADF; 1217f5f7ba03SJordan K. Hubbard break; 1218f5f7ba03SJordan K. Hubbard 1219f5f7ba03SJordan K. Hubbard case DIOCWDINFO: 1220f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1221f5f7ba03SJordan K. Hubbard { 1222f5f7ba03SJordan K. Hubbard error = EBADF; 1223f5f7ba03SJordan K. Hubbard break; 1224f5f7ba03SJordan K. Hubbard } 1225f5f7ba03SJordan K. Hubbard 1226f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)addr; 1227f5f7ba03SJordan K. Hubbard 1228b39c878eSAndrey A. Chernov if (error = setdisklabel ((struct disklabel *)buffer, 1229b39c878eSAndrey A. Chernov dl, 0, NULL)) 1230f5f7ba03SJordan K. Hubbard break; 1231f5f7ba03SJordan K. Hubbard 1232b39c878eSAndrey A. Chernov error = writedisklabel(dev, fdstrategy, 1233b39c878eSAndrey A. Chernov (struct disklabel *)buffer, NULL); 1234b39c878eSAndrey A. Chernov break; 1235b39c878eSAndrey A. Chernov 1236b39c878eSAndrey A. Chernov case FD_FORM: 1237b39c878eSAndrey A. Chernov if((flag & FWRITE) == 0) 1238b39c878eSAndrey A. Chernov error = EBADF; /* must be opened for writing */ 1239b39c878eSAndrey A. Chernov else if(((struct fd_formb *)addr)->format_version != 1240b39c878eSAndrey A. Chernov FD_FORMAT_VERSION) 1241b39c878eSAndrey A. Chernov error = EINVAL; /* wrong version of formatting prog */ 1242b39c878eSAndrey A. Chernov else 1243b39c878eSAndrey A. Chernov error = fdformat(dev, (struct fd_formb *)addr, p); 1244b39c878eSAndrey A. Chernov break; 1245b39c878eSAndrey A. Chernov 1246b39c878eSAndrey A. Chernov case FD_GTYPE: /* get drive type */ 1247b39c878eSAndrey A. Chernov *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft; 1248f5f7ba03SJordan K. Hubbard break; 1249f5f7ba03SJordan K. Hubbard 1250f5f7ba03SJordan K. Hubbard default: 1251f5f7ba03SJordan K. Hubbard error = EINVAL; 1252f5f7ba03SJordan K. Hubbard break; 1253f5f7ba03SJordan K. Hubbard } 1254f5f7ba03SJordan K. Hubbard return (error); 1255f5f7ba03SJordan K. Hubbard } 1256f5f7ba03SJordan K. Hubbard 1257f5f7ba03SJordan K. Hubbard #endif 1258