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 3856ef0285SAndrew Moore * $Id: fd.c,v 1.21 1994/02/14 22:24:23 nate 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> 635b81b6b3SRodney W. Grimes #include "i386/isa/isa.h" 645b81b6b3SRodney W. Grimes #include "i386/isa/isa_device.h" 655b81b6b3SRodney W. Grimes #include "i386/isa/fdreg.h" 669c2638e6SAndrew Moore #include "i386/isa/fdc.h" 675b81b6b3SRodney W. Grimes #include "i386/isa/icu.h" 685b81b6b3SRodney W. Grimes #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 745b81b6b3SRodney W. Grimes #define b_cylin b_resid 755b81b6b3SRodney W. Grimes #define FDBLK 512 765b81b6b3SRodney W. Grimes 77b39c878eSAndrey A. Chernov /* misuse a flag to identify format operation */ 78b39c878eSAndrey A. Chernov #define B_FORMAT B_XXX 795b81b6b3SRodney W. Grimes 80b39c878eSAndrey A. Chernov #define NUMTYPES 14 81b39c878eSAndrey A. Chernov #define NUMDENS (NUMTYPES - 6) 827ca0641bSAndrey A. Chernov 83b99f0a4aSAndrew Moore /* This defines (-1) must match index for fd_types */ 84b99f0a4aSAndrew Moore #define F_TAPE_TYPE 0x020 /* bit for fd_types to indicate tape */ 85b99f0a4aSAndrew Moore #define NO_TYPE 0 /* must match NO_TYPE in ft.c */ 86b99f0a4aSAndrew Moore #define FD_1720 1 87b99f0a4aSAndrew Moore #define FD_1480 2 88b99f0a4aSAndrew Moore #define FD_1440 3 89b99f0a4aSAndrew Moore #define FD_1200 4 90b99f0a4aSAndrew Moore #define FD_820 5 91b99f0a4aSAndrew Moore #define FD_800 6 92b99f0a4aSAndrew Moore #define FD_720 7 93b99f0a4aSAndrew Moore #define FD_360 8 94ed2fa05eSAndrey A. Chernov 95b99f0a4aSAndrew Moore #define FD_1480in5_25 9 96b99f0a4aSAndrew Moore #define FD_1440in5_25 10 97b99f0a4aSAndrew Moore #define FD_820in5_25 11 98b99f0a4aSAndrew Moore #define FD_800in5_25 12 99b99f0a4aSAndrew Moore #define FD_720in5_25 13 100b99f0a4aSAndrew Moore #define FD_360in5_25 14 101b99f0a4aSAndrew Moore 1027ca0641bSAndrey A. Chernov 1035b81b6b3SRodney W. Grimes struct fd_type fd_types[NUMTYPES] = 1045b81b6b3SRodney W. Grimes { 105126518a1SAndrey A. Chernov { 21,2,0xFF,0x04,82,3444,1,FDC_500KBPS,2,0x0C,2 }, /* 1.72M in HD 3.5in */ 106126518a1SAndrey A. Chernov { 18,2,0xFF,0x1B,82,2952,1,FDC_500KBPS,2,0x6C,1 }, /* 1.48M in HD 3.5in */ 107126518a1SAndrey A. Chernov { 18,2,0xFF,0x1B,80,2880,1,FDC_500KBPS,2,0x6C,1 }, /* 1.44M in HD 3.5in */ 108126518a1SAndrey A. Chernov { 15,2,0xFF,0x1B,80,2400,1,FDC_500KBPS,2,0x54,1 }, /* 1.2M in HD 5.25/3.5 */ 109126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,82,1640,1,FDC_250KBPS,2,0x2E,1 }, /* 820K in HD 3.5in */ 110126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,80,1600,1,FDC_250KBPS,2,0x2E,1 }, /* 800K in HD 3.5in */ 111126518a1SAndrey A. Chernov { 9,2,0xFF,0x20,80,1440,1,FDC_250KBPS,2,0x50,1 }, /* 720K in HD 3.5in */ 112126518a1SAndrey A. Chernov { 9,2,0xFF,0x2A,40, 720,1,FDC_300KBPS,2,0x50,1 }, /* 360K in DD 5.25in */ 113ed2fa05eSAndrey A. Chernov 114126518a1SAndrey A. Chernov { 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,0x02,2 }, /* 1.48M in HD 5.25in */ 115126518a1SAndrey A. Chernov { 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,0x02,2 }, /* 1.44M in HD 5.25in */ 116126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,82,1640,1,FDC_300KBPS,2,0x2E,1 }, /* 820K in HD 5.25in */ 117126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,80,1600,1,FDC_300KBPS,2,0x2E,1 }, /* 800K in HD 5.25in */ 118126518a1SAndrey A. Chernov { 9,2,0xFF,0x20,80,1440,1,FDC_300KBPS,2,0x50,1 }, /* 720K in HD 5.25in */ 119126518a1SAndrey A. Chernov { 9,2,0xFF,0x23,40, 720,2,FDC_300KBPS,2,0x50,1 }, /* 360K in HD 5.25in */ 1205b81b6b3SRodney W. Grimes }; 1215b81b6b3SRodney W. Grimes 122b99f0a4aSAndrew Moore #define DRVS_PER_CTLR 2 /* 2 floppies */ 1235b81b6b3SRodney W. Grimes /***********************************************************************\ 1245b81b6b3SRodney W. Grimes * Per controller structure. * 1255b81b6b3SRodney W. Grimes \***********************************************************************/ 126b99f0a4aSAndrew Moore struct fdc_data fdc_data[NFDC]; 1275b81b6b3SRodney W. Grimes 1285b81b6b3SRodney W. Grimes /***********************************************************************\ 1295b81b6b3SRodney W. Grimes * Per drive structure. * 130b99f0a4aSAndrew Moore * N per controller (DRVS_PER_CTLR) * 1315b81b6b3SRodney W. Grimes \***********************************************************************/ 1325b81b6b3SRodney W. Grimes struct fd_data { 133b99f0a4aSAndrew Moore struct fdc_data *fdc; /* pointer to controller structure */ 1345b81b6b3SRodney W. Grimes int fdsu; /* this units number on this controller */ 1355b81b6b3SRodney W. Grimes int type; /* Drive type (HD, DD */ 1365b81b6b3SRodney W. Grimes struct fd_type *ft; /* pointer to the type descriptor */ 1375b81b6b3SRodney W. Grimes int flags; 1385b81b6b3SRodney W. Grimes #define FD_OPEN 0x01 /* it's open */ 1395b81b6b3SRodney W. Grimes #define FD_ACTIVE 0x02 /* it's active */ 1405b81b6b3SRodney W. Grimes #define FD_MOTOR 0x04 /* motor should be on */ 1415b81b6b3SRodney W. Grimes #define FD_MOTOR_WAIT 0x08 /* motor coming up */ 1425b81b6b3SRodney W. Grimes int skip; 1435b81b6b3SRodney W. Grimes int hddrv; 1445b81b6b3SRodney W. Grimes int track; /* where we think the head is */ 1455b81b6b3SRodney W. Grimes } fd_data[NFD]; 1465b81b6b3SRodney W. Grimes 1475b81b6b3SRodney W. Grimes /***********************************************************************\ 1485b81b6b3SRodney W. Grimes * Throughout this file the following conventions will be used: * 1495b81b6b3SRodney W. Grimes * fd is a pointer to the fd_data struct for the drive in question * 1505b81b6b3SRodney W. Grimes * fdc is a pointer to the fdc_data struct for the controller * 1515b81b6b3SRodney W. Grimes * fdu is the floppy drive unit number * 1525b81b6b3SRodney W. Grimes * fdcu is the floppy controller unit number * 1535b81b6b3SRodney W. Grimes * fdsu is the floppy drive unit number on that controller. (sub-unit) * 1545b81b6b3SRodney W. Grimes \***********************************************************************/ 155b99f0a4aSAndrew Moore 156b99f0a4aSAndrew Moore #define id_physid id_scsiid /* this biotab field doubles as a field */ 157b99f0a4aSAndrew Moore /* for the physical unit number on the controller */ 1585b81b6b3SRodney W. Grimes 159aaf08d94SGarrett Wollman static int retrier(fdcu_t); 160aaf08d94SGarrett Wollman 1615b81b6b3SRodney W. Grimes #define DEVIDLE 0 1625b81b6b3SRodney W. Grimes #define FINDWORK 1 1635b81b6b3SRodney W. Grimes #define DOSEEK 2 1645b81b6b3SRodney W. Grimes #define SEEKCOMPLETE 3 1655b81b6b3SRodney W. Grimes #define IOCOMPLETE 4 1665b81b6b3SRodney W. Grimes #define RECALCOMPLETE 5 1675b81b6b3SRodney W. Grimes #define STARTRECAL 6 1685b81b6b3SRodney W. Grimes #define RESETCTLR 7 1695b81b6b3SRodney W. Grimes #define SEEKWAIT 8 1705b81b6b3SRodney W. Grimes #define RECALWAIT 9 1715b81b6b3SRodney W. Grimes #define MOTORWAIT 10 1725b81b6b3SRodney W. Grimes #define IOTIMEDOUT 11 1735b81b6b3SRodney W. Grimes 1745b81b6b3SRodney W. Grimes #ifdef DEBUG 1755b81b6b3SRodney W. Grimes char *fdstates[] = 1765b81b6b3SRodney W. Grimes { 1775b81b6b3SRodney W. Grimes "DEVIDLE", 1785b81b6b3SRodney W. Grimes "FINDWORK", 1795b81b6b3SRodney W. Grimes "DOSEEK", 1805b81b6b3SRodney W. Grimes "SEEKCOMPLETE", 1815b81b6b3SRodney W. Grimes "IOCOMPLETE", 1825b81b6b3SRodney W. Grimes "RECALCOMPLETE", 1835b81b6b3SRodney W. Grimes "STARTRECAL", 1845b81b6b3SRodney W. Grimes "RESETCTLR", 1855b81b6b3SRodney W. Grimes "SEEKWAIT", 1865b81b6b3SRodney W. Grimes "RECALWAIT", 1875b81b6b3SRodney W. Grimes "MOTORWAIT", 1885b81b6b3SRodney W. Grimes "IOTIMEDOUT" 1895b81b6b3SRodney W. Grimes }; 1905b81b6b3SRodney W. Grimes 1915b81b6b3SRodney W. Grimes 1925b81b6b3SRodney W. Grimes int fd_debug = 1; 1935b81b6b3SRodney W. Grimes #define TRACE0(arg) if(fd_debug) printf(arg) 1945b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2) 195381fe1aaSGarrett Wollman #else /* DEBUG */ 1965b81b6b3SRodney W. Grimes #define TRACE0(arg) 1975b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) 198381fe1aaSGarrett Wollman #endif /* DEBUG */ 1995b81b6b3SRodney W. Grimes 200381fe1aaSGarrett Wollman static void fdstart(fdcu_t); 201381fe1aaSGarrett Wollman void fdintr(fdcu_t); 202381fe1aaSGarrett Wollman static void fd_turnoff(caddr_t, int); 2035b81b6b3SRodney W. Grimes 2045b81b6b3SRodney W. Grimes /****************************************************************************/ 2055b81b6b3SRodney W. Grimes /* autoconfiguration stuff */ 2065b81b6b3SRodney W. Grimes /****************************************************************************/ 207381fe1aaSGarrett Wollman static int fdprobe(struct isa_device *); 208381fe1aaSGarrett Wollman static int fdattach(struct isa_device *); 2095b81b6b3SRodney W. Grimes 210b99f0a4aSAndrew Moore struct isa_driver fdcdriver = { 211b99f0a4aSAndrew Moore fdprobe, fdattach, "fdc", 2125b81b6b3SRodney W. Grimes }; 2135b81b6b3SRodney W. Grimes 2145b81b6b3SRodney W. Grimes /* 2155b81b6b3SRodney W. Grimes * probe for existance of controller 2165b81b6b3SRodney W. Grimes */ 217381fe1aaSGarrett Wollman int 2185b81b6b3SRodney W. Grimes fdprobe(dev) 2195b81b6b3SRodney W. Grimes struct isa_device *dev; 2205b81b6b3SRodney W. Grimes { 2215b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2225b81b6b3SRodney W. Grimes if(fdc_data[fdcu].flags & FDC_ATTACHED) 2235b81b6b3SRodney W. Grimes { 2245b81b6b3SRodney W. Grimes printf("fdc: same unit (%d) used multiple times\n",fdcu); 2255b81b6b3SRodney W. Grimes return 0; 2265b81b6b3SRodney W. Grimes } 2275b81b6b3SRodney W. Grimes 2285b81b6b3SRodney W. Grimes fdc_data[fdcu].baseport = dev->id_iobase; 2295b81b6b3SRodney W. Grimes 23016111cedSAndrew Moore /* First - lets reset the floppy controller */ 23116111cedSAndrew Moore 23216111cedSAndrew Moore outb(dev->id_iobase+fdout,0); 23316111cedSAndrew Moore DELAY(100); 23416111cedSAndrew Moore outb(dev->id_iobase+fdout,FDO_FRST); 23516111cedSAndrew Moore 2365b81b6b3SRodney W. Grimes /* see if it can handle a command */ 2375b81b6b3SRodney W. Grimes if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0) 2385b81b6b3SRodney W. Grimes { 2395b81b6b3SRodney W. Grimes return(0); 2405b81b6b3SRodney W. Grimes } 2415b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 2425b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 2435b81b6b3SRodney W. Grimes return (IO_FDCSIZE); 2445b81b6b3SRodney W. Grimes } 2455b81b6b3SRodney W. Grimes 2465b81b6b3SRodney W. Grimes /* 2475b81b6b3SRodney W. Grimes * wire controller into system, look for floppy units 2485b81b6b3SRodney W. Grimes */ 249381fe1aaSGarrett Wollman int 2505b81b6b3SRodney W. Grimes fdattach(dev) 2515b81b6b3SRodney W. Grimes struct isa_device *dev; 2525b81b6b3SRodney W. Grimes { 2535b81b6b3SRodney W. Grimes unsigned fdt,st0, cyl; 2545b81b6b3SRodney W. Grimes int hdr; 2555b81b6b3SRodney W. Grimes fdu_t fdu; 2565b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2575b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 2585b81b6b3SRodney W. Grimes fd_p fd; 2595b81b6b3SRodney W. Grimes int fdsu; 260b99f0a4aSAndrew Moore struct isa_device *fdup; 2615b81b6b3SRodney W. Grimes 2625b81b6b3SRodney W. Grimes fdc->fdcu = fdcu; 2635b81b6b3SRodney W. Grimes fdc->flags |= FDC_ATTACHED; 2645b81b6b3SRodney W. Grimes fdc->dmachan = dev->id_drq; 2655b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 2665b81b6b3SRodney W. Grimes hdr = 0; 267b99f0a4aSAndrew Moore printf("fdc%d:", fdcu); 2685b81b6b3SRodney W. Grimes 2695b81b6b3SRodney W. Grimes /* check for each floppy drive */ 270b99f0a4aSAndrew Moore for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { 271b99f0a4aSAndrew Moore if (fdup->id_iobase != dev->id_iobase) 272b99f0a4aSAndrew Moore continue; 273b99f0a4aSAndrew Moore fdu = fdup->id_unit; 274b99f0a4aSAndrew Moore fd = &fd_data[fdu]; 275b99f0a4aSAndrew Moore if (fdu >= (NFD+NFT)) 276b99f0a4aSAndrew Moore continue; 277b99f0a4aSAndrew Moore fdsu = fdup->id_physid; 278b99f0a4aSAndrew Moore /* look up what bios thinks we have */ 279b99f0a4aSAndrew Moore switch (fdu) { 280b99f0a4aSAndrew Moore case 0: fdt = (rtcin(RTC_FDISKETTE) & 0xf0); 281b99f0a4aSAndrew Moore break; 282b99f0a4aSAndrew Moore case 1: fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); 283b99f0a4aSAndrew Moore break; 284b99f0a4aSAndrew Moore default: fdt = RTCFDT_NONE; 285b99f0a4aSAndrew Moore break; 286b99f0a4aSAndrew Moore } 2875b81b6b3SRodney W. Grimes /* is there a unit? */ 288b99f0a4aSAndrew Moore if ((fdt == RTCFDT_NONE) 289b99f0a4aSAndrew Moore #if NFT > 0 290b99f0a4aSAndrew Moore || (fdsu >= DRVS_PER_CTLR)) { 291b99f0a4aSAndrew Moore #else 292b99f0a4aSAndrew Moore ) { 29356ef0285SAndrew Moore fd->type = NO_TYPE; 294b99f0a4aSAndrew Moore #endif 295b99f0a4aSAndrew Moore #if NFT > 0 296b99f0a4aSAndrew Moore /* If BIOS says no floppy, or > 2nd device */ 297b99f0a4aSAndrew Moore /* Probe for and attach a floppy tape. */ 298b99f0a4aSAndrew Moore if (ftattach(dev, fdup)) 299b99f0a4aSAndrew Moore continue; 30056ef0285SAndrew Moore if (fdsu < DRVS_PER_CTLR) 301b99f0a4aSAndrew Moore fd->type = NO_TYPE; 30256ef0285SAndrew Moore #endif 3035b81b6b3SRodney W. Grimes continue; 304f5f7ba03SJordan K. Hubbard } 3055b81b6b3SRodney W. Grimes 3065b81b6b3SRodney W. Grimes #ifdef notyet 3075b81b6b3SRodney W. Grimes /* select it */ 3085b81b6b3SRodney W. Grimes fd_turnon1(fdu); 3095b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 3105b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 3115b81b6b3SRodney W. Grimes out_fdc(fdcu,fdsu); 3125b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 3135b81b6b3SRodney W. Grimes 3145b81b6b3SRodney W. Grimes /* anything responding */ 3155b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 3165b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 3175b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 3185b81b6b3SRodney W. Grimes if (st0 & 0xd0) 3195b81b6b3SRodney W. Grimes continue; 3205b81b6b3SRodney W. Grimes 3215b81b6b3SRodney W. Grimes #endif 322b99f0a4aSAndrew Moore fd->track = -2; 323b99f0a4aSAndrew Moore fd->fdc = fdc; 324b99f0a4aSAndrew Moore fd->fdsu = fdsu; 325b99f0a4aSAndrew Moore printf(" [%d: fd%d: ", fdsu, fdu); 3265b81b6b3SRodney W. Grimes 327b99f0a4aSAndrew Moore switch (fdt) { 3287ca0641bSAndrey A. Chernov case RTCFDT_12M: 329b99f0a4aSAndrew Moore printf("1.2MB 5.25in]"); 330b99f0a4aSAndrew Moore fd->type = FD_1200; 3317ca0641bSAndrey A. Chernov break; 3327ca0641bSAndrey A. Chernov case RTCFDT_144M: 333b99f0a4aSAndrew Moore printf("1.44MB 3.5in]"); 334b99f0a4aSAndrew Moore fd->type = FD_1440; 3357ca0641bSAndrey A. Chernov break; 3367ca0641bSAndrey A. Chernov case RTCFDT_360K: 337b99f0a4aSAndrew Moore printf("360KB 5.25in]"); 338b99f0a4aSAndrew Moore fd->type = FD_360; 3397ca0641bSAndrey A. Chernov break; 340ed2fa05eSAndrey A. Chernov case RTCFDT_720K: 341b99f0a4aSAndrew Moore printf("720KB 3.5in]"); 342b99f0a4aSAndrew Moore fd->type = FD_720; 343ed2fa05eSAndrey A. Chernov break; 3447ca0641bSAndrey A. Chernov default: 345b99f0a4aSAndrew Moore printf("unknown]"); 346b99f0a4aSAndrew Moore fd->type = NO_TYPE; 3477ca0641bSAndrey A. Chernov break; 3485b81b6b3SRodney W. Grimes } 3495b81b6b3SRodney W. Grimes 350381fe1aaSGarrett Wollman fd_turnoff((caddr_t)fdu, 0); 3515b81b6b3SRodney W. Grimes hdr = 1; 3525b81b6b3SRodney W. Grimes } 353b99f0a4aSAndrew Moore printf("\n"); 3545b81b6b3SRodney W. Grimes 3555b81b6b3SRodney W. Grimes /* Set transfer to 500kbps */ 3565b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,0); /*XXX*/ 357381fe1aaSGarrett Wollman return 1; 3585b81b6b3SRodney W. Grimes } 3595b81b6b3SRodney W. Grimes 3605b81b6b3SRodney W. Grimes int 3615b81b6b3SRodney W. Grimes fdsize(dev) 3625b81b6b3SRodney W. Grimes dev_t dev; 3635b81b6b3SRodney W. Grimes { 3645b81b6b3SRodney W. Grimes return(0); 3655b81b6b3SRodney W. Grimes } 3665b81b6b3SRodney W. Grimes 3675b81b6b3SRodney W. Grimes /****************************************************************************/ 3685b81b6b3SRodney W. Grimes /* fdstrategy */ 3695b81b6b3SRodney W. Grimes /****************************************************************************/ 370381fe1aaSGarrett Wollman void fdstrategy(struct buf *bp) 3715b81b6b3SRodney W. Grimes { 3725b81b6b3SRodney W. Grimes register struct buf *dp,*dp0,*dp1; 3735b81b6b3SRodney W. Grimes long nblocks,blknum; 3745b81b6b3SRodney W. Grimes int s; 3755b81b6b3SRodney W. Grimes fdcu_t fdcu; 3765b81b6b3SRodney W. Grimes fdu_t fdu; 3775b81b6b3SRodney W. Grimes fdc_p fdc; 3785b81b6b3SRodney W. Grimes fd_p fd; 3795b81b6b3SRodney W. Grimes 3805b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 3815b81b6b3SRodney W. Grimes fd = &fd_data[fdu]; 3825b81b6b3SRodney W. Grimes fdc = fd->fdc; 3835b81b6b3SRodney W. Grimes fdcu = fdc->fdcu; 3845b81b6b3SRodney W. Grimes 385b99f0a4aSAndrew Moore #if NFT > 0 386b99f0a4aSAndrew Moore /* check for controller already busy with tape */ 387b99f0a4aSAndrew Moore if (fdc->flags & FDC_TAPE_BUSY) { 388b99f0a4aSAndrew Moore bp->b_error = EBUSY; 389b99f0a4aSAndrew Moore bp->b_flags |= B_ERROR; 390b99f0a4aSAndrew Moore return; 391b99f0a4aSAndrew Moore } 392b99f0a4aSAndrew Moore #endif 393a60eff27SNate Williams if ((fdu >= NFD) || (bp->b_blkno < 0)) { 3945b81b6b3SRodney W. Grimes printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n", 3955b81b6b3SRodney W. Grimes fdu, bp->b_blkno, bp->b_bcount); 3965b81b6b3SRodney W. Grimes pg("fd:error in fdstrategy"); 3975b81b6b3SRodney W. Grimes bp->b_error = EINVAL; 3985b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 3995b81b6b3SRodney W. Grimes goto bad; 4005b81b6b3SRodney W. Grimes } 4015b81b6b3SRodney W. Grimes /* 4025b81b6b3SRodney W. Grimes * Set up block calculations. 4035b81b6b3SRodney W. Grimes */ 4045b81b6b3SRodney W. Grimes blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK; 4055b81b6b3SRodney W. Grimes nblocks = fd->ft->size; 4065b81b6b3SRodney W. Grimes if (blknum + (bp->b_bcount / FDBLK) > nblocks) { 4075b81b6b3SRodney W. Grimes if (blknum == nblocks) { 4085b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount; 4095b81b6b3SRodney W. Grimes } else { 4105b81b6b3SRodney W. Grimes bp->b_error = ENOSPC; 4115b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 4125b81b6b3SRodney W. Grimes } 4135b81b6b3SRodney W. Grimes goto bad; 4145b81b6b3SRodney W. Grimes } 4155b81b6b3SRodney W. Grimes bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads); 4165b81b6b3SRodney W. Grimes dp = &(fdc->head); 4175b81b6b3SRodney W. Grimes s = splbio(); 4185b81b6b3SRodney W. Grimes disksort(dp, bp); 419aaf08d94SGarrett Wollman untimeout(fd_turnoff, (caddr_t)fdu); /* a good idea */ 4205b81b6b3SRodney W. Grimes fdstart(fdcu); 4215b81b6b3SRodney W. Grimes splx(s); 4225b81b6b3SRodney W. Grimes return; 4235b81b6b3SRodney W. Grimes 4245b81b6b3SRodney W. Grimes bad: 4255b81b6b3SRodney W. Grimes biodone(bp); 426b39c878eSAndrey A. Chernov return; 4275b81b6b3SRodney W. Grimes } 4285b81b6b3SRodney W. Grimes 4295b81b6b3SRodney W. Grimes /****************************************************************************/ 4305b81b6b3SRodney W. Grimes /* motor control stuff */ 4315b81b6b3SRodney W. Grimes /* remember to not deselect the drive we're working on */ 4325b81b6b3SRodney W. Grimes /****************************************************************************/ 433381fe1aaSGarrett Wollman void 434f5f7ba03SJordan K. Hubbard set_motor(fdcu, fdu, reset) 435f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 436f5f7ba03SJordan K. Hubbard fdu_t fdu; 437f5f7ba03SJordan K. Hubbard int reset; 4385b81b6b3SRodney W. Grimes { 4395b81b6b3SRodney W. Grimes int m0,m1; 4405b81b6b3SRodney W. Grimes int selunit; 4415b81b6b3SRodney W. Grimes fd_p fd; 4425b81b6b3SRodney W. Grimes if(fd = fdc_data[fdcu].fd)/* yes an assign! */ 4435b81b6b3SRodney W. Grimes { 4445b81b6b3SRodney W. Grimes selunit = fd->fdsu; 4455b81b6b3SRodney W. Grimes } 4465b81b6b3SRodney W. Grimes else 4475b81b6b3SRodney W. Grimes { 4485b81b6b3SRodney W. Grimes selunit = 0; 4495b81b6b3SRodney W. Grimes } 4505b81b6b3SRodney W. Grimes m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR; 4515b81b6b3SRodney W. Grimes m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR; 4525b81b6b3SRodney W. Grimes outb(fdc_data[fdcu].baseport+fdout, 4535b81b6b3SRodney W. Grimes selunit 4545b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4555b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4565b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0)); 4575b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdout]",( 4585b81b6b3SRodney W. Grimes selunit 4595b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4605b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4615b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0))); 4625b81b6b3SRodney W. Grimes } 4635b81b6b3SRodney W. Grimes 464381fe1aaSGarrett Wollman static void 465381fe1aaSGarrett Wollman fd_turnoff(caddr_t arg1, int arg2) 4665b81b6b3SRodney W. Grimes { 467381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 468f5f7ba03SJordan K. Hubbard int s; 469f5f7ba03SJordan K. Hubbard 4705b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 471f5f7ba03SJordan K. Hubbard s = splbio(); 4725b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR; 4735b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 474f5f7ba03SJordan K. Hubbard splx(s); 4755b81b6b3SRodney W. Grimes } 4765b81b6b3SRodney W. Grimes 477381fe1aaSGarrett Wollman void 478381fe1aaSGarrett Wollman fd_motor_on(caddr_t arg1, int arg2) 4795b81b6b3SRodney W. Grimes { 480381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 481f5f7ba03SJordan K. Hubbard int s; 482f5f7ba03SJordan K. Hubbard 4835b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 484f5f7ba03SJordan K. Hubbard s = splbio(); 4855b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR_WAIT; 4865b81b6b3SRodney W. Grimes if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) 4875b81b6b3SRodney W. Grimes { 488f5f7ba03SJordan K. Hubbard fdintr(fd->fdc->fdcu); 4895b81b6b3SRodney W. Grimes } 490f5f7ba03SJordan K. Hubbard splx(s); 4915b81b6b3SRodney W. Grimes } 4925b81b6b3SRodney W. Grimes 493381fe1aaSGarrett Wollman static void fd_turnon1(fdu_t); 494381fe1aaSGarrett Wollman 495381fe1aaSGarrett Wollman void 496f5f7ba03SJordan K. Hubbard fd_turnon(fdu) 497f5f7ba03SJordan K. Hubbard fdu_t fdu; 4985b81b6b3SRodney W. Grimes { 4995b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 5005b81b6b3SRodney W. Grimes if(!(fd->flags & FD_MOTOR)) 5015b81b6b3SRodney W. Grimes { 5025b81b6b3SRodney W. Grimes fd_turnon1(fdu); 5035b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR_WAIT; 504381fe1aaSGarrett Wollman timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ 5055b81b6b3SRodney W. Grimes } 5065b81b6b3SRodney W. Grimes } 5075b81b6b3SRodney W. Grimes 508381fe1aaSGarrett Wollman static void 509381fe1aaSGarrett Wollman fd_turnon1(fdu_t fdu) 5105b81b6b3SRodney W. Grimes { 5115b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 5125b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR; 5135b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 5145b81b6b3SRodney W. Grimes } 5155b81b6b3SRodney W. Grimes 5165b81b6b3SRodney W. Grimes /****************************************************************************/ 5175b81b6b3SRodney W. Grimes /* fdc in/out */ 5185b81b6b3SRodney W. Grimes /****************************************************************************/ 5195b81b6b3SRodney W. Grimes int 520f5f7ba03SJordan K. Hubbard in_fdc(fdcu) 521f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 5225b81b6b3SRodney W. Grimes { 5235b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5245b81b6b3SRodney W. Grimes int i, j = 100000; 5255b81b6b3SRodney W. Grimes while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM)) 5265b81b6b3SRodney W. Grimes != (NE7_DIO|NE7_RQM) && j-- > 0) 5275b81b6b3SRodney W. Grimes if (i == NE7_RQM) return -1; 5285b81b6b3SRodney W. Grimes if (j <= 0) 5295b81b6b3SRodney W. Grimes return(-1); 5305b81b6b3SRodney W. Grimes #ifdef DEBUG 5315b81b6b3SRodney W. Grimes i = inb(baseport+fddata); 5325b81b6b3SRodney W. Grimes TRACE1("[fddata->0x%x]",(unsigned char)i); 5335b81b6b3SRodney W. Grimes return(i); 5345b81b6b3SRodney W. Grimes #else 5355b81b6b3SRodney W. Grimes return inb(baseport+fddata); 5365b81b6b3SRodney W. Grimes #endif 5375b81b6b3SRodney W. Grimes } 5385b81b6b3SRodney W. Grimes 539381fe1aaSGarrett Wollman int 540f5f7ba03SJordan K. Hubbard out_fdc(fdcu, x) 541f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 542f5f7ba03SJordan K. Hubbard int x; 5435b81b6b3SRodney W. Grimes { 5445b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5453b3837dbSRodney W. Grimes int i; 5465b81b6b3SRodney W. Grimes 5473b3837dbSRodney W. Grimes /* Check that the direction bit is set */ 5483b3837dbSRodney W. Grimes i = 100000; 5495b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0); 5503b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5513b3837dbSRodney W. Grimes 5523b3837dbSRodney W. Grimes /* Check that the floppy controller is ready for a command */ 5533b3837dbSRodney W. Grimes i = 100000; 5545b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0); 5553b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5563b3837dbSRodney W. Grimes 5573b3837dbSRodney W. Grimes /* Send the command and return */ 5585b81b6b3SRodney W. Grimes outb(baseport+fddata,x); 5595b81b6b3SRodney W. Grimes TRACE1("[0x%x->fddata]",x); 5605b81b6b3SRodney W. Grimes return (0); 5615b81b6b3SRodney W. Grimes } 5625b81b6b3SRodney W. Grimes 5635b81b6b3SRodney W. Grimes /****************************************************************************/ 5645b81b6b3SRodney W. Grimes /* fdopen/fdclose */ 5655b81b6b3SRodney W. Grimes /****************************************************************************/ 566381fe1aaSGarrett Wollman int 5675b81b6b3SRodney W. Grimes Fdopen(dev, flags) 5685b81b6b3SRodney W. Grimes dev_t dev; 5695b81b6b3SRodney W. Grimes int flags; 5705b81b6b3SRodney W. Grimes { 5715b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 57220a29168SAndrey A. Chernov int type = FDTYPE(minor(dev)); 573b99f0a4aSAndrew Moore fdc_p fdc; 5745b81b6b3SRodney W. Grimes 575b99f0a4aSAndrew Moore #if NFT > 0 576b99f0a4aSAndrew Moore /* check for a tape open */ 577b99f0a4aSAndrew Moore if (type & F_TAPE_TYPE) 578b99f0a4aSAndrew Moore return(ftopen(dev, flags)); 579b99f0a4aSAndrew Moore #endif 5805b81b6b3SRodney W. Grimes /* check bounds */ 581b99f0a4aSAndrew Moore if (fdu >= NFD) 582b99f0a4aSAndrew Moore return(ENXIO); 583b99f0a4aSAndrew Moore fdc = fd_data[fdu].fdc; 584b99f0a4aSAndrew Moore if ((fdc == NULL) || (fd_data[fdu].type == NO_TYPE)) 585b99f0a4aSAndrew Moore return(ENXIO); 586b99f0a4aSAndrew Moore if (type > NUMDENS) 587b99f0a4aSAndrew Moore return(ENXIO); 5887ca0641bSAndrey A. Chernov if (type == 0) 5897ca0641bSAndrey A. Chernov type = fd_data[fdu].type; 5907ca0641bSAndrey A. Chernov else { 5917ca0641bSAndrey A. Chernov if (type != fd_data[fdu].type) { 592fa4700b4SAndrey A. Chernov switch (fd_data[fdu].type) { 5937ca0641bSAndrey A. Chernov case FD_360: 5947ca0641bSAndrey A. Chernov return(ENXIO); 595ed2fa05eSAndrey A. Chernov case FD_720: 596b39c878eSAndrey A. Chernov if ( type != FD_820 597b39c878eSAndrey A. Chernov && type != FD_800 598ed2fa05eSAndrey A. Chernov ) 599ed2fa05eSAndrey A. Chernov return(ENXIO); 600ed2fa05eSAndrey A. Chernov break; 6017ca0641bSAndrey A. Chernov case FD_1200: 602b39c878eSAndrey A. Chernov switch (type) { 603b39c878eSAndrey A. Chernov case FD_1480: 604b39c878eSAndrey A. Chernov type = FD_1480in5_25; 605fa4700b4SAndrey A. Chernov break; 6067ca0641bSAndrey A. Chernov case FD_1440: 607b39c878eSAndrey A. Chernov type = FD_1440in5_25; 608b39c878eSAndrey A. Chernov break; 609b39c878eSAndrey A. Chernov case FD_820: 610b39c878eSAndrey A. Chernov type = FD_820in5_25; 611b39c878eSAndrey A. Chernov break; 612b39c878eSAndrey A. Chernov case FD_800: 613b39c878eSAndrey A. Chernov type = FD_800in5_25; 614b39c878eSAndrey A. Chernov break; 615b39c878eSAndrey A. Chernov case FD_720: 616b39c878eSAndrey A. Chernov type = FD_720in5_25; 617b39c878eSAndrey A. Chernov break; 618b39c878eSAndrey A. Chernov case FD_360: 619b39c878eSAndrey A. Chernov type = FD_360in5_25; 620b39c878eSAndrey A. Chernov break; 621b39c878eSAndrey A. Chernov default: 622b39c878eSAndrey A. Chernov return(ENXIO); 623b39c878eSAndrey A. Chernov } 624b39c878eSAndrey A. Chernov break; 625b39c878eSAndrey A. Chernov case FD_1440: 626b39c878eSAndrey A. Chernov if ( type != FD_1720 627b39c878eSAndrey A. Chernov && type != FD_1480 628ed2fa05eSAndrey A. Chernov && type != FD_1200 629b39c878eSAndrey A. Chernov && type != FD_820 630b39c878eSAndrey A. Chernov && type != FD_800 631b39c878eSAndrey A. Chernov && type != FD_720 6327ca0641bSAndrey A. Chernov ) 633dffff499SAndrey A. Chernov return(ENXIO); 634fa4700b4SAndrey A. Chernov break; 6357ca0641bSAndrey A. Chernov } 6367ca0641bSAndrey A. Chernov } 637fa4700b4SAndrey A. Chernov } 638b99f0a4aSAndrew Moore fd_data[fdu].ft = fd_types + type - 1; 6395b81b6b3SRodney W. Grimes fd_data[fdu].flags |= FD_OPEN; 6405b81b6b3SRodney W. Grimes 6415b81b6b3SRodney W. Grimes return 0; 6425b81b6b3SRodney W. Grimes } 6435b81b6b3SRodney W. Grimes 644381fe1aaSGarrett Wollman int 6455b81b6b3SRodney W. Grimes fdclose(dev, flags) 6465b81b6b3SRodney W. Grimes dev_t dev; 647381fe1aaSGarrett Wollman int flags; 6485b81b6b3SRodney W. Grimes { 6495b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 650b99f0a4aSAndrew Moore int type = FDTYPE(minor(dev)); 651b99f0a4aSAndrew Moore 652b99f0a4aSAndrew Moore #if NFT > 0 653b99f0a4aSAndrew Moore if (type & F_TAPE_TYPE) 654b99f0a4aSAndrew Moore return ftclose(0); 655b99f0a4aSAndrew Moore #endif 6565b81b6b3SRodney W. Grimes fd_data[fdu].flags &= ~FD_OPEN; 6575b81b6b3SRodney W. Grimes return(0); 6585b81b6b3SRodney W. Grimes } 6595b81b6b3SRodney W. Grimes 6605b81b6b3SRodney W. Grimes 6615b81b6b3SRodney W. Grimes /***************************************************************\ 6625b81b6b3SRodney W. Grimes * fdstart * 6635b81b6b3SRodney W. Grimes * We have just queued something.. if the controller is not busy * 6645b81b6b3SRodney W. Grimes * then simulate the case where it has just finished a command * 6655b81b6b3SRodney W. Grimes * So that it (the interrupt routine) looks on the queue for more* 6665b81b6b3SRodney W. Grimes * work to do and picks up what we just added. * 6675b81b6b3SRodney W. Grimes * If the controller is already busy, we need do nothing, as it * 6685b81b6b3SRodney W. Grimes * will pick up our work when the present work completes * 6695b81b6b3SRodney W. Grimes \***************************************************************/ 670381fe1aaSGarrett Wollman static void 671f5f7ba03SJordan K. Hubbard fdstart(fdcu) 672f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 6735b81b6b3SRodney W. Grimes { 6745b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 6755b81b6b3SRodney W. Grimes int s; 6765b81b6b3SRodney W. Grimes fdu_t fdu; 6775b81b6b3SRodney W. Grimes 6785b81b6b3SRodney W. Grimes s = splbio(); 6795b81b6b3SRodney W. Grimes if(fdc_data[fdcu].state == DEVIDLE) 6805b81b6b3SRodney W. Grimes { 6815b81b6b3SRodney W. Grimes fdintr(fdcu); 6825b81b6b3SRodney W. Grimes } 6835b81b6b3SRodney W. Grimes splx(s); 6845b81b6b3SRodney W. Grimes } 6855b81b6b3SRodney W. Grimes 686381fe1aaSGarrett Wollman static void 687381fe1aaSGarrett Wollman fd_timeout(caddr_t arg1, int arg2) 6885b81b6b3SRodney W. Grimes { 689381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 6905b81b6b3SRodney W. Grimes fdu_t fdu = fdc_data[fdcu].fdu; 6915b81b6b3SRodney W. Grimes int st0, st3, cyl; 6925b81b6b3SRodney W. Grimes struct buf *dp,*bp; 693f5f7ba03SJordan K. Hubbard int s; 6945b81b6b3SRodney W. Grimes 6955b81b6b3SRodney W. Grimes dp = &fdc_data[fdcu].head; 696f5f7ba03SJordan K. Hubbard s = splbio(); 6975b81b6b3SRodney W. Grimes bp = dp->b_actf; 6985b81b6b3SRodney W. Grimes 6995b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSED); 7005b81b6b3SRodney W. Grimes out_fdc(fdcu,fd_data[fdu].hddrv); 7015b81b6b3SRodney W. Grimes st3 = in_fdc(fdcu); 7025b81b6b3SRodney W. Grimes 7035b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 7045b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 7055b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 7065b81b6b3SRodney W. Grimes printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n", 7075b81b6b3SRodney W. Grimes fdu, 7085b81b6b3SRodney W. Grimes st0, 7095b81b6b3SRodney W. Grimes NE7_ST0BITS, 7105b81b6b3SRodney W. Grimes cyl, 7115b81b6b3SRodney W. Grimes st3, 7125b81b6b3SRodney W. Grimes NE7_ST3BITS); 7135b81b6b3SRodney W. Grimes 7145b81b6b3SRodney W. Grimes if (bp) 7155b81b6b3SRodney W. Grimes { 7165b81b6b3SRodney W. Grimes retrier(fdcu); 7175b81b6b3SRodney W. Grimes fdc_data[fdcu].status[0] = 0xc0; 7185b81b6b3SRodney W. Grimes fdc_data[fdcu].state = IOTIMEDOUT; 7195b81b6b3SRodney W. Grimes if( fdc_data[fdcu].retry < 6) 7205b81b6b3SRodney W. Grimes fdc_data[fdcu].retry = 6; 7215b81b6b3SRodney W. Grimes } 7225b81b6b3SRodney W. Grimes else 7235b81b6b3SRodney W. Grimes { 7245b81b6b3SRodney W. Grimes fdc_data[fdcu].fd = (fd_p) 0; 7255b81b6b3SRodney W. Grimes fdc_data[fdcu].fdu = -1; 7265b81b6b3SRodney W. Grimes fdc_data[fdcu].state = DEVIDLE; 7275b81b6b3SRodney W. Grimes } 728f5f7ba03SJordan K. Hubbard fdintr(fdcu); 729f5f7ba03SJordan K. Hubbard splx(s); 7305b81b6b3SRodney W. Grimes } 7315b81b6b3SRodney W. Grimes 7325b81b6b3SRodney W. Grimes /* just ensure it has the right spl */ 733381fe1aaSGarrett Wollman static void 734381fe1aaSGarrett Wollman fd_pseudointr(caddr_t arg1, int arg2) 7355b81b6b3SRodney W. Grimes { 736381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 7375b81b6b3SRodney W. Grimes int s; 7385b81b6b3SRodney W. Grimes s = splbio(); 7395b81b6b3SRodney W. Grimes fdintr(fdcu); 7405b81b6b3SRodney W. Grimes splx(s); 7415b81b6b3SRodney W. Grimes } 7425b81b6b3SRodney W. Grimes 7435b81b6b3SRodney W. Grimes /***********************************************************************\ 7445b81b6b3SRodney W. Grimes * fdintr * 7455b81b6b3SRodney W. Grimes * keep calling the state machine until it returns a 0 * 7465b81b6b3SRodney W. Grimes * ALWAYS called at SPLBIO * 7475b81b6b3SRodney W. Grimes \***********************************************************************/ 748381fe1aaSGarrett Wollman void 749381fe1aaSGarrett Wollman fdintr(fdcu_t fdcu) 7505b81b6b3SRodney W. Grimes { 7515b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 752b99f0a4aSAndrew Moore #if NFT > 0 753b99f0a4aSAndrew Moore fdu_t fdu = fdc->fdu; 754b99f0a4aSAndrew Moore 755b99f0a4aSAndrew Moore if (fdc->flags & FDC_TAPE_BUSY) 756b99f0a4aSAndrew Moore (ftintr(fdu)); 757b99f0a4aSAndrew Moore else 758b99f0a4aSAndrew Moore #endif 759381fe1aaSGarrett Wollman while(fdstate(fdcu, fdc)) 760381fe1aaSGarrett Wollman ; 7615b81b6b3SRodney W. Grimes } 7625b81b6b3SRodney W. Grimes 7635b81b6b3SRodney W. Grimes /***********************************************************************\ 7645b81b6b3SRodney W. Grimes * The controller state machine. * 7655b81b6b3SRodney W. Grimes * if it returns a non zero value, it should be called again immediatly * 7665b81b6b3SRodney W. Grimes \***********************************************************************/ 767381fe1aaSGarrett Wollman int 768381fe1aaSGarrett Wollman fdstate(fdcu, fdc) 769f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 770f5f7ba03SJordan K. Hubbard fdc_p fdc; 7715b81b6b3SRodney W. Grimes { 772b39c878eSAndrey A. Chernov int read, format, head, trac, sec = 0, i = 0, s, sectrac, cyl, st0; 7735b81b6b3SRodney W. Grimes unsigned long blknum; 7745b81b6b3SRodney W. Grimes fdu_t fdu = fdc->fdu; 7755b81b6b3SRodney W. Grimes fd_p fd; 7765b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 777b39c878eSAndrey A. Chernov struct fd_formb *finfo = NULL; 7785b81b6b3SRodney W. Grimes 7795b81b6b3SRodney W. Grimes dp = &(fdc->head); 7805b81b6b3SRodney W. Grimes bp = dp->b_actf; 7815b81b6b3SRodney W. Grimes if(!bp) 7825b81b6b3SRodney W. Grimes { 7835b81b6b3SRodney W. Grimes /***********************************************\ 7845b81b6b3SRodney W. Grimes * nothing left for this controller to do * 7855b81b6b3SRodney W. Grimes * Force into the IDLE state, * 7865b81b6b3SRodney W. Grimes \***********************************************/ 7875b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 7885b81b6b3SRodney W. Grimes if(fdc->fd) 7895b81b6b3SRodney W. Grimes { 7905b81b6b3SRodney W. Grimes printf("unexpected valid fd pointer (fdu = %d)\n" 7915b81b6b3SRodney W. Grimes ,fdc->fdu); 7925b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 7935b81b6b3SRodney W. Grimes fdc->fdu = -1; 7945b81b6b3SRodney W. Grimes } 7955b81b6b3SRodney W. Grimes TRACE1("[fdc%d IDLE]",fdcu); 7965b81b6b3SRodney W. Grimes return(0); 7975b81b6b3SRodney W. Grimes } 7985b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 7995b81b6b3SRodney W. Grimes fd = fd_data + fdu; 8005b81b6b3SRodney W. Grimes if (fdc->fd && (fd != fdc->fd)) 8015b81b6b3SRodney W. Grimes { 8025b81b6b3SRodney W. Grimes printf("confused fd pointers\n"); 8035b81b6b3SRodney W. Grimes } 8045b81b6b3SRodney W. Grimes read = bp->b_flags & B_READ; 805b39c878eSAndrey A. Chernov format = bp->b_flags & B_FORMAT; 806b39c878eSAndrey A. Chernov if(format) 807b39c878eSAndrey A. Chernov finfo = (struct fd_formb *)bp->b_un.b_addr; 8085b81b6b3SRodney W. Grimes TRACE1("fd%d",fdu); 8095b81b6b3SRodney W. Grimes TRACE1("[%s]",fdstates[fdc->state]); 8105b81b6b3SRodney W. Grimes TRACE1("(0x%x)",fd->flags); 811aaf08d94SGarrett Wollman untimeout(fd_turnoff, (caddr_t)fdu); 812381fe1aaSGarrett Wollman timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); 8135b81b6b3SRodney W. Grimes switch (fdc->state) 8145b81b6b3SRodney W. Grimes { 8155b81b6b3SRodney W. Grimes case DEVIDLE: 8165b81b6b3SRodney W. Grimes case FINDWORK: /* we have found new work */ 8175b81b6b3SRodney W. Grimes fdc->retry = 0; 8185b81b6b3SRodney W. Grimes fd->skip = 0; 8195b81b6b3SRodney W. Grimes fdc->fd = fd; 8205b81b6b3SRodney W. Grimes fdc->fdu = fdu; 8215b81b6b3SRodney W. Grimes /*******************************************************\ 8225b81b6b3SRodney W. Grimes * If the next drive has a motor startup pending, then * 8235b81b6b3SRodney W. Grimes * it will start up in it's own good time * 8245b81b6b3SRodney W. Grimes \*******************************************************/ 8255b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 8265b81b6b3SRodney W. Grimes { 8275b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 8285b81b6b3SRodney W. Grimes return(0); /* come back later */ 8295b81b6b3SRodney W. Grimes } 8305b81b6b3SRodney W. Grimes /*******************************************************\ 8315b81b6b3SRodney W. Grimes * Maybe if it's not starting, it SHOULD be starting * 8325b81b6b3SRodney W. Grimes \*******************************************************/ 8335b81b6b3SRodney W. Grimes if (!(fd->flags & FD_MOTOR)) 8345b81b6b3SRodney W. Grimes { 8355b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 8365b81b6b3SRodney W. Grimes fd_turnon(fdu); 8375b81b6b3SRodney W. Grimes return(0); 8385b81b6b3SRodney W. Grimes } 8395b81b6b3SRodney W. Grimes else /* at least make sure we are selected */ 8405b81b6b3SRodney W. Grimes { 8415b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 8425b81b6b3SRodney W. Grimes } 8435b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 8445b81b6b3SRodney W. Grimes break; 8455b81b6b3SRodney W. Grimes case DOSEEK: 8465b81b6b3SRodney W. Grimes if (bp->b_cylin == fd->track) 8475b81b6b3SRodney W. Grimes { 8485b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8495b81b6b3SRodney W. Grimes break; 8505b81b6b3SRodney W. Grimes } 8515b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SEEK); /* Seek function */ 8525b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); /* Drive number */ 8535b81b6b3SRodney W. Grimes out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac); 8545b81b6b3SRodney W. Grimes fd->track = -2; 8555b81b6b3SRodney W. Grimes fdc->state = SEEKWAIT; 856381fe1aaSGarrett Wollman timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 8575b81b6b3SRodney W. Grimes return(0); /* will return later */ 8585b81b6b3SRodney W. Grimes case SEEKWAIT: 859aaf08d94SGarrett Wollman untimeout(fd_timeout, (caddr_t)fdcu); 8605b81b6b3SRodney W. Grimes /* allow heads to settle */ 861381fe1aaSGarrett Wollman timeout(fd_pseudointr, (caddr_t)fdcu, hz / 50); 8625b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8635b81b6b3SRodney W. Grimes return(0); /* will return later */ 8645b81b6b3SRodney W. Grimes break; 8655b81b6b3SRodney W. Grimes 8665b81b6b3SRodney W. Grimes case SEEKCOMPLETE : /* SEEK DONE, START DMA */ 8675b81b6b3SRodney W. Grimes /* Make sure seek really happened*/ 8685b81b6b3SRodney W. Grimes if(fd->track == -2) 8695b81b6b3SRodney W. Grimes { 8705b81b6b3SRodney W. Grimes int descyl = bp->b_cylin * fd->ft->steptrac; 8715b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 8725b81b6b3SRodney W. Grimes i = in_fdc(fdcu); 8735b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 8745b81b6b3SRodney W. Grimes if (cyl != descyl) 8755b81b6b3SRodney W. Grimes { 876b99f0a4aSAndrew Moore printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", 877b99f0a4aSAndrew Moore fdu, descyl, cyl, i, NE7_ST0BITS); 8785b81b6b3SRodney W. Grimes return(retrier(fdcu)); 8795b81b6b3SRodney W. Grimes } 8805b81b6b3SRodney W. Grimes } 8815b81b6b3SRodney W. Grimes 8825b81b6b3SRodney W. Grimes fd->track = bp->b_cylin; 883b39c878eSAndrey A. Chernov if(format) 884b39c878eSAndrey A. Chernov fd->skip = (char *)&(finfo->fd_formb_cylno(0)) 885b39c878eSAndrey A. Chernov - (char *)finfo; 8865b81b6b3SRodney W. Grimes isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip, 887b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 8885b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 8895b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 8905b81b6b3SRodney W. Grimes sectrac = fd->ft->sectrac; 8915b81b6b3SRodney W. Grimes sec = blknum % (sectrac * fd->ft->heads); 8925b81b6b3SRodney W. Grimes head = sec / sectrac; 8935b81b6b3SRodney W. Grimes sec = sec % sectrac + 1; 8945b81b6b3SRodney W. Grimes /*XXX*/ fd->hddrv = ((head&1)<<2)+fdu; 8955b81b6b3SRodney W. Grimes 896b39c878eSAndrey A. Chernov if(format) 897b39c878eSAndrey A. Chernov { 898b39c878eSAndrey A. Chernov /* formatting */ 899b39c878eSAndrey A. Chernov out_fdc(fdcu,/* NE7CMD_FORMAT */ 0x4d); 900b39c878eSAndrey A. Chernov out_fdc(fdcu,head << 2 | fdu); 901b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_secshift); 902b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_nsecs); 903b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_gaplen); 904b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_fillbyte); 905b39c878eSAndrey A. Chernov } 906b39c878eSAndrey A. Chernov else 907b39c878eSAndrey A. Chernov { 9085b81b6b3SRodney W. Grimes if (read) 9095b81b6b3SRodney W. Grimes { 9105b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_READ); /* READ */ 9115b81b6b3SRodney W. Grimes } 9125b81b6b3SRodney W. Grimes else 9135b81b6b3SRodney W. Grimes { 9145b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_WRITE); /* WRITE */ 9155b81b6b3SRodney W. Grimes } 9165b81b6b3SRodney W. Grimes out_fdc(fdcu,head << 2 | fdu); /* head & unit */ 9175b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->track); /* track */ 9185b81b6b3SRodney W. Grimes out_fdc(fdcu,head); 9195b81b6b3SRodney W. Grimes out_fdc(fdcu,sec); /* sector XXX +1? */ 9205b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->secsize); /* sector size */ 9215b81b6b3SRodney W. Grimes out_fdc(fdcu,sectrac); /* sectors/track */ 9225b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->gap); /* gap size */ 9235b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->datalen); /* data length */ 924b39c878eSAndrey A. Chernov } 9255b81b6b3SRodney W. Grimes fdc->state = IOCOMPLETE; 926381fe1aaSGarrett Wollman timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 9275b81b6b3SRodney W. Grimes return(0); /* will return later */ 9285b81b6b3SRodney W. Grimes case IOCOMPLETE: /* IO DONE, post-analyze */ 929aaf08d94SGarrett Wollman untimeout(fd_timeout, (caddr_t)fdcu); 9305b81b6b3SRodney W. Grimes for(i=0;i<7;i++) 9315b81b6b3SRodney W. Grimes { 9325b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 9335b81b6b3SRodney W. Grimes } 9345b81b6b3SRodney W. Grimes case IOTIMEDOUT: /*XXX*/ 9355b81b6b3SRodney W. Grimes isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, 936b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 9375b81b6b3SRodney W. Grimes if (fdc->status[0]&0xF8) 9385b81b6b3SRodney W. Grimes { 939b39c878eSAndrey A. Chernov if (fdc->status[1] & 0x10) { 940b39c878eSAndrey A. Chernov /* 941b39c878eSAndrey A. Chernov * Operation not completed in reasonable time. 942b39c878eSAndrey A. Chernov * Just restart it, don't increment retry count. 943b39c878eSAndrey A. Chernov * (vak) 944b39c878eSAndrey A. Chernov */ 945b39c878eSAndrey A. Chernov fdc->state = SEEKCOMPLETE; 946b39c878eSAndrey A. Chernov return (1); 947b39c878eSAndrey A. Chernov } 9485b81b6b3SRodney W. Grimes return(retrier(fdcu)); 9495b81b6b3SRodney W. Grimes } 9505b81b6b3SRodney W. Grimes /* All OK */ 9515b81b6b3SRodney W. Grimes fd->skip += FDBLK; 952b39c878eSAndrey A. Chernov if (!format && fd->skip < bp->b_bcount) 9535b81b6b3SRodney W. Grimes { 9545b81b6b3SRodney W. Grimes /* set up next transfer */ 9555b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 9565b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 9575b81b6b3SRodney W. Grimes bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads)); 9585b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9595b81b6b3SRodney W. Grimes } 9605b81b6b3SRodney W. Grimes else 9615b81b6b3SRodney W. Grimes { 9625b81b6b3SRodney W. Grimes /* ALL DONE */ 9635b81b6b3SRodney W. Grimes fd->skip = 0; 9645b81b6b3SRodney W. Grimes bp->b_resid = 0; 9655b81b6b3SRodney W. Grimes dp->b_actf = bp->av_forw; 9665b81b6b3SRodney W. Grimes biodone(bp); 9675b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 9685b81b6b3SRodney W. Grimes fdc->fdu = -1; 9695b81b6b3SRodney W. Grimes fdc->state = FINDWORK; 9705b81b6b3SRodney W. Grimes } 9715b81b6b3SRodney W. Grimes return(1); 9725b81b6b3SRodney W. Grimes case RESETCTLR: 9735b81b6b3SRodney W. Grimes /* Try a reset, keep motor on */ 9745b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,1); 9755b81b6b3SRodney W. Grimes DELAY(100); 9765b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 9775b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,fd->ft->trans); 9785b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdctl]",fd->ft->trans); 9795b81b6b3SRodney W. Grimes fdc->retry++; 9805b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 9815b81b6b3SRodney W. Grimes break; 9825b81b6b3SRodney W. Grimes case STARTRECAL: 9835b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */ 9845b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 9855b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 9865b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 9875b81b6b3SRodney W. Grimes out_fdc(fdcu,fdu); 9885b81b6b3SRodney W. Grimes fdc->state = RECALWAIT; 9895b81b6b3SRodney W. Grimes return(0); /* will return later */ 9905b81b6b3SRodney W. Grimes case RECALWAIT: 9915b81b6b3SRodney W. Grimes /* allow heads to settle */ 992381fe1aaSGarrett Wollman timeout(fd_pseudointr, (caddr_t)fdcu, hz / 30); 9935b81b6b3SRodney W. Grimes fdc->state = RECALCOMPLETE; 9945b81b6b3SRodney W. Grimes return(0); /* will return later */ 9955b81b6b3SRodney W. Grimes case RECALCOMPLETE: 9965b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 9975b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 9985b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 9995b81b6b3SRodney W. Grimes if (cyl != 0) 10005b81b6b3SRodney W. Grimes { 10015b81b6b3SRodney W. Grimes printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, 10025b81b6b3SRodney W. Grimes st0, NE7_ST0BITS, cyl); 10035b81b6b3SRodney W. Grimes return(retrier(fdcu)); 10045b81b6b3SRodney W. Grimes } 10055b81b6b3SRodney W. Grimes fd->track = 0; 10065b81b6b3SRodney W. Grimes /* Seek (probably) necessary */ 10075b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 10085b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 10095b81b6b3SRodney W. Grimes case MOTORWAIT: 10105b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 10115b81b6b3SRodney W. Grimes { 10125b81b6b3SRodney W. Grimes return(0); /* time's not up yet */ 10135b81b6b3SRodney W. Grimes } 10145b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 10155b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 10165b81b6b3SRodney W. Grimes default: 10175b81b6b3SRodney W. Grimes printf("Unexpected FD int->"); 10185b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 10195b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 10205b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 10215b81b6b3SRodney W. Grimes printf("ST0 = %lx, PCN = %lx\n",i,sec); 10225b81b6b3SRodney W. Grimes out_fdc(fdcu,0x4A); 10235b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); 10245b81b6b3SRodney W. Grimes for(i=0;i<7;i++) { 10255b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 10265b81b6b3SRodney W. Grimes } 10275b81b6b3SRodney W. Grimes printf("intr status :%lx %lx %lx %lx %lx %lx %lx ", 10285b81b6b3SRodney W. Grimes fdc->status[0], 10295b81b6b3SRodney W. Grimes fdc->status[1], 10305b81b6b3SRodney W. Grimes fdc->status[2], 10315b81b6b3SRodney W. Grimes fdc->status[3], 10325b81b6b3SRodney W. Grimes fdc->status[4], 10335b81b6b3SRodney W. Grimes fdc->status[5], 10345b81b6b3SRodney W. Grimes fdc->status[6] ); 10355b81b6b3SRodney W. Grimes return(0); 10365b81b6b3SRodney W. Grimes } 10375b81b6b3SRodney W. Grimes return(1); /* Come back immediatly to new state */ 10385b81b6b3SRodney W. Grimes } 10395b81b6b3SRodney W. Grimes 1040aaf08d94SGarrett Wollman static int 1041f5f7ba03SJordan K. Hubbard retrier(fdcu) 1042f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 10435b81b6b3SRodney W. Grimes { 10445b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 10455b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 10465b81b6b3SRodney W. Grimes 10475b81b6b3SRodney W. Grimes dp = &(fdc->head); 10485b81b6b3SRodney W. Grimes bp = dp->b_actf; 10495b81b6b3SRodney W. Grimes 10505b81b6b3SRodney W. Grimes switch(fdc->retry) 10515b81b6b3SRodney W. Grimes { 10525b81b6b3SRodney W. Grimes case 0: case 1: case 2: 10535b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 10545b81b6b3SRodney W. Grimes break; 10555b81b6b3SRodney W. Grimes case 3: case 4: case 5: 10565b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 10575b81b6b3SRodney W. Grimes break; 10585b81b6b3SRodney W. Grimes case 6: 10595b81b6b3SRodney W. Grimes fdc->state = RESETCTLR; 10605b81b6b3SRodney W. Grimes break; 10615b81b6b3SRodney W. Grimes case 7: 10625b81b6b3SRodney W. Grimes break; 10635b81b6b3SRodney W. Grimes default: 10645b81b6b3SRodney W. Grimes { 10657ca0641bSAndrey A. Chernov dev_t sav_b_dev = bp->b_dev; 10667ca0641bSAndrey A. Chernov /* Trick diskerr */ 10677ca0641bSAndrey A. Chernov bp->b_dev = makedev(major(bp->b_dev), (FDUNIT(minor(bp->b_dev))<<3)|3); 106892ed385aSRodney W. Grimes diskerr(bp, "fd", "hard error", LOG_PRINTF, 106992ed385aSRodney W. Grimes fdc->fd->skip, (struct disklabel *)NULL); 10707ca0641bSAndrey A. Chernov bp->b_dev = sav_b_dev; 107192ed385aSRodney W. Grimes printf(" (ST0 %b ", fdc->status[0], NE7_ST0BITS); 10725b81b6b3SRodney W. Grimes printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS); 10735b81b6b3SRodney W. Grimes printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS); 10745b81b6b3SRodney W. Grimes printf("cyl %d hd %d sec %d)\n", 107592ed385aSRodney W. Grimes fdc->status[3], fdc->status[4], fdc->status[5]); 10765b81b6b3SRodney W. Grimes } 10775b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 10785b81b6b3SRodney W. Grimes bp->b_error = EIO; 10795b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount - fdc->fd->skip; 10805b81b6b3SRodney W. Grimes dp->b_actf = bp->av_forw; 10815b81b6b3SRodney W. Grimes fdc->fd->skip = 0; 10825b81b6b3SRodney W. Grimes biodone(bp); 108392ed385aSRodney W. Grimes fdc->state = FINDWORK; 10845b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 10855b81b6b3SRodney W. Grimes fdc->fdu = -1; 1086f5f7ba03SJordan K. Hubbard /* XXX abort current command, if any. */ 108792ed385aSRodney W. Grimes return(1); 10885b81b6b3SRodney W. Grimes } 10895b81b6b3SRodney W. Grimes fdc->retry++; 10905b81b6b3SRodney W. Grimes return(1); 10915b81b6b3SRodney W. Grimes } 10925b81b6b3SRodney W. Grimes 1093b39c878eSAndrey A. Chernov static int 1094b39c878eSAndrey A. Chernov fdformat(dev, finfo, p) 1095b39c878eSAndrey A. Chernov dev_t dev; 1096b39c878eSAndrey A. Chernov struct fd_formb *finfo; 1097b39c878eSAndrey A. Chernov struct proc *p; 1098b39c878eSAndrey A. Chernov { 1099b39c878eSAndrey A. Chernov fdu_t fdu; 1100b39c878eSAndrey A. Chernov fd_p fd; 1101b39c878eSAndrey A. Chernov 1102b39c878eSAndrey A. Chernov struct buf *bp; 1103b39c878eSAndrey A. Chernov int rv = 0, s; 1104b39c878eSAndrey A. Chernov 1105b39c878eSAndrey A. Chernov fdu = FDUNIT(minor(dev)); 1106b39c878eSAndrey A. Chernov fd = &fd_data[fdu]; 1107b39c878eSAndrey A. Chernov 1108b39c878eSAndrey A. Chernov /* set up a buffer header for fdstrategy() */ 1109b39c878eSAndrey A. Chernov bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 1110b39c878eSAndrey A. Chernov if(bp == 0) 1111b39c878eSAndrey A. Chernov return ENOBUFS; 1112b39c878eSAndrey A. Chernov bzero((void *)bp, sizeof(struct buf)); 1113b39c878eSAndrey A. Chernov bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 1114b39c878eSAndrey A. Chernov bp->b_proc = p; 1115b39c878eSAndrey A. Chernov bp->b_dev = dev; 1116b39c878eSAndrey A. Chernov 1117b39c878eSAndrey A. Chernov /* 1118b39c878eSAndrey A. Chernov * calculate a fake blkno, so fdstrategy() would initiate a 1119b39c878eSAndrey A. Chernov * seek to the requested cylinder 1120b39c878eSAndrey A. Chernov */ 1121b39c878eSAndrey A. Chernov bp->b_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) 1122b39c878eSAndrey A. Chernov + finfo->head * fd->ft->sectrac) * FDBLK / DEV_BSIZE; 1123b39c878eSAndrey A. Chernov 1124b39c878eSAndrey A. Chernov bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 1125b39c878eSAndrey A. Chernov bp->b_un.b_addr = (caddr_t)finfo; 1126b39c878eSAndrey A. Chernov 1127b39c878eSAndrey A. Chernov /* now do the format */ 1128b39c878eSAndrey A. Chernov fdstrategy(bp); 1129b39c878eSAndrey A. Chernov 1130b39c878eSAndrey A. Chernov /* ...and wait for it to complete */ 1131b39c878eSAndrey A. Chernov s = splbio(); 1132b39c878eSAndrey A. Chernov while(!(bp->b_flags & B_DONE)) 1133b39c878eSAndrey A. Chernov { 1134b39c878eSAndrey A. Chernov rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 1135b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1136b39c878eSAndrey A. Chernov break; 1137b39c878eSAndrey A. Chernov } 1138b39c878eSAndrey A. Chernov splx(s); 1139b39c878eSAndrey A. Chernov 1140b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1141b39c878eSAndrey A. Chernov { 1142b39c878eSAndrey A. Chernov /* timed out */ 1143b39c878eSAndrey A. Chernov biodone(bp); 1144b39c878eSAndrey A. Chernov rv = EIO; 1145b39c878eSAndrey A. Chernov } 1146b39c878eSAndrey A. Chernov free(bp, M_TEMP); 1147b39c878eSAndrey A. Chernov return rv; 1148b39c878eSAndrey A. Chernov } 1149b39c878eSAndrey A. Chernov 1150f5f7ba03SJordan K. Hubbard /* 1151f5f7ba03SJordan K. Hubbard * fdioctl() from jc@irbs.UUCP (John Capo) 1152f5f7ba03SJordan K. Hubbard * i386/i386/conf.c needs to have fdioctl() declared and remove the line that 1153f5f7ba03SJordan K. Hubbard * defines fdioctl to be enxio. 1154f5f7ba03SJordan K. Hubbard * 1155f5f7ba03SJordan K. Hubbard * TODO: Reformat. 1156f5f7ba03SJordan K. Hubbard * Think about allocating buffer off stack. 1157f5f7ba03SJordan K. Hubbard * Don't pass uncast 0's and NULL's to read/write/setdisklabel(). 1158f5f7ba03SJordan K. Hubbard * Watch out for NetBSD's different *disklabel() interface. 1159b39c878eSAndrey A. Chernov * 1160b39c878eSAndrey A. Chernov * Added functionality for floppy formatting 1161b39c878eSAndrey A. Chernov * joerg_wunsch@uriah.sax.de (Joerg Wunsch) 1162f5f7ba03SJordan K. Hubbard */ 11635b81b6b3SRodney W. Grimes 1164f5f7ba03SJordan K. Hubbard int 1165b39c878eSAndrey A. Chernov fdioctl (dev, cmd, addr, flag, p) 1166f5f7ba03SJordan K. Hubbard dev_t dev; 1167f5f7ba03SJordan K. Hubbard int cmd; 1168f5f7ba03SJordan K. Hubbard caddr_t addr; 1169f5f7ba03SJordan K. Hubbard int flag; 1170b39c878eSAndrey A. Chernov struct proc *p; 1171f5f7ba03SJordan K. Hubbard { 1172f5f7ba03SJordan K. Hubbard struct fd_type *fdt; 1173f5f7ba03SJordan K. Hubbard struct disklabel *dl; 1174f5f7ba03SJordan K. Hubbard char buffer[DEV_BSIZE]; 1175f5f7ba03SJordan K. Hubbard int error; 1176f5f7ba03SJordan K. Hubbard 1177b99f0a4aSAndrew Moore #if NFT > 0 1178a60eff27SNate Williams int type = FDTYPE(minor(dev)); 1179a60eff27SNate Williams 1180a60eff27SNate Williams /* check for a tape ioctl */ 1181a60eff27SNate Williams if (type & F_TAPE_TYPE) 1182b99f0a4aSAndrew Moore return ftioctl(dev, cmd, addr, flag, p); 1183b99f0a4aSAndrew Moore #endif 1184b99f0a4aSAndrew Moore 1185f5f7ba03SJordan K. Hubbard error = 0; 1186f5f7ba03SJordan K. Hubbard 1187f5f7ba03SJordan K. Hubbard switch (cmd) 1188f5f7ba03SJordan K. Hubbard { 1189f5f7ba03SJordan K. Hubbard case DIOCGDINFO: 1190f5f7ba03SJordan K. Hubbard bzero(buffer, sizeof (buffer)); 1191f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)buffer; 1192f5f7ba03SJordan K. Hubbard dl->d_secsize = FDBLK; 119392ed385aSRodney W. Grimes fdt = fd_data[FDUNIT(minor(dev))].ft; 1194f5f7ba03SJordan K. Hubbard dl->d_secpercyl = fdt->size / fdt->tracks; 1195f5f7ba03SJordan K. Hubbard dl->d_type = DTYPE_FLOPPY; 1196f5f7ba03SJordan K. Hubbard 1197f5f7ba03SJordan K. Hubbard if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) 1198f5f7ba03SJordan K. Hubbard error = 0; 1199f5f7ba03SJordan K. Hubbard else 1200f5f7ba03SJordan K. Hubbard error = EINVAL; 1201f5f7ba03SJordan K. Hubbard 1202f5f7ba03SJordan K. Hubbard *(struct disklabel *)addr = *dl; 1203f5f7ba03SJordan K. Hubbard break; 1204f5f7ba03SJordan K. Hubbard 1205f5f7ba03SJordan K. Hubbard case DIOCSDINFO: 1206f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1207f5f7ba03SJordan K. Hubbard error = EBADF; 1208f5f7ba03SJordan K. Hubbard break; 1209f5f7ba03SJordan K. Hubbard 1210f5f7ba03SJordan K. Hubbard case DIOCWLABEL: 1211f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1212f5f7ba03SJordan K. Hubbard error = EBADF; 1213f5f7ba03SJordan K. Hubbard break; 1214f5f7ba03SJordan K. Hubbard 1215f5f7ba03SJordan K. Hubbard case DIOCWDINFO: 1216f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1217f5f7ba03SJordan K. Hubbard { 1218f5f7ba03SJordan K. Hubbard error = EBADF; 1219f5f7ba03SJordan K. Hubbard break; 1220f5f7ba03SJordan K. Hubbard } 1221f5f7ba03SJordan K. Hubbard 1222f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)addr; 1223f5f7ba03SJordan K. Hubbard 1224b39c878eSAndrey A. Chernov if (error = setdisklabel ((struct disklabel *)buffer, 1225b39c878eSAndrey A. Chernov dl, 0, NULL)) 1226f5f7ba03SJordan K. Hubbard break; 1227f5f7ba03SJordan K. Hubbard 1228b39c878eSAndrey A. Chernov error = writedisklabel(dev, fdstrategy, 1229b39c878eSAndrey A. Chernov (struct disklabel *)buffer, NULL); 1230b39c878eSAndrey A. Chernov break; 1231b39c878eSAndrey A. Chernov 1232b39c878eSAndrey A. Chernov case FD_FORM: 1233b39c878eSAndrey A. Chernov if((flag & FWRITE) == 0) 1234b39c878eSAndrey A. Chernov error = EBADF; /* must be opened for writing */ 1235b39c878eSAndrey A. Chernov else if(((struct fd_formb *)addr)->format_version != 1236b39c878eSAndrey A. Chernov FD_FORMAT_VERSION) 1237b39c878eSAndrey A. Chernov error = EINVAL; /* wrong version of formatting prog */ 1238b39c878eSAndrey A. Chernov else 1239b39c878eSAndrey A. Chernov error = fdformat(dev, (struct fd_formb *)addr, p); 1240b39c878eSAndrey A. Chernov break; 1241b39c878eSAndrey A. Chernov 1242b39c878eSAndrey A. Chernov case FD_GTYPE: /* get drive type */ 1243b39c878eSAndrey A. Chernov *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft; 1244f5f7ba03SJordan K. Hubbard break; 1245f5f7ba03SJordan K. Hubbard 1246f5f7ba03SJordan K. Hubbard default: 1247f5f7ba03SJordan K. Hubbard error = EINVAL; 1248f5f7ba03SJordan K. Hubbard break; 1249f5f7ba03SJordan K. Hubbard } 1250f5f7ba03SJordan K. Hubbard return (error); 1251f5f7ba03SJordan K. Hubbard } 1252f5f7ba03SJordan K. Hubbard 1253f5f7ba03SJordan K. Hubbard #endif 1254