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 38b99f0a4aSAndrew Moore * $from: fd.c,v 1.18 1993/12/21 05:09:21 ache 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" 665b81b6b3SRodney W. Grimes #include "i386/isa/icu.h" 675b81b6b3SRodney W. Grimes #include "i386/isa/rtc.h" 685b81b6b3SRodney W. Grimes 69b99f0a4aSAndrew Moore #if NFT > 0 70b99f0a4aSAndrew Moore extern int ftopen(), ftintr(), ftattach(), ftclose(), ftioctl(); 71b99f0a4aSAndrew Moore #endif 725b81b6b3SRodney W. Grimes 735b81b6b3SRodney W. Grimes #define b_cylin b_resid 745b81b6b3SRodney W. Grimes #define FDBLK 512 755b81b6b3SRodney W. Grimes 76b39c878eSAndrey A. Chernov /* misuse a flag to identify format operation */ 77b39c878eSAndrey A. Chernov #define B_FORMAT B_XXX 785b81b6b3SRodney W. Grimes 79b39c878eSAndrey A. Chernov #define NUMTYPES 14 80b39c878eSAndrey A. Chernov #define NUMDENS (NUMTYPES - 6) 817ca0641bSAndrey A. Chernov 82b99f0a4aSAndrew Moore /* This defines (-1) must match index for fd_types */ 83b99f0a4aSAndrew Moore #define F_TAPE_TYPE 0x020 /* bit for fd_types to indicate tape */ 84b99f0a4aSAndrew Moore #define NO_TYPE 0 /* must match NO_TYPE in ft.c */ 85b99f0a4aSAndrew Moore #define FD_1720 1 86b99f0a4aSAndrew Moore #define FD_1480 2 87b99f0a4aSAndrew Moore #define FD_1440 3 88b99f0a4aSAndrew Moore #define FD_1200 4 89b99f0a4aSAndrew Moore #define FD_820 5 90b99f0a4aSAndrew Moore #define FD_800 6 91b99f0a4aSAndrew Moore #define FD_720 7 92b99f0a4aSAndrew Moore #define FD_360 8 93ed2fa05eSAndrey A. Chernov 94b99f0a4aSAndrew Moore #define FD_1480in5_25 9 95b99f0a4aSAndrew Moore #define FD_1440in5_25 10 96b99f0a4aSAndrew Moore #define FD_820in5_25 11 97b99f0a4aSAndrew Moore #define FD_800in5_25 12 98b99f0a4aSAndrew Moore #define FD_720in5_25 13 99b99f0a4aSAndrew Moore #define FD_360in5_25 14 100b99f0a4aSAndrew Moore 1017ca0641bSAndrey A. Chernov 1025b81b6b3SRodney W. Grimes struct fd_type fd_types[NUMTYPES] = 1035b81b6b3SRodney W. Grimes { 104126518a1SAndrey A. Chernov { 21,2,0xFF,0x04,82,3444,1,FDC_500KBPS,2,0x0C,2 }, /* 1.72M in HD 3.5in */ 105126518a1SAndrey A. Chernov { 18,2,0xFF,0x1B,82,2952,1,FDC_500KBPS,2,0x6C,1 }, /* 1.48M in HD 3.5in */ 106126518a1SAndrey A. Chernov { 18,2,0xFF,0x1B,80,2880,1,FDC_500KBPS,2,0x6C,1 }, /* 1.44M in HD 3.5in */ 107126518a1SAndrey A. Chernov { 15,2,0xFF,0x1B,80,2400,1,FDC_500KBPS,2,0x54,1 }, /* 1.2M in HD 5.25/3.5 */ 108126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,82,1640,1,FDC_250KBPS,2,0x2E,1 }, /* 820K in HD 3.5in */ 109126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,80,1600,1,FDC_250KBPS,2,0x2E,1 }, /* 800K in HD 3.5in */ 110126518a1SAndrey A. Chernov { 9,2,0xFF,0x20,80,1440,1,FDC_250KBPS,2,0x50,1 }, /* 720K in HD 3.5in */ 111126518a1SAndrey A. Chernov { 9,2,0xFF,0x2A,40, 720,1,FDC_300KBPS,2,0x50,1 }, /* 360K in DD 5.25in */ 112ed2fa05eSAndrey A. Chernov 113126518a1SAndrey A. Chernov { 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,0x02,2 }, /* 1.48M in HD 5.25in */ 114126518a1SAndrey A. Chernov { 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,0x02,2 }, /* 1.44M in HD 5.25in */ 115126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,82,1640,1,FDC_300KBPS,2,0x2E,1 }, /* 820K in HD 5.25in */ 116126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,80,1600,1,FDC_300KBPS,2,0x2E,1 }, /* 800K in HD 5.25in */ 117126518a1SAndrey A. Chernov { 9,2,0xFF,0x20,80,1440,1,FDC_300KBPS,2,0x50,1 }, /* 720K in HD 5.25in */ 118126518a1SAndrey A. Chernov { 9,2,0xFF,0x23,40, 720,2,FDC_300KBPS,2,0x50,1 }, /* 360K in HD 5.25in */ 1195b81b6b3SRodney W. Grimes }; 1205b81b6b3SRodney W. Grimes 121b99f0a4aSAndrew Moore #define DRVS_PER_CTLR 2 /* 2 floppies */ 1225b81b6b3SRodney W. Grimes /***********************************************************************\ 1235b81b6b3SRodney W. Grimes * Per controller structure. * 1245b81b6b3SRodney W. Grimes \***********************************************************************/ 125b99f0a4aSAndrew Moore struct fdc_data fdc_data[NFDC]; 1265b81b6b3SRodney W. Grimes 1275b81b6b3SRodney W. Grimes /***********************************************************************\ 1285b81b6b3SRodney W. Grimes * Per drive structure. * 129b99f0a4aSAndrew Moore * N per controller (DRVS_PER_CTLR) * 1305b81b6b3SRodney W. Grimes \***********************************************************************/ 1315b81b6b3SRodney W. Grimes struct fd_data { 132b99f0a4aSAndrew Moore struct fdc_data *fdc; /* pointer to controller structure */ 1335b81b6b3SRodney W. Grimes int fdsu; /* this units number on this controller */ 1345b81b6b3SRodney W. Grimes int type; /* Drive type (HD, DD */ 1355b81b6b3SRodney W. Grimes struct fd_type *ft; /* pointer to the type descriptor */ 1365b81b6b3SRodney W. Grimes int flags; 1375b81b6b3SRodney W. Grimes #define FD_OPEN 0x01 /* it's open */ 1385b81b6b3SRodney W. Grimes #define FD_ACTIVE 0x02 /* it's active */ 1395b81b6b3SRodney W. Grimes #define FD_MOTOR 0x04 /* motor should be on */ 1405b81b6b3SRodney W. Grimes #define FD_MOTOR_WAIT 0x08 /* motor coming up */ 1415b81b6b3SRodney W. Grimes int skip; 1425b81b6b3SRodney W. Grimes int hddrv; 1435b81b6b3SRodney W. Grimes int track; /* where we think the head is */ 1445b81b6b3SRodney W. Grimes } fd_data[NFD]; 1455b81b6b3SRodney W. Grimes 1465b81b6b3SRodney W. Grimes /***********************************************************************\ 1475b81b6b3SRodney W. Grimes * Throughout this file the following conventions will be used: * 1485b81b6b3SRodney W. Grimes * fd is a pointer to the fd_data struct for the drive in question * 1495b81b6b3SRodney W. Grimes * fdc is a pointer to the fdc_data struct for the controller * 1505b81b6b3SRodney W. Grimes * fdu is the floppy drive unit number * 1515b81b6b3SRodney W. Grimes * fdcu is the floppy controller unit number * 1525b81b6b3SRodney W. Grimes * fdsu is the floppy drive unit number on that controller. (sub-unit) * 1535b81b6b3SRodney W. Grimes \***********************************************************************/ 154b99f0a4aSAndrew Moore 155b99f0a4aSAndrew Moore #define id_physid id_scsiid /* this biotab field doubles as a field */ 156b99f0a4aSAndrew Moore /* for the physical unit number on the controller */ 1575b81b6b3SRodney W. Grimes 158aaf08d94SGarrett Wollman static int retrier(fdcu_t); 159aaf08d94SGarrett Wollman 1605b81b6b3SRodney W. Grimes #define DEVIDLE 0 1615b81b6b3SRodney W. Grimes #define FINDWORK 1 1625b81b6b3SRodney W. Grimes #define DOSEEK 2 1635b81b6b3SRodney W. Grimes #define SEEKCOMPLETE 3 1645b81b6b3SRodney W. Grimes #define IOCOMPLETE 4 1655b81b6b3SRodney W. Grimes #define RECALCOMPLETE 5 1665b81b6b3SRodney W. Grimes #define STARTRECAL 6 1675b81b6b3SRodney W. Grimes #define RESETCTLR 7 1685b81b6b3SRodney W. Grimes #define SEEKWAIT 8 1695b81b6b3SRodney W. Grimes #define RECALWAIT 9 1705b81b6b3SRodney W. Grimes #define MOTORWAIT 10 1715b81b6b3SRodney W. Grimes #define IOTIMEDOUT 11 1725b81b6b3SRodney W. Grimes 1735b81b6b3SRodney W. Grimes #ifdef DEBUG 1745b81b6b3SRodney W. Grimes char *fdstates[] = 1755b81b6b3SRodney W. Grimes { 1765b81b6b3SRodney W. Grimes "DEVIDLE", 1775b81b6b3SRodney W. Grimes "FINDWORK", 1785b81b6b3SRodney W. Grimes "DOSEEK", 1795b81b6b3SRodney W. Grimes "SEEKCOMPLETE", 1805b81b6b3SRodney W. Grimes "IOCOMPLETE", 1815b81b6b3SRodney W. Grimes "RECALCOMPLETE", 1825b81b6b3SRodney W. Grimes "STARTRECAL", 1835b81b6b3SRodney W. Grimes "RESETCTLR", 1845b81b6b3SRodney W. Grimes "SEEKWAIT", 1855b81b6b3SRodney W. Grimes "RECALWAIT", 1865b81b6b3SRodney W. Grimes "MOTORWAIT", 1875b81b6b3SRodney W. Grimes "IOTIMEDOUT" 1885b81b6b3SRodney W. Grimes }; 1895b81b6b3SRodney W. Grimes 1905b81b6b3SRodney W. Grimes 1915b81b6b3SRodney W. Grimes int fd_debug = 1; 1925b81b6b3SRodney W. Grimes #define TRACE0(arg) if(fd_debug) printf(arg) 1935b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2) 194381fe1aaSGarrett Wollman #else /* DEBUG */ 1955b81b6b3SRodney W. Grimes #define TRACE0(arg) 1965b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) 197381fe1aaSGarrett Wollman #endif /* DEBUG */ 1985b81b6b3SRodney W. Grimes 199381fe1aaSGarrett Wollman static void fdstart(fdcu_t); 200381fe1aaSGarrett Wollman void fdintr(fdcu_t); 201381fe1aaSGarrett Wollman static void fd_turnoff(caddr_t, int); 2025b81b6b3SRodney W. Grimes 2035b81b6b3SRodney W. Grimes /****************************************************************************/ 2045b81b6b3SRodney W. Grimes /* autoconfiguration stuff */ 2055b81b6b3SRodney W. Grimes /****************************************************************************/ 206381fe1aaSGarrett Wollman static int fdprobe(struct isa_device *); 207381fe1aaSGarrett Wollman static int fdattach(struct isa_device *); 2085b81b6b3SRodney W. Grimes 209b99f0a4aSAndrew Moore struct isa_driver fdcdriver = { 210b99f0a4aSAndrew Moore fdprobe, fdattach, "fdc", 2115b81b6b3SRodney W. Grimes }; 2125b81b6b3SRodney W. Grimes 2135b81b6b3SRodney W. Grimes /* 2145b81b6b3SRodney W. Grimes * probe for existance of controller 2155b81b6b3SRodney W. Grimes */ 216381fe1aaSGarrett Wollman int 2175b81b6b3SRodney W. Grimes fdprobe(dev) 2185b81b6b3SRodney W. Grimes struct isa_device *dev; 2195b81b6b3SRodney W. Grimes { 2205b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2215b81b6b3SRodney W. Grimes if(fdc_data[fdcu].flags & FDC_ATTACHED) 2225b81b6b3SRodney W. Grimes { 2235b81b6b3SRodney W. Grimes printf("fdc: same unit (%d) used multiple times\n",fdcu); 2245b81b6b3SRodney W. Grimes return 0; 2255b81b6b3SRodney W. Grimes } 2265b81b6b3SRodney W. Grimes 2275b81b6b3SRodney W. Grimes fdc_data[fdcu].baseport = dev->id_iobase; 2285b81b6b3SRodney W. Grimes 22916111cedSAndrew Moore /* First - lets reset the floppy controller */ 23016111cedSAndrew Moore 23116111cedSAndrew Moore outb(dev->id_iobase+fdout,0); 23216111cedSAndrew Moore DELAY(100); 23316111cedSAndrew Moore outb(dev->id_iobase+fdout,FDO_FRST); 23416111cedSAndrew Moore 2355b81b6b3SRodney W. Grimes /* see if it can handle a command */ 2365b81b6b3SRodney W. Grimes if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0) 2375b81b6b3SRodney W. Grimes { 2385b81b6b3SRodney W. Grimes return(0); 2395b81b6b3SRodney W. Grimes } 2405b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 2415b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 2425b81b6b3SRodney W. Grimes return (IO_FDCSIZE); 2435b81b6b3SRodney W. Grimes } 2445b81b6b3SRodney W. Grimes 2455b81b6b3SRodney W. Grimes /* 2465b81b6b3SRodney W. Grimes * wire controller into system, look for floppy units 2475b81b6b3SRodney W. Grimes */ 248381fe1aaSGarrett Wollman int 2495b81b6b3SRodney W. Grimes fdattach(dev) 2505b81b6b3SRodney W. Grimes struct isa_device *dev; 2515b81b6b3SRodney W. Grimes { 2525b81b6b3SRodney W. Grimes unsigned fdt,st0, cyl; 2535b81b6b3SRodney W. Grimes int hdr; 2545b81b6b3SRodney W. Grimes fdu_t fdu; 2555b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2565b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 2575b81b6b3SRodney W. Grimes fd_p fd; 2585b81b6b3SRodney W. Grimes int fdsu; 259b99f0a4aSAndrew Moore struct isa_device *fdup; 2605b81b6b3SRodney W. Grimes 2615b81b6b3SRodney W. Grimes fdc->fdcu = fdcu; 2625b81b6b3SRodney W. Grimes fdc->flags |= FDC_ATTACHED; 2635b81b6b3SRodney W. Grimes fdc->dmachan = dev->id_drq; 2645b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 2655b81b6b3SRodney W. Grimes hdr = 0; 266b99f0a4aSAndrew Moore printf("fdc%d:", fdcu); 2675b81b6b3SRodney W. Grimes 2685b81b6b3SRodney W. Grimes /* check for each floppy drive */ 269b99f0a4aSAndrew Moore for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { 270b99f0a4aSAndrew Moore if (fdup->id_iobase != dev->id_iobase) 271b99f0a4aSAndrew Moore continue; 272b99f0a4aSAndrew Moore fdu = fdup->id_unit; 273b99f0a4aSAndrew Moore fd = &fd_data[fdu]; 274b99f0a4aSAndrew Moore if (fdu >= (NFD+NFT)) 275b99f0a4aSAndrew Moore continue; 276b99f0a4aSAndrew Moore fdsu = fdup->id_physid; 277b99f0a4aSAndrew Moore /* look up what bios thinks we have */ 278b99f0a4aSAndrew Moore switch (fdu) { 279b99f0a4aSAndrew Moore case 0: fdt = (rtcin(RTC_FDISKETTE) & 0xf0); 280b99f0a4aSAndrew Moore break; 281b99f0a4aSAndrew Moore case 1: fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); 282b99f0a4aSAndrew Moore break; 283b99f0a4aSAndrew Moore default: fdt = RTCFDT_NONE; 284b99f0a4aSAndrew Moore break; 285b99f0a4aSAndrew Moore } 2865b81b6b3SRodney W. Grimes /* is there a unit? */ 287b99f0a4aSAndrew Moore if ((fdt == RTCFDT_NONE) 288b99f0a4aSAndrew Moore #if NFT > 0 289b99f0a4aSAndrew Moore || (fdsu >= DRVS_PER_CTLR)) { 290b99f0a4aSAndrew Moore #else 291b99f0a4aSAndrew Moore ) { 292b99f0a4aSAndrew Moore #endif 293b99f0a4aSAndrew Moore #if NFT > 0 294b99f0a4aSAndrew Moore /* If BIOS says no floppy, or > 2nd device */ 295b99f0a4aSAndrew Moore /* Probe for and attach a floppy tape. */ 296b99f0a4aSAndrew Moore if (ftattach(dev, fdup)) 297b99f0a4aSAndrew Moore continue; 298b99f0a4aSAndrew Moore 299b99f0a4aSAndrew Moore #endif 300b99f0a4aSAndrew Moore fd->type = NO_TYPE; 3015b81b6b3SRodney W. Grimes continue; 302f5f7ba03SJordan K. Hubbard } 3035b81b6b3SRodney W. Grimes 3045b81b6b3SRodney W. Grimes #ifdef notyet 3055b81b6b3SRodney W. Grimes /* select it */ 3065b81b6b3SRodney W. Grimes fd_turnon1(fdu); 3075b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 3085b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 3095b81b6b3SRodney W. Grimes out_fdc(fdcu,fdsu); 3105b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 3115b81b6b3SRodney W. Grimes 3125b81b6b3SRodney W. Grimes /* anything responding */ 3135b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 3145b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 3155b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 3165b81b6b3SRodney W. Grimes if (st0 & 0xd0) 3175b81b6b3SRodney W. Grimes continue; 3185b81b6b3SRodney W. Grimes 3195b81b6b3SRodney W. Grimes #endif 320b99f0a4aSAndrew Moore fd->track = -2; 321b99f0a4aSAndrew Moore fd->fdc = fdc; 322b99f0a4aSAndrew Moore fd->fdsu = fdsu; 323b99f0a4aSAndrew Moore printf(" [%d: fd%d: ", fdsu, fdu); 3245b81b6b3SRodney W. Grimes 325b99f0a4aSAndrew Moore switch (fdt) { 3267ca0641bSAndrey A. Chernov case RTCFDT_12M: 327b99f0a4aSAndrew Moore printf("1.2MB 5.25in]"); 328b99f0a4aSAndrew Moore fd->type = FD_1200; 3297ca0641bSAndrey A. Chernov break; 3307ca0641bSAndrey A. Chernov case RTCFDT_144M: 331b99f0a4aSAndrew Moore printf("1.44MB 3.5in]"); 332b99f0a4aSAndrew Moore fd->type = FD_1440; 3337ca0641bSAndrey A. Chernov break; 3347ca0641bSAndrey A. Chernov case RTCFDT_360K: 335b99f0a4aSAndrew Moore printf("360KB 5.25in]"); 336b99f0a4aSAndrew Moore fd->type = FD_360; 3377ca0641bSAndrey A. Chernov break; 338ed2fa05eSAndrey A. Chernov case RTCFDT_720K: 339b99f0a4aSAndrew Moore printf("720KB 3.5in]"); 340b99f0a4aSAndrew Moore fd->type = FD_720; 341ed2fa05eSAndrey A. Chernov break; 3427ca0641bSAndrey A. Chernov default: 343b99f0a4aSAndrew Moore printf("unknown]"); 344b99f0a4aSAndrew Moore fd->type = NO_TYPE; 3457ca0641bSAndrey A. Chernov break; 3465b81b6b3SRodney W. Grimes } 3475b81b6b3SRodney W. Grimes 348381fe1aaSGarrett Wollman fd_turnoff((caddr_t)fdu, 0); 3495b81b6b3SRodney W. Grimes hdr = 1; 3505b81b6b3SRodney W. Grimes } 351b99f0a4aSAndrew Moore printf("\n"); 3525b81b6b3SRodney W. Grimes 3535b81b6b3SRodney W. Grimes /* Set transfer to 500kbps */ 3545b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,0); /*XXX*/ 355381fe1aaSGarrett Wollman return 1; 3565b81b6b3SRodney W. Grimes } 3575b81b6b3SRodney W. Grimes 3585b81b6b3SRodney W. Grimes int 3595b81b6b3SRodney W. Grimes fdsize(dev) 3605b81b6b3SRodney W. Grimes dev_t dev; 3615b81b6b3SRodney W. Grimes { 3625b81b6b3SRodney W. Grimes return(0); 3635b81b6b3SRodney W. Grimes } 3645b81b6b3SRodney W. Grimes 3655b81b6b3SRodney W. Grimes /****************************************************************************/ 3665b81b6b3SRodney W. Grimes /* fdstrategy */ 3675b81b6b3SRodney W. Grimes /****************************************************************************/ 368381fe1aaSGarrett Wollman void fdstrategy(struct buf *bp) 3695b81b6b3SRodney W. Grimes { 3705b81b6b3SRodney W. Grimes register struct buf *dp,*dp0,*dp1; 3715b81b6b3SRodney W. Grimes long nblocks,blknum; 3725b81b6b3SRodney W. Grimes int s; 3735b81b6b3SRodney W. Grimes fdcu_t fdcu; 3745b81b6b3SRodney W. Grimes fdu_t fdu; 3755b81b6b3SRodney W. Grimes fdc_p fdc; 3765b81b6b3SRodney W. Grimes fd_p fd; 3775b81b6b3SRodney W. Grimes 3785b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 3795b81b6b3SRodney W. Grimes fd = &fd_data[fdu]; 3805b81b6b3SRodney W. Grimes fdc = fd->fdc; 3815b81b6b3SRodney W. Grimes fdcu = fdc->fdcu; 3825b81b6b3SRodney W. Grimes 383b99f0a4aSAndrew Moore #if NFT > 0 384b99f0a4aSAndrew Moore /* check for controller already busy with tape */ 385b99f0a4aSAndrew Moore if (fdc->flags & FDC_TAPE_BUSY) { 386b99f0a4aSAndrew Moore bp->b_error = EBUSY; 387b99f0a4aSAndrew Moore bp->b_flags |= B_ERROR; 388b99f0a4aSAndrew Moore return; 389b99f0a4aSAndrew Moore } 390b99f0a4aSAndrew Moore #endif 391b99f0a4aSAndrew Moore if ((fdu >= (NFD+NFT)) || (bp->b_blkno < 0)) { 3925b81b6b3SRodney W. Grimes printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n", 3935b81b6b3SRodney W. Grimes fdu, bp->b_blkno, bp->b_bcount); 3945b81b6b3SRodney W. Grimes pg("fd:error in fdstrategy"); 3955b81b6b3SRodney W. Grimes bp->b_error = EINVAL; 3965b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 3975b81b6b3SRodney W. Grimes goto bad; 3985b81b6b3SRodney W. Grimes } 3995b81b6b3SRodney W. Grimes /* 4005b81b6b3SRodney W. Grimes * Set up block calculations. 4015b81b6b3SRodney W. Grimes */ 4025b81b6b3SRodney W. Grimes blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK; 4035b81b6b3SRodney W. Grimes nblocks = fd->ft->size; 4045b81b6b3SRodney W. Grimes if (blknum + (bp->b_bcount / FDBLK) > nblocks) { 4055b81b6b3SRodney W. Grimes if (blknum == nblocks) { 4065b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount; 4075b81b6b3SRodney W. Grimes } else { 4085b81b6b3SRodney W. Grimes bp->b_error = ENOSPC; 4095b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 4105b81b6b3SRodney W. Grimes } 4115b81b6b3SRodney W. Grimes goto bad; 4125b81b6b3SRodney W. Grimes } 4135b81b6b3SRodney W. Grimes bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads); 4145b81b6b3SRodney W. Grimes dp = &(fdc->head); 4155b81b6b3SRodney W. Grimes s = splbio(); 4165b81b6b3SRodney W. Grimes disksort(dp, bp); 417aaf08d94SGarrett Wollman untimeout(fd_turnoff, (caddr_t)fdu); /* a good idea */ 4185b81b6b3SRodney W. Grimes fdstart(fdcu); 4195b81b6b3SRodney W. Grimes splx(s); 4205b81b6b3SRodney W. Grimes return; 4215b81b6b3SRodney W. Grimes 4225b81b6b3SRodney W. Grimes bad: 4235b81b6b3SRodney W. Grimes biodone(bp); 424b39c878eSAndrey A. Chernov return; 4255b81b6b3SRodney W. Grimes } 4265b81b6b3SRodney W. Grimes 4275b81b6b3SRodney W. Grimes /****************************************************************************/ 4285b81b6b3SRodney W. Grimes /* motor control stuff */ 4295b81b6b3SRodney W. Grimes /* remember to not deselect the drive we're working on */ 4305b81b6b3SRodney W. Grimes /****************************************************************************/ 431381fe1aaSGarrett Wollman void 432f5f7ba03SJordan K. Hubbard set_motor(fdcu, fdu, reset) 433f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 434f5f7ba03SJordan K. Hubbard fdu_t fdu; 435f5f7ba03SJordan K. Hubbard int reset; 4365b81b6b3SRodney W. Grimes { 4375b81b6b3SRodney W. Grimes int m0,m1; 4385b81b6b3SRodney W. Grimes int selunit; 4395b81b6b3SRodney W. Grimes fd_p fd; 4405b81b6b3SRodney W. Grimes if(fd = fdc_data[fdcu].fd)/* yes an assign! */ 4415b81b6b3SRodney W. Grimes { 4425b81b6b3SRodney W. Grimes selunit = fd->fdsu; 4435b81b6b3SRodney W. Grimes } 4445b81b6b3SRodney W. Grimes else 4455b81b6b3SRodney W. Grimes { 4465b81b6b3SRodney W. Grimes selunit = 0; 4475b81b6b3SRodney W. Grimes } 4485b81b6b3SRodney W. Grimes m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR; 4495b81b6b3SRodney W. Grimes m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR; 4505b81b6b3SRodney W. Grimes outb(fdc_data[fdcu].baseport+fdout, 4515b81b6b3SRodney W. Grimes selunit 4525b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4535b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4545b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0)); 4555b81b6b3SRodney W. Grimes TRACE1("[0x%x->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 } 4615b81b6b3SRodney W. Grimes 462381fe1aaSGarrett Wollman static void 463381fe1aaSGarrett Wollman fd_turnoff(caddr_t arg1, int arg2) 4645b81b6b3SRodney W. Grimes { 465381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 466f5f7ba03SJordan K. Hubbard int s; 467f5f7ba03SJordan K. Hubbard 4685b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 469f5f7ba03SJordan K. Hubbard s = splbio(); 4705b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR; 4715b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 472f5f7ba03SJordan K. Hubbard splx(s); 4735b81b6b3SRodney W. Grimes } 4745b81b6b3SRodney W. Grimes 475381fe1aaSGarrett Wollman void 476381fe1aaSGarrett Wollman fd_motor_on(caddr_t arg1, int arg2) 4775b81b6b3SRodney W. Grimes { 478381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 479f5f7ba03SJordan K. Hubbard int s; 480f5f7ba03SJordan K. Hubbard 4815b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 482f5f7ba03SJordan K. Hubbard s = splbio(); 4835b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR_WAIT; 4845b81b6b3SRodney W. Grimes if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) 4855b81b6b3SRodney W. Grimes { 486f5f7ba03SJordan K. Hubbard fdintr(fd->fdc->fdcu); 4875b81b6b3SRodney W. Grimes } 488f5f7ba03SJordan K. Hubbard splx(s); 4895b81b6b3SRodney W. Grimes } 4905b81b6b3SRodney W. Grimes 491381fe1aaSGarrett Wollman static void fd_turnon1(fdu_t); 492381fe1aaSGarrett Wollman 493381fe1aaSGarrett Wollman void 494f5f7ba03SJordan K. Hubbard fd_turnon(fdu) 495f5f7ba03SJordan K. Hubbard fdu_t fdu; 4965b81b6b3SRodney W. Grimes { 4975b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 4985b81b6b3SRodney W. Grimes if(!(fd->flags & FD_MOTOR)) 4995b81b6b3SRodney W. Grimes { 5005b81b6b3SRodney W. Grimes fd_turnon1(fdu); 5015b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR_WAIT; 502381fe1aaSGarrett Wollman timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ 5035b81b6b3SRodney W. Grimes } 5045b81b6b3SRodney W. Grimes } 5055b81b6b3SRodney W. Grimes 506381fe1aaSGarrett Wollman static void 507381fe1aaSGarrett Wollman fd_turnon1(fdu_t fdu) 5085b81b6b3SRodney W. Grimes { 5095b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 5105b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR; 5115b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 5125b81b6b3SRodney W. Grimes } 5135b81b6b3SRodney W. Grimes 5145b81b6b3SRodney W. Grimes /****************************************************************************/ 5155b81b6b3SRodney W. Grimes /* fdc in/out */ 5165b81b6b3SRodney W. Grimes /****************************************************************************/ 5175b81b6b3SRodney W. Grimes int 518f5f7ba03SJordan K. Hubbard in_fdc(fdcu) 519f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 5205b81b6b3SRodney W. Grimes { 5215b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5225b81b6b3SRodney W. Grimes int i, j = 100000; 5235b81b6b3SRodney W. Grimes while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM)) 5245b81b6b3SRodney W. Grimes != (NE7_DIO|NE7_RQM) && j-- > 0) 5255b81b6b3SRodney W. Grimes if (i == NE7_RQM) return -1; 5265b81b6b3SRodney W. Grimes if (j <= 0) 5275b81b6b3SRodney W. Grimes return(-1); 5285b81b6b3SRodney W. Grimes #ifdef DEBUG 5295b81b6b3SRodney W. Grimes i = inb(baseport+fddata); 5305b81b6b3SRodney W. Grimes TRACE1("[fddata->0x%x]",(unsigned char)i); 5315b81b6b3SRodney W. Grimes return(i); 5325b81b6b3SRodney W. Grimes #else 5335b81b6b3SRodney W. Grimes return inb(baseport+fddata); 5345b81b6b3SRodney W. Grimes #endif 5355b81b6b3SRodney W. Grimes } 5365b81b6b3SRodney W. Grimes 537381fe1aaSGarrett Wollman int 538f5f7ba03SJordan K. Hubbard out_fdc(fdcu, x) 539f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 540f5f7ba03SJordan K. Hubbard int x; 5415b81b6b3SRodney W. Grimes { 5425b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5433b3837dbSRodney W. Grimes int i; 5445b81b6b3SRodney W. Grimes 5453b3837dbSRodney W. Grimes /* Check that the direction bit is set */ 5463b3837dbSRodney W. Grimes i = 100000; 5475b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0); 5483b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5493b3837dbSRodney W. Grimes 5503b3837dbSRodney W. Grimes /* Check that the floppy controller is ready for a command */ 5513b3837dbSRodney W. Grimes i = 100000; 5525b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0); 5533b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5543b3837dbSRodney W. Grimes 5553b3837dbSRodney W. Grimes /* Send the command and return */ 5565b81b6b3SRodney W. Grimes outb(baseport+fddata,x); 5575b81b6b3SRodney W. Grimes TRACE1("[0x%x->fddata]",x); 5585b81b6b3SRodney W. Grimes return (0); 5595b81b6b3SRodney W. Grimes } 5605b81b6b3SRodney W. Grimes 5615b81b6b3SRodney W. Grimes /****************************************************************************/ 5625b81b6b3SRodney W. Grimes /* fdopen/fdclose */ 5635b81b6b3SRodney W. Grimes /****************************************************************************/ 564381fe1aaSGarrett Wollman int 5655b81b6b3SRodney W. Grimes Fdopen(dev, flags) 5665b81b6b3SRodney W. Grimes dev_t dev; 5675b81b6b3SRodney W. Grimes int flags; 5685b81b6b3SRodney W. Grimes { 5695b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 57020a29168SAndrey A. Chernov int type = FDTYPE(minor(dev)); 571b99f0a4aSAndrew Moore fdc_p fdc; 5725b81b6b3SRodney W. Grimes 573b99f0a4aSAndrew Moore #if NFT > 0 574b99f0a4aSAndrew Moore /* check for a tape open */ 575b99f0a4aSAndrew Moore if (type & F_TAPE_TYPE) 576b99f0a4aSAndrew Moore return(ftopen(dev, flags)); 577b99f0a4aSAndrew Moore #endif 5785b81b6b3SRodney W. Grimes /* check bounds */ 579b99f0a4aSAndrew Moore if (fdu >= NFD) 580b99f0a4aSAndrew Moore return(ENXIO); 581b99f0a4aSAndrew Moore fdc = fd_data[fdu].fdc; 582b99f0a4aSAndrew Moore if ((fdc == NULL) || (fd_data[fdu].type == NO_TYPE)) 583b99f0a4aSAndrew Moore return(ENXIO); 584b99f0a4aSAndrew Moore if (type > NUMDENS) 585b99f0a4aSAndrew Moore return(ENXIO); 5867ca0641bSAndrey A. Chernov if (type == 0) 5877ca0641bSAndrey A. Chernov type = fd_data[fdu].type; 5887ca0641bSAndrey A. Chernov else { 5897ca0641bSAndrey A. Chernov if (type != fd_data[fdu].type) { 590fa4700b4SAndrey A. Chernov switch (fd_data[fdu].type) { 5917ca0641bSAndrey A. Chernov case FD_360: 5927ca0641bSAndrey A. Chernov return(ENXIO); 593ed2fa05eSAndrey A. Chernov case FD_720: 594b39c878eSAndrey A. Chernov if ( type != FD_820 595b39c878eSAndrey A. Chernov && type != FD_800 596ed2fa05eSAndrey A. Chernov ) 597ed2fa05eSAndrey A. Chernov return(ENXIO); 598ed2fa05eSAndrey A. Chernov break; 5997ca0641bSAndrey A. Chernov case FD_1200: 600b39c878eSAndrey A. Chernov switch (type) { 601b39c878eSAndrey A. Chernov case FD_1480: 602b39c878eSAndrey A. Chernov type = FD_1480in5_25; 603fa4700b4SAndrey A. Chernov break; 6047ca0641bSAndrey A. Chernov case FD_1440: 605b39c878eSAndrey A. Chernov type = FD_1440in5_25; 606b39c878eSAndrey A. Chernov break; 607b39c878eSAndrey A. Chernov case FD_820: 608b39c878eSAndrey A. Chernov type = FD_820in5_25; 609b39c878eSAndrey A. Chernov break; 610b39c878eSAndrey A. Chernov case FD_800: 611b39c878eSAndrey A. Chernov type = FD_800in5_25; 612b39c878eSAndrey A. Chernov break; 613b39c878eSAndrey A. Chernov case FD_720: 614b39c878eSAndrey A. Chernov type = FD_720in5_25; 615b39c878eSAndrey A. Chernov break; 616b39c878eSAndrey A. Chernov case FD_360: 617b39c878eSAndrey A. Chernov type = FD_360in5_25; 618b39c878eSAndrey A. Chernov break; 619b39c878eSAndrey A. Chernov default: 620b39c878eSAndrey A. Chernov return(ENXIO); 621b39c878eSAndrey A. Chernov } 622b39c878eSAndrey A. Chernov break; 623b39c878eSAndrey A. Chernov case FD_1440: 624b39c878eSAndrey A. Chernov if ( type != FD_1720 625b39c878eSAndrey A. Chernov && type != FD_1480 626ed2fa05eSAndrey A. Chernov && type != FD_1200 627b39c878eSAndrey A. Chernov && type != FD_820 628b39c878eSAndrey A. Chernov && type != FD_800 629b39c878eSAndrey A. Chernov && type != FD_720 6307ca0641bSAndrey A. Chernov ) 631dffff499SAndrey A. Chernov return(ENXIO); 632fa4700b4SAndrey A. Chernov break; 6337ca0641bSAndrey A. Chernov } 6347ca0641bSAndrey A. Chernov } 635fa4700b4SAndrey A. Chernov } 636b99f0a4aSAndrew Moore fd_data[fdu].ft = fd_types + type - 1; 6375b81b6b3SRodney W. Grimes fd_data[fdu].flags |= FD_OPEN; 6385b81b6b3SRodney W. Grimes 6395b81b6b3SRodney W. Grimes return 0; 6405b81b6b3SRodney W. Grimes } 6415b81b6b3SRodney W. Grimes 642381fe1aaSGarrett Wollman int 6435b81b6b3SRodney W. Grimes fdclose(dev, flags) 6445b81b6b3SRodney W. Grimes dev_t dev; 645381fe1aaSGarrett Wollman int flags; 6465b81b6b3SRodney W. Grimes { 6475b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 648b99f0a4aSAndrew Moore int type = FDTYPE(minor(dev)); 649b99f0a4aSAndrew Moore 650b99f0a4aSAndrew Moore #if NFT > 0 651b99f0a4aSAndrew Moore if (type & F_TAPE_TYPE) 652b99f0a4aSAndrew Moore return ftclose(0); 653b99f0a4aSAndrew Moore #endif 6545b81b6b3SRodney W. Grimes fd_data[fdu].flags &= ~FD_OPEN; 6555b81b6b3SRodney W. Grimes return(0); 6565b81b6b3SRodney W. Grimes } 6575b81b6b3SRodney W. Grimes 6585b81b6b3SRodney W. Grimes 6595b81b6b3SRodney W. Grimes /***************************************************************\ 6605b81b6b3SRodney W. Grimes * fdstart * 6615b81b6b3SRodney W. Grimes * We have just queued something.. if the controller is not busy * 6625b81b6b3SRodney W. Grimes * then simulate the case where it has just finished a command * 6635b81b6b3SRodney W. Grimes * So that it (the interrupt routine) looks on the queue for more* 6645b81b6b3SRodney W. Grimes * work to do and picks up what we just added. * 6655b81b6b3SRodney W. Grimes * If the controller is already busy, we need do nothing, as it * 6665b81b6b3SRodney W. Grimes * will pick up our work when the present work completes * 6675b81b6b3SRodney W. Grimes \***************************************************************/ 668381fe1aaSGarrett Wollman static void 669f5f7ba03SJordan K. Hubbard fdstart(fdcu) 670f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 6715b81b6b3SRodney W. Grimes { 6725b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 6735b81b6b3SRodney W. Grimes int s; 6745b81b6b3SRodney W. Grimes fdu_t fdu; 6755b81b6b3SRodney W. Grimes 6765b81b6b3SRodney W. Grimes s = splbio(); 6775b81b6b3SRodney W. Grimes if(fdc_data[fdcu].state == DEVIDLE) 6785b81b6b3SRodney W. Grimes { 6795b81b6b3SRodney W. Grimes fdintr(fdcu); 6805b81b6b3SRodney W. Grimes } 6815b81b6b3SRodney W. Grimes splx(s); 6825b81b6b3SRodney W. Grimes } 6835b81b6b3SRodney W. Grimes 684381fe1aaSGarrett Wollman static void 685381fe1aaSGarrett Wollman fd_timeout(caddr_t arg1, int arg2) 6865b81b6b3SRodney W. Grimes { 687381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 6885b81b6b3SRodney W. Grimes fdu_t fdu = fdc_data[fdcu].fdu; 6895b81b6b3SRodney W. Grimes int st0, st3, cyl; 6905b81b6b3SRodney W. Grimes struct buf *dp,*bp; 691f5f7ba03SJordan K. Hubbard int s; 6925b81b6b3SRodney W. Grimes 6935b81b6b3SRodney W. Grimes dp = &fdc_data[fdcu].head; 694f5f7ba03SJordan K. Hubbard s = splbio(); 6955b81b6b3SRodney W. Grimes bp = dp->b_actf; 6965b81b6b3SRodney W. Grimes 6975b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSED); 6985b81b6b3SRodney W. Grimes out_fdc(fdcu,fd_data[fdu].hddrv); 6995b81b6b3SRodney W. Grimes st3 = in_fdc(fdcu); 7005b81b6b3SRodney W. Grimes 7015b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 7025b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 7035b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 7045b81b6b3SRodney W. Grimes printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n", 7055b81b6b3SRodney W. Grimes fdu, 7065b81b6b3SRodney W. Grimes st0, 7075b81b6b3SRodney W. Grimes NE7_ST0BITS, 7085b81b6b3SRodney W. Grimes cyl, 7095b81b6b3SRodney W. Grimes st3, 7105b81b6b3SRodney W. Grimes NE7_ST3BITS); 7115b81b6b3SRodney W. Grimes 7125b81b6b3SRodney W. Grimes if (bp) 7135b81b6b3SRodney W. Grimes { 7145b81b6b3SRodney W. Grimes retrier(fdcu); 7155b81b6b3SRodney W. Grimes fdc_data[fdcu].status[0] = 0xc0; 7165b81b6b3SRodney W. Grimes fdc_data[fdcu].state = IOTIMEDOUT; 7175b81b6b3SRodney W. Grimes if( fdc_data[fdcu].retry < 6) 7185b81b6b3SRodney W. Grimes fdc_data[fdcu].retry = 6; 7195b81b6b3SRodney W. Grimes } 7205b81b6b3SRodney W. Grimes else 7215b81b6b3SRodney W. Grimes { 7225b81b6b3SRodney W. Grimes fdc_data[fdcu].fd = (fd_p) 0; 7235b81b6b3SRodney W. Grimes fdc_data[fdcu].fdu = -1; 7245b81b6b3SRodney W. Grimes fdc_data[fdcu].state = DEVIDLE; 7255b81b6b3SRodney W. Grimes } 726f5f7ba03SJordan K. Hubbard fdintr(fdcu); 727f5f7ba03SJordan K. Hubbard splx(s); 7285b81b6b3SRodney W. Grimes } 7295b81b6b3SRodney W. Grimes 7305b81b6b3SRodney W. Grimes /* just ensure it has the right spl */ 731381fe1aaSGarrett Wollman static void 732381fe1aaSGarrett Wollman fd_pseudointr(caddr_t arg1, int arg2) 7335b81b6b3SRodney W. Grimes { 734381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 7355b81b6b3SRodney W. Grimes int s; 7365b81b6b3SRodney W. Grimes s = splbio(); 7375b81b6b3SRodney W. Grimes fdintr(fdcu); 7385b81b6b3SRodney W. Grimes splx(s); 7395b81b6b3SRodney W. Grimes } 7405b81b6b3SRodney W. Grimes 7415b81b6b3SRodney W. Grimes /***********************************************************************\ 7425b81b6b3SRodney W. Grimes * fdintr * 7435b81b6b3SRodney W. Grimes * keep calling the state machine until it returns a 0 * 7445b81b6b3SRodney W. Grimes * ALWAYS called at SPLBIO * 7455b81b6b3SRodney W. Grimes \***********************************************************************/ 746381fe1aaSGarrett Wollman void 747381fe1aaSGarrett Wollman fdintr(fdcu_t fdcu) 7485b81b6b3SRodney W. Grimes { 7495b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 750b99f0a4aSAndrew Moore #if NFT > 0 751b99f0a4aSAndrew Moore fdu_t fdu = fdc->fdu; 752b99f0a4aSAndrew Moore 753b99f0a4aSAndrew Moore if (fdc->flags & FDC_TAPE_BUSY) 754b99f0a4aSAndrew Moore (ftintr(fdu)); 755b99f0a4aSAndrew Moore else 756b99f0a4aSAndrew Moore #endif 757381fe1aaSGarrett Wollman while(fdstate(fdcu, fdc)) 758381fe1aaSGarrett Wollman ; 7595b81b6b3SRodney W. Grimes } 7605b81b6b3SRodney W. Grimes 7615b81b6b3SRodney W. Grimes /***********************************************************************\ 7625b81b6b3SRodney W. Grimes * The controller state machine. * 7635b81b6b3SRodney W. Grimes * if it returns a non zero value, it should be called again immediatly * 7645b81b6b3SRodney W. Grimes \***********************************************************************/ 765381fe1aaSGarrett Wollman int 766381fe1aaSGarrett Wollman fdstate(fdcu, fdc) 767f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 768f5f7ba03SJordan K. Hubbard fdc_p fdc; 7695b81b6b3SRodney W. Grimes { 770b39c878eSAndrey A. Chernov int read, format, head, trac, sec = 0, i = 0, s, sectrac, cyl, st0; 7715b81b6b3SRodney W. Grimes unsigned long blknum; 7725b81b6b3SRodney W. Grimes fdu_t fdu = fdc->fdu; 7735b81b6b3SRodney W. Grimes fd_p fd; 7745b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 775b39c878eSAndrey A. Chernov struct fd_formb *finfo = NULL; 7765b81b6b3SRodney W. Grimes 7775b81b6b3SRodney W. Grimes dp = &(fdc->head); 7785b81b6b3SRodney W. Grimes bp = dp->b_actf; 7795b81b6b3SRodney W. Grimes if(!bp) 7805b81b6b3SRodney W. Grimes { 7815b81b6b3SRodney W. Grimes /***********************************************\ 7825b81b6b3SRodney W. Grimes * nothing left for this controller to do * 7835b81b6b3SRodney W. Grimes * Force into the IDLE state, * 7845b81b6b3SRodney W. Grimes \***********************************************/ 7855b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 7865b81b6b3SRodney W. Grimes if(fdc->fd) 7875b81b6b3SRodney W. Grimes { 7885b81b6b3SRodney W. Grimes printf("unexpected valid fd pointer (fdu = %d)\n" 7895b81b6b3SRodney W. Grimes ,fdc->fdu); 7905b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 7915b81b6b3SRodney W. Grimes fdc->fdu = -1; 7925b81b6b3SRodney W. Grimes } 7935b81b6b3SRodney W. Grimes TRACE1("[fdc%d IDLE]",fdcu); 7945b81b6b3SRodney W. Grimes return(0); 7955b81b6b3SRodney W. Grimes } 7965b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 7975b81b6b3SRodney W. Grimes fd = fd_data + fdu; 7985b81b6b3SRodney W. Grimes if (fdc->fd && (fd != fdc->fd)) 7995b81b6b3SRodney W. Grimes { 8005b81b6b3SRodney W. Grimes printf("confused fd pointers\n"); 8015b81b6b3SRodney W. Grimes } 8025b81b6b3SRodney W. Grimes read = bp->b_flags & B_READ; 803b39c878eSAndrey A. Chernov format = bp->b_flags & B_FORMAT; 804b39c878eSAndrey A. Chernov if(format) 805b39c878eSAndrey A. Chernov finfo = (struct fd_formb *)bp->b_un.b_addr; 8065b81b6b3SRodney W. Grimes TRACE1("fd%d",fdu); 8075b81b6b3SRodney W. Grimes TRACE1("[%s]",fdstates[fdc->state]); 8085b81b6b3SRodney W. Grimes TRACE1("(0x%x)",fd->flags); 809aaf08d94SGarrett Wollman untimeout(fd_turnoff, (caddr_t)fdu); 810381fe1aaSGarrett Wollman timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); 8115b81b6b3SRodney W. Grimes switch (fdc->state) 8125b81b6b3SRodney W. Grimes { 8135b81b6b3SRodney W. Grimes case DEVIDLE: 8145b81b6b3SRodney W. Grimes case FINDWORK: /* we have found new work */ 8155b81b6b3SRodney W. Grimes fdc->retry = 0; 8165b81b6b3SRodney W. Grimes fd->skip = 0; 8175b81b6b3SRodney W. Grimes fdc->fd = fd; 8185b81b6b3SRodney W. Grimes fdc->fdu = fdu; 8195b81b6b3SRodney W. Grimes /*******************************************************\ 8205b81b6b3SRodney W. Grimes * If the next drive has a motor startup pending, then * 8215b81b6b3SRodney W. Grimes * it will start up in it's own good time * 8225b81b6b3SRodney W. Grimes \*******************************************************/ 8235b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 8245b81b6b3SRodney W. Grimes { 8255b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 8265b81b6b3SRodney W. Grimes return(0); /* come back later */ 8275b81b6b3SRodney W. Grimes } 8285b81b6b3SRodney W. Grimes /*******************************************************\ 8295b81b6b3SRodney W. Grimes * Maybe if it's not starting, it SHOULD be starting * 8305b81b6b3SRodney W. Grimes \*******************************************************/ 8315b81b6b3SRodney W. Grimes if (!(fd->flags & FD_MOTOR)) 8325b81b6b3SRodney W. Grimes { 8335b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 8345b81b6b3SRodney W. Grimes fd_turnon(fdu); 8355b81b6b3SRodney W. Grimes return(0); 8365b81b6b3SRodney W. Grimes } 8375b81b6b3SRodney W. Grimes else /* at least make sure we are selected */ 8385b81b6b3SRodney W. Grimes { 8395b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 8405b81b6b3SRodney W. Grimes } 8415b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 8425b81b6b3SRodney W. Grimes break; 8435b81b6b3SRodney W. Grimes case DOSEEK: 8445b81b6b3SRodney W. Grimes if (bp->b_cylin == fd->track) 8455b81b6b3SRodney W. Grimes { 8465b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8475b81b6b3SRodney W. Grimes break; 8485b81b6b3SRodney W. Grimes } 8495b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SEEK); /* Seek function */ 8505b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); /* Drive number */ 8515b81b6b3SRodney W. Grimes out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac); 8525b81b6b3SRodney W. Grimes fd->track = -2; 8535b81b6b3SRodney W. Grimes fdc->state = SEEKWAIT; 854381fe1aaSGarrett Wollman timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 8555b81b6b3SRodney W. Grimes return(0); /* will return later */ 8565b81b6b3SRodney W. Grimes case SEEKWAIT: 857aaf08d94SGarrett Wollman untimeout(fd_timeout, (caddr_t)fdcu); 8585b81b6b3SRodney W. Grimes /* allow heads to settle */ 859381fe1aaSGarrett Wollman timeout(fd_pseudointr, (caddr_t)fdcu, hz / 50); 8605b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8615b81b6b3SRodney W. Grimes return(0); /* will return later */ 8625b81b6b3SRodney W. Grimes break; 8635b81b6b3SRodney W. Grimes 8645b81b6b3SRodney W. Grimes case SEEKCOMPLETE : /* SEEK DONE, START DMA */ 8655b81b6b3SRodney W. Grimes /* Make sure seek really happened*/ 8665b81b6b3SRodney W. Grimes if(fd->track == -2) 8675b81b6b3SRodney W. Grimes { 8685b81b6b3SRodney W. Grimes int descyl = bp->b_cylin * fd->ft->steptrac; 8695b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 8705b81b6b3SRodney W. Grimes i = in_fdc(fdcu); 8715b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 8725b81b6b3SRodney W. Grimes if (cyl != descyl) 8735b81b6b3SRodney W. Grimes { 874b99f0a4aSAndrew Moore printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", 875b99f0a4aSAndrew Moore fdu, descyl, cyl, i, NE7_ST0BITS); 8765b81b6b3SRodney W. Grimes return(retrier(fdcu)); 8775b81b6b3SRodney W. Grimes } 8785b81b6b3SRodney W. Grimes } 8795b81b6b3SRodney W. Grimes 8805b81b6b3SRodney W. Grimes fd->track = bp->b_cylin; 881b39c878eSAndrey A. Chernov if(format) 882b39c878eSAndrey A. Chernov fd->skip = (char *)&(finfo->fd_formb_cylno(0)) 883b39c878eSAndrey A. Chernov - (char *)finfo; 8845b81b6b3SRodney W. Grimes isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip, 885b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 8865b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 8875b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 8885b81b6b3SRodney W. Grimes sectrac = fd->ft->sectrac; 8895b81b6b3SRodney W. Grimes sec = blknum % (sectrac * fd->ft->heads); 8905b81b6b3SRodney W. Grimes head = sec / sectrac; 8915b81b6b3SRodney W. Grimes sec = sec % sectrac + 1; 8925b81b6b3SRodney W. Grimes /*XXX*/ fd->hddrv = ((head&1)<<2)+fdu; 8935b81b6b3SRodney W. Grimes 894b39c878eSAndrey A. Chernov if(format) 895b39c878eSAndrey A. Chernov { 896b39c878eSAndrey A. Chernov /* formatting */ 897b39c878eSAndrey A. Chernov out_fdc(fdcu,/* NE7CMD_FORMAT */ 0x4d); 898b39c878eSAndrey A. Chernov out_fdc(fdcu,head << 2 | fdu); 899b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_secshift); 900b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_nsecs); 901b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_gaplen); 902b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_fillbyte); 903b39c878eSAndrey A. Chernov } 904b39c878eSAndrey A. Chernov else 905b39c878eSAndrey A. Chernov { 9065b81b6b3SRodney W. Grimes if (read) 9075b81b6b3SRodney W. Grimes { 9085b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_READ); /* READ */ 9095b81b6b3SRodney W. Grimes } 9105b81b6b3SRodney W. Grimes else 9115b81b6b3SRodney W. Grimes { 9125b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_WRITE); /* WRITE */ 9135b81b6b3SRodney W. Grimes } 9145b81b6b3SRodney W. Grimes out_fdc(fdcu,head << 2 | fdu); /* head & unit */ 9155b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->track); /* track */ 9165b81b6b3SRodney W. Grimes out_fdc(fdcu,head); 9175b81b6b3SRodney W. Grimes out_fdc(fdcu,sec); /* sector XXX +1? */ 9185b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->secsize); /* sector size */ 9195b81b6b3SRodney W. Grimes out_fdc(fdcu,sectrac); /* sectors/track */ 9205b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->gap); /* gap size */ 9215b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->datalen); /* data length */ 922b39c878eSAndrey A. Chernov } 9235b81b6b3SRodney W. Grimes fdc->state = IOCOMPLETE; 924381fe1aaSGarrett Wollman timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 9255b81b6b3SRodney W. Grimes return(0); /* will return later */ 9265b81b6b3SRodney W. Grimes case IOCOMPLETE: /* IO DONE, post-analyze */ 927aaf08d94SGarrett Wollman untimeout(fd_timeout, (caddr_t)fdcu); 9285b81b6b3SRodney W. Grimes for(i=0;i<7;i++) 9295b81b6b3SRodney W. Grimes { 9305b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 9315b81b6b3SRodney W. Grimes } 9325b81b6b3SRodney W. Grimes case IOTIMEDOUT: /*XXX*/ 9335b81b6b3SRodney W. Grimes isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, 934b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 9355b81b6b3SRodney W. Grimes if (fdc->status[0]&0xF8) 9365b81b6b3SRodney W. Grimes { 937b39c878eSAndrey A. Chernov if (fdc->status[1] & 0x10) { 938b39c878eSAndrey A. Chernov /* 939b39c878eSAndrey A. Chernov * Operation not completed in reasonable time. 940b39c878eSAndrey A. Chernov * Just restart it, don't increment retry count. 941b39c878eSAndrey A. Chernov * (vak) 942b39c878eSAndrey A. Chernov */ 943b39c878eSAndrey A. Chernov fdc->state = SEEKCOMPLETE; 944b39c878eSAndrey A. Chernov return (1); 945b39c878eSAndrey A. Chernov } 9465b81b6b3SRodney W. Grimes return(retrier(fdcu)); 9475b81b6b3SRodney W. Grimes } 9485b81b6b3SRodney W. Grimes /* All OK */ 9495b81b6b3SRodney W. Grimes fd->skip += FDBLK; 950b39c878eSAndrey A. Chernov if (!format && fd->skip < bp->b_bcount) 9515b81b6b3SRodney W. Grimes { 9525b81b6b3SRodney W. Grimes /* set up next transfer */ 9535b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 9545b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 9555b81b6b3SRodney W. Grimes bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads)); 9565b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9575b81b6b3SRodney W. Grimes } 9585b81b6b3SRodney W. Grimes else 9595b81b6b3SRodney W. Grimes { 9605b81b6b3SRodney W. Grimes /* ALL DONE */ 9615b81b6b3SRodney W. Grimes fd->skip = 0; 9625b81b6b3SRodney W. Grimes bp->b_resid = 0; 9635b81b6b3SRodney W. Grimes dp->b_actf = bp->av_forw; 9645b81b6b3SRodney W. Grimes biodone(bp); 9655b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 9665b81b6b3SRodney W. Grimes fdc->fdu = -1; 9675b81b6b3SRodney W. Grimes fdc->state = FINDWORK; 9685b81b6b3SRodney W. Grimes } 9695b81b6b3SRodney W. Grimes return(1); 9705b81b6b3SRodney W. Grimes case RESETCTLR: 9715b81b6b3SRodney W. Grimes /* Try a reset, keep motor on */ 9725b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,1); 9735b81b6b3SRodney W. Grimes DELAY(100); 9745b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 9755b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,fd->ft->trans); 9765b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdctl]",fd->ft->trans); 9775b81b6b3SRodney W. Grimes fdc->retry++; 9785b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 9795b81b6b3SRodney W. Grimes break; 9805b81b6b3SRodney W. Grimes case STARTRECAL: 9815b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */ 9825b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 9835b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 9845b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 9855b81b6b3SRodney W. Grimes out_fdc(fdcu,fdu); 9865b81b6b3SRodney W. Grimes fdc->state = RECALWAIT; 9875b81b6b3SRodney W. Grimes return(0); /* will return later */ 9885b81b6b3SRodney W. Grimes case RECALWAIT: 9895b81b6b3SRodney W. Grimes /* allow heads to settle */ 990381fe1aaSGarrett Wollman timeout(fd_pseudointr, (caddr_t)fdcu, hz / 30); 9915b81b6b3SRodney W. Grimes fdc->state = RECALCOMPLETE; 9925b81b6b3SRodney W. Grimes return(0); /* will return later */ 9935b81b6b3SRodney W. Grimes case RECALCOMPLETE: 9945b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 9955b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 9965b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 9975b81b6b3SRodney W. Grimes if (cyl != 0) 9985b81b6b3SRodney W. Grimes { 9995b81b6b3SRodney W. Grimes printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, 10005b81b6b3SRodney W. Grimes st0, NE7_ST0BITS, cyl); 10015b81b6b3SRodney W. Grimes return(retrier(fdcu)); 10025b81b6b3SRodney W. Grimes } 10035b81b6b3SRodney W. Grimes fd->track = 0; 10045b81b6b3SRodney W. Grimes /* Seek (probably) necessary */ 10055b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 10065b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 10075b81b6b3SRodney W. Grimes case MOTORWAIT: 10085b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 10095b81b6b3SRodney W. Grimes { 10105b81b6b3SRodney W. Grimes return(0); /* time's not up yet */ 10115b81b6b3SRodney W. Grimes } 10125b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 10135b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 10145b81b6b3SRodney W. Grimes default: 10155b81b6b3SRodney W. Grimes printf("Unexpected FD int->"); 10165b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 10175b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 10185b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 10195b81b6b3SRodney W. Grimes printf("ST0 = %lx, PCN = %lx\n",i,sec); 10205b81b6b3SRodney W. Grimes out_fdc(fdcu,0x4A); 10215b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); 10225b81b6b3SRodney W. Grimes for(i=0;i<7;i++) { 10235b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 10245b81b6b3SRodney W. Grimes } 10255b81b6b3SRodney W. Grimes printf("intr status :%lx %lx %lx %lx %lx %lx %lx ", 10265b81b6b3SRodney W. Grimes fdc->status[0], 10275b81b6b3SRodney W. Grimes fdc->status[1], 10285b81b6b3SRodney W. Grimes fdc->status[2], 10295b81b6b3SRodney W. Grimes fdc->status[3], 10305b81b6b3SRodney W. Grimes fdc->status[4], 10315b81b6b3SRodney W. Grimes fdc->status[5], 10325b81b6b3SRodney W. Grimes fdc->status[6] ); 10335b81b6b3SRodney W. Grimes return(0); 10345b81b6b3SRodney W. Grimes } 10355b81b6b3SRodney W. Grimes return(1); /* Come back immediatly to new state */ 10365b81b6b3SRodney W. Grimes } 10375b81b6b3SRodney W. Grimes 1038aaf08d94SGarrett Wollman static int 1039f5f7ba03SJordan K. Hubbard retrier(fdcu) 1040f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 10415b81b6b3SRodney W. Grimes { 10425b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 10435b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 10445b81b6b3SRodney W. Grimes 10455b81b6b3SRodney W. Grimes dp = &(fdc->head); 10465b81b6b3SRodney W. Grimes bp = dp->b_actf; 10475b81b6b3SRodney W. Grimes 10485b81b6b3SRodney W. Grimes switch(fdc->retry) 10495b81b6b3SRodney W. Grimes { 10505b81b6b3SRodney W. Grimes case 0: case 1: case 2: 10515b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 10525b81b6b3SRodney W. Grimes break; 10535b81b6b3SRodney W. Grimes case 3: case 4: case 5: 10545b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 10555b81b6b3SRodney W. Grimes break; 10565b81b6b3SRodney W. Grimes case 6: 10575b81b6b3SRodney W. Grimes fdc->state = RESETCTLR; 10585b81b6b3SRodney W. Grimes break; 10595b81b6b3SRodney W. Grimes case 7: 10605b81b6b3SRodney W. Grimes break; 10615b81b6b3SRodney W. Grimes default: 10625b81b6b3SRodney W. Grimes { 10637ca0641bSAndrey A. Chernov dev_t sav_b_dev = bp->b_dev; 10647ca0641bSAndrey A. Chernov /* Trick diskerr */ 10657ca0641bSAndrey A. Chernov bp->b_dev = makedev(major(bp->b_dev), (FDUNIT(minor(bp->b_dev))<<3)|3); 106692ed385aSRodney W. Grimes diskerr(bp, "fd", "hard error", LOG_PRINTF, 106792ed385aSRodney W. Grimes fdc->fd->skip, (struct disklabel *)NULL); 10687ca0641bSAndrey A. Chernov bp->b_dev = sav_b_dev; 106992ed385aSRodney W. Grimes printf(" (ST0 %b ", fdc->status[0], NE7_ST0BITS); 10705b81b6b3SRodney W. Grimes printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS); 10715b81b6b3SRodney W. Grimes printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS); 10725b81b6b3SRodney W. Grimes printf("cyl %d hd %d sec %d)\n", 107392ed385aSRodney W. Grimes fdc->status[3], fdc->status[4], fdc->status[5]); 10745b81b6b3SRodney W. Grimes } 10755b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 10765b81b6b3SRodney W. Grimes bp->b_error = EIO; 10775b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount - fdc->fd->skip; 10785b81b6b3SRodney W. Grimes dp->b_actf = bp->av_forw; 10795b81b6b3SRodney W. Grimes fdc->fd->skip = 0; 10805b81b6b3SRodney W. Grimes biodone(bp); 108192ed385aSRodney W. Grimes fdc->state = FINDWORK; 10825b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 10835b81b6b3SRodney W. Grimes fdc->fdu = -1; 1084f5f7ba03SJordan K. Hubbard /* XXX abort current command, if any. */ 108592ed385aSRodney W. Grimes return(1); 10865b81b6b3SRodney W. Grimes } 10875b81b6b3SRodney W. Grimes fdc->retry++; 10885b81b6b3SRodney W. Grimes return(1); 10895b81b6b3SRodney W. Grimes } 10905b81b6b3SRodney W. Grimes 1091b39c878eSAndrey A. Chernov static int 1092b39c878eSAndrey A. Chernov fdformat(dev, finfo, p) 1093b39c878eSAndrey A. Chernov dev_t dev; 1094b39c878eSAndrey A. Chernov struct fd_formb *finfo; 1095b39c878eSAndrey A. Chernov struct proc *p; 1096b39c878eSAndrey A. Chernov { 1097b39c878eSAndrey A. Chernov fdu_t fdu; 1098b39c878eSAndrey A. Chernov fd_p fd; 1099b39c878eSAndrey A. Chernov 1100b39c878eSAndrey A. Chernov struct buf *bp; 1101b39c878eSAndrey A. Chernov int rv = 0, s; 1102b39c878eSAndrey A. Chernov 1103b39c878eSAndrey A. Chernov fdu = FDUNIT(minor(dev)); 1104b39c878eSAndrey A. Chernov fd = &fd_data[fdu]; 1105b39c878eSAndrey A. Chernov 1106b39c878eSAndrey A. Chernov /* set up a buffer header for fdstrategy() */ 1107b39c878eSAndrey A. Chernov bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 1108b39c878eSAndrey A. Chernov if(bp == 0) 1109b39c878eSAndrey A. Chernov return ENOBUFS; 1110b39c878eSAndrey A. Chernov bzero((void *)bp, sizeof(struct buf)); 1111b39c878eSAndrey A. Chernov bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 1112b39c878eSAndrey A. Chernov bp->b_proc = p; 1113b39c878eSAndrey A. Chernov bp->b_dev = dev; 1114b39c878eSAndrey A. Chernov 1115b39c878eSAndrey A. Chernov /* 1116b39c878eSAndrey A. Chernov * calculate a fake blkno, so fdstrategy() would initiate a 1117b39c878eSAndrey A. Chernov * seek to the requested cylinder 1118b39c878eSAndrey A. Chernov */ 1119b39c878eSAndrey A. Chernov bp->b_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) 1120b39c878eSAndrey A. Chernov + finfo->head * fd->ft->sectrac) * FDBLK / DEV_BSIZE; 1121b39c878eSAndrey A. Chernov 1122b39c878eSAndrey A. Chernov bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 1123b39c878eSAndrey A. Chernov bp->b_un.b_addr = (caddr_t)finfo; 1124b39c878eSAndrey A. Chernov 1125b39c878eSAndrey A. Chernov /* now do the format */ 1126b39c878eSAndrey A. Chernov fdstrategy(bp); 1127b39c878eSAndrey A. Chernov 1128b39c878eSAndrey A. Chernov /* ...and wait for it to complete */ 1129b39c878eSAndrey A. Chernov s = splbio(); 1130b39c878eSAndrey A. Chernov while(!(bp->b_flags & B_DONE)) 1131b39c878eSAndrey A. Chernov { 1132b39c878eSAndrey A. Chernov rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 1133b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1134b39c878eSAndrey A. Chernov break; 1135b39c878eSAndrey A. Chernov } 1136b39c878eSAndrey A. Chernov splx(s); 1137b39c878eSAndrey A. Chernov 1138b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1139b39c878eSAndrey A. Chernov { 1140b39c878eSAndrey A. Chernov /* timed out */ 1141b39c878eSAndrey A. Chernov biodone(bp); 1142b39c878eSAndrey A. Chernov rv = EIO; 1143b39c878eSAndrey A. Chernov } 1144b39c878eSAndrey A. Chernov free(bp, M_TEMP); 1145b39c878eSAndrey A. Chernov return rv; 1146b39c878eSAndrey A. Chernov } 1147b39c878eSAndrey A. Chernov 1148f5f7ba03SJordan K. Hubbard /* 1149f5f7ba03SJordan K. Hubbard * fdioctl() from jc@irbs.UUCP (John Capo) 1150f5f7ba03SJordan K. Hubbard * i386/i386/conf.c needs to have fdioctl() declared and remove the line that 1151f5f7ba03SJordan K. Hubbard * defines fdioctl to be enxio. 1152f5f7ba03SJordan K. Hubbard * 1153f5f7ba03SJordan K. Hubbard * TODO: Reformat. 1154f5f7ba03SJordan K. Hubbard * Think about allocating buffer off stack. 1155f5f7ba03SJordan K. Hubbard * Don't pass uncast 0's and NULL's to read/write/setdisklabel(). 1156f5f7ba03SJordan K. Hubbard * Watch out for NetBSD's different *disklabel() interface. 1157b39c878eSAndrey A. Chernov * 1158b39c878eSAndrey A. Chernov * Added functionality for floppy formatting 1159b39c878eSAndrey A. Chernov * joerg_wunsch@uriah.sax.de (Joerg Wunsch) 1160f5f7ba03SJordan K. Hubbard */ 11615b81b6b3SRodney W. Grimes 1162f5f7ba03SJordan K. Hubbard int 1163b39c878eSAndrey A. Chernov fdioctl (dev, cmd, addr, flag, p) 1164f5f7ba03SJordan K. Hubbard dev_t dev; 1165f5f7ba03SJordan K. Hubbard int cmd; 1166f5f7ba03SJordan K. Hubbard caddr_t addr; 1167f5f7ba03SJordan K. Hubbard int flag; 1168b39c878eSAndrey A. Chernov struct proc *p; 1169f5f7ba03SJordan K. Hubbard { 1170f5f7ba03SJordan K. Hubbard struct fd_type *fdt; 1171f5f7ba03SJordan K. Hubbard struct disklabel *dl; 1172f5f7ba03SJordan K. Hubbard char buffer[DEV_BSIZE]; 1173f5f7ba03SJordan K. Hubbard int error; 1174f5f7ba03SJordan K. Hubbard 1175b99f0a4aSAndrew Moore #if NFT > 0 1176b99f0a4aSAndrew Moore if (fd_data[FDUNIT(minor(dev))].fdc->flags & FDC_TAPE_BUSY) 1177b99f0a4aSAndrew Moore return ftioctl(dev, cmd, addr, flag, p); 1178b99f0a4aSAndrew Moore #endif 1179b99f0a4aSAndrew Moore 1180f5f7ba03SJordan K. Hubbard error = 0; 1181f5f7ba03SJordan K. Hubbard 1182f5f7ba03SJordan K. Hubbard switch (cmd) 1183f5f7ba03SJordan K. Hubbard { 1184f5f7ba03SJordan K. Hubbard case DIOCGDINFO: 1185f5f7ba03SJordan K. Hubbard bzero(buffer, sizeof (buffer)); 1186f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)buffer; 1187f5f7ba03SJordan K. Hubbard dl->d_secsize = FDBLK; 118892ed385aSRodney W. Grimes fdt = fd_data[FDUNIT(minor(dev))].ft; 1189f5f7ba03SJordan K. Hubbard dl->d_secpercyl = fdt->size / fdt->tracks; 1190f5f7ba03SJordan K. Hubbard dl->d_type = DTYPE_FLOPPY; 1191f5f7ba03SJordan K. Hubbard 1192f5f7ba03SJordan K. Hubbard if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) 1193f5f7ba03SJordan K. Hubbard error = 0; 1194f5f7ba03SJordan K. Hubbard else 1195f5f7ba03SJordan K. Hubbard error = EINVAL; 1196f5f7ba03SJordan K. Hubbard 1197f5f7ba03SJordan K. Hubbard *(struct disklabel *)addr = *dl; 1198f5f7ba03SJordan K. Hubbard break; 1199f5f7ba03SJordan K. Hubbard 1200f5f7ba03SJordan K. Hubbard case DIOCSDINFO: 1201f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1202f5f7ba03SJordan K. Hubbard error = EBADF; 1203f5f7ba03SJordan K. Hubbard break; 1204f5f7ba03SJordan K. Hubbard 1205f5f7ba03SJordan K. Hubbard case DIOCWLABEL: 1206f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1207f5f7ba03SJordan K. Hubbard error = EBADF; 1208f5f7ba03SJordan K. Hubbard break; 1209f5f7ba03SJordan K. Hubbard 1210f5f7ba03SJordan K. Hubbard case DIOCWDINFO: 1211f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1212f5f7ba03SJordan K. Hubbard { 1213f5f7ba03SJordan K. Hubbard error = EBADF; 1214f5f7ba03SJordan K. Hubbard break; 1215f5f7ba03SJordan K. Hubbard } 1216f5f7ba03SJordan K. Hubbard 1217f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)addr; 1218f5f7ba03SJordan K. Hubbard 1219b39c878eSAndrey A. Chernov if (error = setdisklabel ((struct disklabel *)buffer, 1220b39c878eSAndrey A. Chernov dl, 0, NULL)) 1221f5f7ba03SJordan K. Hubbard break; 1222f5f7ba03SJordan K. Hubbard 1223b39c878eSAndrey A. Chernov error = writedisklabel(dev, fdstrategy, 1224b39c878eSAndrey A. Chernov (struct disklabel *)buffer, NULL); 1225b39c878eSAndrey A. Chernov break; 1226b39c878eSAndrey A. Chernov 1227b39c878eSAndrey A. Chernov case FD_FORM: 1228b39c878eSAndrey A. Chernov if((flag & FWRITE) == 0) 1229b39c878eSAndrey A. Chernov error = EBADF; /* must be opened for writing */ 1230b39c878eSAndrey A. Chernov else if(((struct fd_formb *)addr)->format_version != 1231b39c878eSAndrey A. Chernov FD_FORMAT_VERSION) 1232b39c878eSAndrey A. Chernov error = EINVAL; /* wrong version of formatting prog */ 1233b39c878eSAndrey A. Chernov else 1234b39c878eSAndrey A. Chernov error = fdformat(dev, (struct fd_formb *)addr, p); 1235b39c878eSAndrey A. Chernov break; 1236b39c878eSAndrey A. Chernov 1237b39c878eSAndrey A. Chernov case FD_GTYPE: /* get drive type */ 1238b39c878eSAndrey A. Chernov *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft; 1239f5f7ba03SJordan K. Hubbard break; 1240f5f7ba03SJordan K. Hubbard 1241f5f7ba03SJordan K. Hubbard default: 1242f5f7ba03SJordan K. Hubbard error = EINVAL; 1243f5f7ba03SJordan K. Hubbard break; 1244f5f7ba03SJordan K. Hubbard } 1245f5f7ba03SJordan K. Hubbard return (error); 1246f5f7ba03SJordan K. Hubbard } 1247f5f7ba03SJordan K. Hubbard 1248f5f7ba03SJordan K. Hubbard #endif 1249