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 38ed2fa05eSAndrey A. Chernov * $Id: fd.c,v 1.14 1993/12/16 19:47:42 ache Exp $ 395b81b6b3SRodney W. Grimes * 405b81b6b3SRodney W. Grimes */ 415b81b6b3SRodney W. Grimes 425b81b6b3SRodney W. Grimes #include "fd.h" 435b81b6b3SRodney W. Grimes #if NFD > 0 445b81b6b3SRodney W. Grimes 455b81b6b3SRodney W. Grimes #include "param.h" 465b81b6b3SRodney W. Grimes #include "dkbad.h" 475b81b6b3SRodney W. Grimes #include "systm.h" 48381fe1aaSGarrett Wollman #include "kernel.h" 495b81b6b3SRodney W. Grimes #include "conf.h" 505b81b6b3SRodney W. Grimes #include "file.h" 515b81b6b3SRodney W. Grimes #include "ioctl.h" 52b39c878eSAndrey A. Chernov #include "machine/ioctl_fd.h" 53f5f7ba03SJordan K. Hubbard #include "disklabel.h" 545b81b6b3SRodney W. Grimes #include "buf.h" 555b81b6b3SRodney W. Grimes #include "uio.h" 56b39c878eSAndrey A. Chernov #include "malloc.h" 5792ed385aSRodney W. Grimes #include "syslog.h" 585b81b6b3SRodney W. Grimes #include "i386/isa/isa.h" 595b81b6b3SRodney W. Grimes #include "i386/isa/isa_device.h" 605b81b6b3SRodney W. Grimes #include "i386/isa/fdreg.h" 615b81b6b3SRodney W. Grimes #include "i386/isa/icu.h" 625b81b6b3SRodney W. Grimes #include "i386/isa/rtc.h" 635b81b6b3SRodney W. Grimes #undef NFD 645b81b6b3SRodney W. Grimes #define NFD 2 655b81b6b3SRodney W. Grimes 667ca0641bSAndrey A. Chernov #define FDUNIT(s) (((s)>>6)&03) 677ca0641bSAndrey A. Chernov #define FDTYPE(s) ((s)&077) 685b81b6b3SRodney W. Grimes 695b81b6b3SRodney W. Grimes #define b_cylin b_resid 705b81b6b3SRodney W. Grimes #define FDBLK 512 715b81b6b3SRodney W. Grimes 72b39c878eSAndrey A. Chernov /* misuse a flag to identify format operation */ 73b39c878eSAndrey A. Chernov #define B_FORMAT B_XXX 745b81b6b3SRodney W. Grimes 75b39c878eSAndrey A. Chernov #define NUMTYPES 14 76b39c878eSAndrey A. Chernov #define NUMDENS (NUMTYPES - 6) 777ca0641bSAndrey A. Chernov 78dffff499SAndrey A. Chernov /* This defines must match fd_types */ 79ed2fa05eSAndrey A. Chernov #define FD_1720 0 80ed2fa05eSAndrey A. Chernov #define FD_1480 1 81ed2fa05eSAndrey A. Chernov #define FD_1440 2 82ed2fa05eSAndrey A. Chernov #define FD_1200 3 83ed2fa05eSAndrey A. Chernov #define FD_820 4 84ed2fa05eSAndrey A. Chernov #define FD_800 5 85ed2fa05eSAndrey A. Chernov #define FD_720 6 86ed2fa05eSAndrey A. Chernov #define FD_360 7 87ed2fa05eSAndrey A. Chernov 88b39c878eSAndrey A. Chernov #define FD_1480in5_25 8 89b39c878eSAndrey A. Chernov #define FD_1440in5_25 9 90b39c878eSAndrey A. Chernov #define FD_820in5_25 10 91b39c878eSAndrey A. Chernov #define FD_800in5_25 11 92b39c878eSAndrey A. Chernov #define FD_720in5_25 12 93b39c878eSAndrey A. Chernov #define FD_360in5_25 13 947ca0641bSAndrey A. Chernov 955b81b6b3SRodney W. Grimes struct fd_type fd_types[NUMTYPES] = 965b81b6b3SRodney W. Grimes { 97b39c878eSAndrey A. Chernov { 21,2,0xFF,0x0C,82,3444,1,FDC_500KBPS,2,2 }, /* 1.72M in HD 3.5in */ 98b39c878eSAndrey A. Chernov { 18,2,0xFF,0x6C,82,2952,1,FDC_500KBPS,2,1 }, /* 1.48M in HD 3.5in */ 99b39c878eSAndrey A. Chernov { 18,2,0xFF,0x6C,80,2880,1,FDC_500KBPS,2,1 }, /* 1.44M in HD 3.5in */ 100b39c878eSAndrey A. Chernov { 15,2,0xFF,0x54,80,2400,1,FDC_500KBPS,2,1 }, /* 1.2M in HD 5.25/3.5 */ 101b39c878eSAndrey A. Chernov { 10,2,0xFF,0x2E,82,1640,1,FDC_250KBPS,2,1 }, /* 820K in HD 3.5in */ 102b39c878eSAndrey A. Chernov { 10,2,0xFF,0x2E,80,1600,1,FDC_250KBPS,2,1 }, /* 800K in HD 3.5in */ 103b39c878eSAndrey A. Chernov { 9,2,0xFF,0x50,80,1440,1,FDC_250KBPS,2,1 }, /* 720K in HD 3.5in */ 104b39c878eSAndrey A. Chernov { 9,2,0xFF,0x50,40, 720,1,FDC_300KBPS,2,1 }, /* 360K in DD 5.25in */ 105ed2fa05eSAndrey A. Chernov 106b39c878eSAndrey A. Chernov { 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,2 }, /* 1.48M in HD 5.25in */ 107b39c878eSAndrey A. Chernov { 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,2 }, /* 1.44M in HD 5.25in */ 108b39c878eSAndrey A. Chernov { 10,2,0xFF,0x2E,82,1640,1,FDC_300KBPS,2,1 }, /* 820K in HD 5.25in */ 109b39c878eSAndrey A. Chernov { 10,2,0xFF,0x2E,80,1600,1,FDC_300KBPS,2,1 }, /* 800K in HD 5.25in */ 110b39c878eSAndrey A. Chernov { 9,2,0xFF,0x50,80,1440,1,FDC_300KBPS,2,1 }, /* 720K in HD 5.25in */ 111b39c878eSAndrey A. Chernov { 9,2,0xFF,0x50,40, 720,2,FDC_300KBPS,2,1 }, /* 360K in HD 5.25in */ 1125b81b6b3SRodney W. Grimes }; 1135b81b6b3SRodney W. Grimes 1145b81b6b3SRodney W. Grimes #define DRVS_PER_CTLR 2 1155b81b6b3SRodney W. Grimes /***********************************************************************\ 1165b81b6b3SRodney W. Grimes * Per controller structure. * 1175b81b6b3SRodney W. Grimes \***********************************************************************/ 1185b81b6b3SRodney W. Grimes struct fdc_data 1195b81b6b3SRodney W. Grimes { 1205b81b6b3SRodney W. Grimes int fdcu; /* our unit number */ 1215b81b6b3SRodney W. Grimes int baseport; 1225b81b6b3SRodney W. Grimes int dmachan; 1235b81b6b3SRodney W. Grimes int flags; 1245b81b6b3SRodney W. Grimes #define FDC_ATTACHED 0x01 1255b81b6b3SRodney W. Grimes struct fd_data *fd; 1265b81b6b3SRodney W. Grimes int fdu; /* the active drive */ 1275b81b6b3SRodney W. Grimes struct buf head; /* Head of buf chain */ 1285b81b6b3SRodney W. Grimes struct buf rhead; /* Raw head of buf chain */ 1295b81b6b3SRodney W. Grimes int state; 1305b81b6b3SRodney W. Grimes int retry; 1315b81b6b3SRodney W. Grimes int status[7]; /* copy of the registers */ 1325b81b6b3SRodney W. Grimes }fdc_data[(NFD+1)/DRVS_PER_CTLR]; 1335b81b6b3SRodney W. Grimes 1345b81b6b3SRodney W. Grimes /***********************************************************************\ 1355b81b6b3SRodney W. Grimes * Per drive structure. * 1365b81b6b3SRodney W. Grimes * N per controller (presently 2) (DRVS_PER_CTLR) * 1375b81b6b3SRodney W. Grimes \***********************************************************************/ 1385b81b6b3SRodney W. Grimes struct fd_data { 1395b81b6b3SRodney W. Grimes struct fdc_data *fdc; 1405b81b6b3SRodney W. Grimes int fdu; /* this unit number */ 1415b81b6b3SRodney W. Grimes int fdsu; /* this units number on this controller */ 1425b81b6b3SRodney W. Grimes int type; /* Drive type (HD, DD */ 1435b81b6b3SRodney W. Grimes struct fd_type *ft; /* pointer to the type descriptor */ 1445b81b6b3SRodney W. Grimes int flags; 1455b81b6b3SRodney W. Grimes #define FD_OPEN 0x01 /* it's open */ 1465b81b6b3SRodney W. Grimes #define FD_ACTIVE 0x02 /* it's active */ 1475b81b6b3SRodney W. Grimes #define FD_MOTOR 0x04 /* motor should be on */ 1485b81b6b3SRodney W. Grimes #define FD_MOTOR_WAIT 0x08 /* motor coming up */ 1495b81b6b3SRodney W. Grimes int skip; 1505b81b6b3SRodney W. Grimes int hddrv; 1515b81b6b3SRodney W. Grimes int track; /* where we think the head is */ 1525b81b6b3SRodney W. Grimes } fd_data[NFD]; 1535b81b6b3SRodney W. Grimes 1545b81b6b3SRodney W. Grimes /***********************************************************************\ 1555b81b6b3SRodney W. Grimes * Throughout this file the following conventions will be used: * 1565b81b6b3SRodney W. Grimes * fd is a pointer to the fd_data struct for the drive in question * 1575b81b6b3SRodney W. Grimes * fdc is a pointer to the fdc_data struct for the controller * 1585b81b6b3SRodney W. Grimes * fdu is the floppy drive unit number * 1595b81b6b3SRodney W. Grimes * fdcu is the floppy controller unit number * 1605b81b6b3SRodney W. Grimes * fdsu is the floppy drive unit number on that controller. (sub-unit) * 1615b81b6b3SRodney W. Grimes \***********************************************************************/ 1625b81b6b3SRodney W. Grimes typedef int fdu_t; 1635b81b6b3SRodney W. Grimes typedef int fdcu_t; 1645b81b6b3SRodney W. Grimes typedef int fdsu_t; 1655b81b6b3SRodney W. Grimes typedef struct fd_data *fd_p; 1665b81b6b3SRodney W. Grimes typedef struct fdc_data *fdc_p; 1675b81b6b3SRodney W. Grimes 1685b81b6b3SRodney W. Grimes #define DEVIDLE 0 1695b81b6b3SRodney W. Grimes #define FINDWORK 1 1705b81b6b3SRodney W. Grimes #define DOSEEK 2 1715b81b6b3SRodney W. Grimes #define SEEKCOMPLETE 3 1725b81b6b3SRodney W. Grimes #define IOCOMPLETE 4 1735b81b6b3SRodney W. Grimes #define RECALCOMPLETE 5 1745b81b6b3SRodney W. Grimes #define STARTRECAL 6 1755b81b6b3SRodney W. Grimes #define RESETCTLR 7 1765b81b6b3SRodney W. Grimes #define SEEKWAIT 8 1775b81b6b3SRodney W. Grimes #define RECALWAIT 9 1785b81b6b3SRodney W. Grimes #define MOTORWAIT 10 1795b81b6b3SRodney W. Grimes #define IOTIMEDOUT 11 1805b81b6b3SRodney W. Grimes 1815b81b6b3SRodney W. Grimes #ifdef DEBUG 1825b81b6b3SRodney W. Grimes char *fdstates[] = 1835b81b6b3SRodney W. Grimes { 1845b81b6b3SRodney W. Grimes "DEVIDLE", 1855b81b6b3SRodney W. Grimes "FINDWORK", 1865b81b6b3SRodney W. Grimes "DOSEEK", 1875b81b6b3SRodney W. Grimes "SEEKCOMPLETE", 1885b81b6b3SRodney W. Grimes "IOCOMPLETE", 1895b81b6b3SRodney W. Grimes "RECALCOMPLETE", 1905b81b6b3SRodney W. Grimes "STARTRECAL", 1915b81b6b3SRodney W. Grimes "RESETCTLR", 1925b81b6b3SRodney W. Grimes "SEEKWAIT", 1935b81b6b3SRodney W. Grimes "RECALWAIT", 1945b81b6b3SRodney W. Grimes "MOTORWAIT", 1955b81b6b3SRodney W. Grimes "IOTIMEDOUT" 1965b81b6b3SRodney W. Grimes }; 1975b81b6b3SRodney W. Grimes 1985b81b6b3SRodney W. Grimes 1995b81b6b3SRodney W. Grimes int fd_debug = 1; 2005b81b6b3SRodney W. Grimes #define TRACE0(arg) if(fd_debug) printf(arg) 2015b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2) 202381fe1aaSGarrett Wollman #else /* DEBUG */ 2035b81b6b3SRodney W. Grimes #define TRACE0(arg) 2045b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) 205381fe1aaSGarrett Wollman #endif /* DEBUG */ 2065b81b6b3SRodney W. Grimes 207381fe1aaSGarrett Wollman static void fdstart(fdcu_t); 208381fe1aaSGarrett Wollman void fdintr(fdcu_t); 209381fe1aaSGarrett Wollman static void fd_turnoff(caddr_t, int); 2105b81b6b3SRodney W. Grimes 2115b81b6b3SRodney W. Grimes /****************************************************************************/ 2125b81b6b3SRodney W. Grimes /* autoconfiguration stuff */ 2135b81b6b3SRodney W. Grimes /****************************************************************************/ 214381fe1aaSGarrett Wollman static int fdprobe(struct isa_device *); 215381fe1aaSGarrett Wollman static int fdattach(struct isa_device *); 2165b81b6b3SRodney W. Grimes 2175b81b6b3SRodney W. Grimes struct isa_driver fddriver = { 2185b81b6b3SRodney W. Grimes fdprobe, fdattach, "fd", 2195b81b6b3SRodney W. Grimes }; 2205b81b6b3SRodney W. Grimes 2215b81b6b3SRodney W. Grimes /* 2225b81b6b3SRodney W. Grimes * probe for existance of controller 2235b81b6b3SRodney W. Grimes */ 224381fe1aaSGarrett Wollman int 2255b81b6b3SRodney W. Grimes fdprobe(dev) 2265b81b6b3SRodney W. Grimes struct isa_device *dev; 2275b81b6b3SRodney W. Grimes { 2285b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2295b81b6b3SRodney W. Grimes if(fdc_data[fdcu].flags & FDC_ATTACHED) 2305b81b6b3SRodney W. Grimes { 2315b81b6b3SRodney W. Grimes printf("fdc: same unit (%d) used multiple times\n",fdcu); 2325b81b6b3SRodney W. Grimes return 0; 2335b81b6b3SRodney W. Grimes } 2345b81b6b3SRodney W. Grimes 2355b81b6b3SRodney W. Grimes fdc_data[fdcu].baseport = dev->id_iobase; 2365b81b6b3SRodney W. Grimes 23716111cedSAndrew Moore /* First - lets reset the floppy controller */ 23816111cedSAndrew Moore 23916111cedSAndrew Moore outb(dev->id_iobase+fdout,0); 24016111cedSAndrew Moore DELAY(100); 24116111cedSAndrew Moore outb(dev->id_iobase+fdout,FDO_FRST); 24216111cedSAndrew Moore 2435b81b6b3SRodney W. Grimes /* see if it can handle a command */ 2445b81b6b3SRodney W. Grimes if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0) 2455b81b6b3SRodney W. Grimes { 2465b81b6b3SRodney W. Grimes return(0); 2475b81b6b3SRodney W. Grimes } 2485b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 2495b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 2505b81b6b3SRodney W. Grimes return (IO_FDCSIZE); 2515b81b6b3SRodney W. Grimes } 2525b81b6b3SRodney W. Grimes 2535b81b6b3SRodney W. Grimes /* 2545b81b6b3SRodney W. Grimes * wire controller into system, look for floppy units 2555b81b6b3SRodney W. Grimes */ 256381fe1aaSGarrett Wollman int 2575b81b6b3SRodney W. Grimes fdattach(dev) 2585b81b6b3SRodney W. Grimes struct isa_device *dev; 2595b81b6b3SRodney W. Grimes { 2605b81b6b3SRodney W. Grimes unsigned fdt,st0, cyl; 2615b81b6b3SRodney W. Grimes int hdr; 2625b81b6b3SRodney W. Grimes fdu_t fdu; 2635b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2645b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 2655b81b6b3SRodney W. Grimes fd_p fd; 2665b81b6b3SRodney W. Grimes int fdsu; 2675b81b6b3SRodney W. Grimes 2685b81b6b3SRodney W. Grimes fdc->fdcu = fdcu; 2695b81b6b3SRodney W. Grimes fdc->flags |= FDC_ATTACHED; 2705b81b6b3SRodney W. Grimes fdc->dmachan = dev->id_drq; 2715b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 2725b81b6b3SRodney W. Grimes 2735b81b6b3SRodney W. Grimes fdt = rtcin(RTC_FDISKETTE); 2745b81b6b3SRodney W. Grimes hdr = 0; 2755b81b6b3SRodney W. Grimes 2765b81b6b3SRodney W. Grimes /* check for each floppy drive */ 2775b81b6b3SRodney W. Grimes for (fdu = (fdcu * DRVS_PER_CTLR),fdsu = 0; 2785b81b6b3SRodney W. Grimes ((fdu < NFD) && (fdsu < DRVS_PER_CTLR)); 2795b81b6b3SRodney W. Grimes fdu++,fdsu++) 2805b81b6b3SRodney W. Grimes { 2815b81b6b3SRodney W. Grimes /* is there a unit? */ 282f5f7ba03SJordan K. Hubbard if ((fdt & 0xf0) == RTCFDT_NONE) { 283f5f7ba03SJordan K. Hubbard #define NO_TYPE NUMTYPES 284f5f7ba03SJordan K. Hubbard fd_data[fdu].type = NO_TYPE; 2855b81b6b3SRodney W. Grimes continue; 286f5f7ba03SJordan K. Hubbard } 2875b81b6b3SRodney W. Grimes 2885b81b6b3SRodney W. Grimes #ifdef notyet 2895b81b6b3SRodney W. Grimes /* select it */ 2905b81b6b3SRodney W. Grimes fd_turnon1(fdu); 2915b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 2925b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 2935b81b6b3SRodney W. Grimes out_fdc(fdcu,fdsu); 2945b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 2955b81b6b3SRodney W. Grimes 2965b81b6b3SRodney W. Grimes /* anything responding */ 2975b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 2985b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 2995b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 3005b81b6b3SRodney W. Grimes if (st0 & 0xd0) 3015b81b6b3SRodney W. Grimes continue; 3025b81b6b3SRodney W. Grimes 3035b81b6b3SRodney W. Grimes #endif 3045b81b6b3SRodney W. Grimes fd_data[fdu].track = -2; 3055b81b6b3SRodney W. Grimes fd_data[fdu].fdc = fdc; 3065b81b6b3SRodney W. Grimes fd_data[fdu].fdsu = fdsu; 3072a6c8980SDavid Greenman printf("fd%d: unit %d type ", fdcu, fdu); 3085b81b6b3SRodney W. Grimes 3097ca0641bSAndrey A. Chernov switch (fdt & 0xf0) { 3107ca0641bSAndrey A. Chernov case RTCFDT_12M: 3112a6c8980SDavid Greenman printf("1.2MB 5.25in\n"); 3127ca0641bSAndrey A. Chernov fd_data[fdu].type = FD_1200; 3137ca0641bSAndrey A. Chernov break; 3147ca0641bSAndrey A. Chernov case RTCFDT_144M: 3152a6c8980SDavid Greenman printf("1.44MB 3.5in\n"); 3167ca0641bSAndrey A. Chernov fd_data[fdu].type = FD_1440; 3177ca0641bSAndrey A. Chernov break; 3187ca0641bSAndrey A. Chernov case RTCFDT_360K: 319ed2fa05eSAndrey A. Chernov printf("360KB 5.25in\n"); 3207ca0641bSAndrey A. Chernov fd_data[fdu].type = FD_360; 3217ca0641bSAndrey A. Chernov break; 322ed2fa05eSAndrey A. Chernov case RTCFDT_720K: 323ed2fa05eSAndrey A. Chernov printf("720KB 3.5in\n"); 324ed2fa05eSAndrey A. Chernov fd_data[fdu].type = FD_720; 325ed2fa05eSAndrey A. Chernov break; 3267ca0641bSAndrey A. Chernov default: 3277ca0641bSAndrey A. Chernov printf("unknown\n"); 3287ca0641bSAndrey A. Chernov fd_data[fdu].type = NO_TYPE; 3297ca0641bSAndrey A. Chernov break; 3305b81b6b3SRodney W. Grimes } 3315b81b6b3SRodney W. Grimes 3325b81b6b3SRodney W. Grimes fdt <<= 4; 333381fe1aaSGarrett Wollman fd_turnoff((caddr_t)fdu, 0); 3345b81b6b3SRodney W. Grimes hdr = 1; 3355b81b6b3SRodney W. Grimes } 3365b81b6b3SRodney W. Grimes 3375b81b6b3SRodney W. Grimes /* Set transfer to 500kbps */ 3385b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,0); /*XXX*/ 339381fe1aaSGarrett Wollman return 1; 3405b81b6b3SRodney W. Grimes } 3415b81b6b3SRodney W. Grimes 3425b81b6b3SRodney W. Grimes int 3435b81b6b3SRodney W. Grimes fdsize(dev) 3445b81b6b3SRodney W. Grimes dev_t dev; 3455b81b6b3SRodney W. Grimes { 3465b81b6b3SRodney W. Grimes return(0); 3475b81b6b3SRodney W. Grimes } 3485b81b6b3SRodney W. Grimes 3495b81b6b3SRodney W. Grimes /****************************************************************************/ 3505b81b6b3SRodney W. Grimes /* fdstrategy */ 3515b81b6b3SRodney W. Grimes /****************************************************************************/ 352381fe1aaSGarrett Wollman void fdstrategy(struct buf *bp) 3535b81b6b3SRodney W. Grimes { 3545b81b6b3SRodney W. Grimes register struct buf *dp,*dp0,*dp1; 3555b81b6b3SRodney W. Grimes long nblocks,blknum; 3565b81b6b3SRodney W. Grimes int s; 3575b81b6b3SRodney W. Grimes fdcu_t fdcu; 3585b81b6b3SRodney W. Grimes fdu_t fdu; 3595b81b6b3SRodney W. Grimes fdc_p fdc; 3605b81b6b3SRodney W. Grimes fd_p fd; 3615b81b6b3SRodney W. Grimes 3625b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 3635b81b6b3SRodney W. Grimes fd = &fd_data[fdu]; 3645b81b6b3SRodney W. Grimes fdc = fd->fdc; 3655b81b6b3SRodney W. Grimes fdcu = fdc->fdcu; 3665b81b6b3SRodney W. Grimes /*type = FDTYPE(minor(bp->b_dev));*/ 3675b81b6b3SRodney W. Grimes 3685b81b6b3SRodney W. Grimes if ((fdu >= NFD) || (bp->b_blkno < 0)) { 3695b81b6b3SRodney W. Grimes printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n", 3705b81b6b3SRodney W. Grimes fdu, bp->b_blkno, bp->b_bcount); 3715b81b6b3SRodney W. Grimes pg("fd:error in fdstrategy"); 3725b81b6b3SRodney W. Grimes bp->b_error = EINVAL; 3735b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 3745b81b6b3SRodney W. Grimes goto bad; 3755b81b6b3SRodney W. Grimes } 3765b81b6b3SRodney W. Grimes /* 3775b81b6b3SRodney W. Grimes * Set up block calculations. 3785b81b6b3SRodney W. Grimes */ 3795b81b6b3SRodney W. Grimes blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK; 3805b81b6b3SRodney W. Grimes nblocks = fd->ft->size; 3815b81b6b3SRodney W. Grimes if (blknum + (bp->b_bcount / FDBLK) > nblocks) { 3825b81b6b3SRodney W. Grimes if (blknum == nblocks) { 3835b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount; 3845b81b6b3SRodney W. Grimes } else { 3855b81b6b3SRodney W. Grimes bp->b_error = ENOSPC; 3865b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 3875b81b6b3SRodney W. Grimes } 3885b81b6b3SRodney W. Grimes goto bad; 3895b81b6b3SRodney W. Grimes } 3905b81b6b3SRodney W. Grimes bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads); 3915b81b6b3SRodney W. Grimes dp = &(fdc->head); 3925b81b6b3SRodney W. Grimes s = splbio(); 3935b81b6b3SRodney W. Grimes disksort(dp, bp); 3945b81b6b3SRodney W. Grimes untimeout(fd_turnoff,fdu); /* a good idea */ 3955b81b6b3SRodney W. Grimes fdstart(fdcu); 3965b81b6b3SRodney W. Grimes splx(s); 3975b81b6b3SRodney W. Grimes return; 3985b81b6b3SRodney W. Grimes 3995b81b6b3SRodney W. Grimes bad: 4005b81b6b3SRodney W. Grimes biodone(bp); 401b39c878eSAndrey A. Chernov return; 4025b81b6b3SRodney W. Grimes } 4035b81b6b3SRodney W. Grimes 4045b81b6b3SRodney W. Grimes /****************************************************************************/ 4055b81b6b3SRodney W. Grimes /* motor control stuff */ 4065b81b6b3SRodney W. Grimes /* remember to not deselect the drive we're working on */ 4075b81b6b3SRodney W. Grimes /****************************************************************************/ 408381fe1aaSGarrett Wollman void 409f5f7ba03SJordan K. Hubbard set_motor(fdcu, fdu, reset) 410f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 411f5f7ba03SJordan K. Hubbard fdu_t fdu; 412f5f7ba03SJordan K. Hubbard int reset; 4135b81b6b3SRodney W. Grimes { 4145b81b6b3SRodney W. Grimes int m0,m1; 4155b81b6b3SRodney W. Grimes int selunit; 4165b81b6b3SRodney W. Grimes fd_p fd; 4175b81b6b3SRodney W. Grimes if(fd = fdc_data[fdcu].fd)/* yes an assign! */ 4185b81b6b3SRodney W. Grimes { 4195b81b6b3SRodney W. Grimes selunit = fd->fdsu; 4205b81b6b3SRodney W. Grimes } 4215b81b6b3SRodney W. Grimes else 4225b81b6b3SRodney W. Grimes { 4235b81b6b3SRodney W. Grimes selunit = 0; 4245b81b6b3SRodney W. Grimes } 4255b81b6b3SRodney W. Grimes m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR; 4265b81b6b3SRodney W. Grimes m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR; 4275b81b6b3SRodney W. Grimes outb(fdc_data[fdcu].baseport+fdout, 4285b81b6b3SRodney W. Grimes selunit 4295b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4305b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4315b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0)); 4325b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdout]",( 4335b81b6b3SRodney W. Grimes selunit 4345b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4355b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4365b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0))); 4375b81b6b3SRodney W. Grimes } 4385b81b6b3SRodney W. Grimes 439381fe1aaSGarrett Wollman static void 440381fe1aaSGarrett Wollman fd_turnoff(caddr_t arg1, int arg2) 4415b81b6b3SRodney W. Grimes { 442381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 443f5f7ba03SJordan K. Hubbard int s; 444f5f7ba03SJordan K. Hubbard 4455b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 446f5f7ba03SJordan K. Hubbard s = splbio(); 4475b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR; 4485b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 449f5f7ba03SJordan K. Hubbard splx(s); 4505b81b6b3SRodney W. Grimes } 4515b81b6b3SRodney W. Grimes 452381fe1aaSGarrett Wollman void 453381fe1aaSGarrett Wollman fd_motor_on(caddr_t arg1, int arg2) 4545b81b6b3SRodney W. Grimes { 455381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 456f5f7ba03SJordan K. Hubbard int s; 457f5f7ba03SJordan K. Hubbard 4585b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 459f5f7ba03SJordan K. Hubbard s = splbio(); 4605b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR_WAIT; 4615b81b6b3SRodney W. Grimes if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) 4625b81b6b3SRodney W. Grimes { 463f5f7ba03SJordan K. Hubbard fdintr(fd->fdc->fdcu); 4645b81b6b3SRodney W. Grimes } 465f5f7ba03SJordan K. Hubbard splx(s); 4665b81b6b3SRodney W. Grimes } 4675b81b6b3SRodney W. Grimes 468381fe1aaSGarrett Wollman static void fd_turnon1(fdu_t); 469381fe1aaSGarrett Wollman 470381fe1aaSGarrett Wollman void 471f5f7ba03SJordan K. Hubbard fd_turnon(fdu) 472f5f7ba03SJordan K. Hubbard fdu_t fdu; 4735b81b6b3SRodney W. Grimes { 4745b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 4755b81b6b3SRodney W. Grimes if(!(fd->flags & FD_MOTOR)) 4765b81b6b3SRodney W. Grimes { 4775b81b6b3SRodney W. Grimes fd_turnon1(fdu); 4785b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR_WAIT; 479381fe1aaSGarrett Wollman timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ 4805b81b6b3SRodney W. Grimes } 4815b81b6b3SRodney W. Grimes } 4825b81b6b3SRodney W. Grimes 483381fe1aaSGarrett Wollman static void 484381fe1aaSGarrett Wollman fd_turnon1(fdu_t fdu) 4855b81b6b3SRodney W. Grimes { 4865b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 4875b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR; 4885b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 4895b81b6b3SRodney W. Grimes } 4905b81b6b3SRodney W. Grimes 4915b81b6b3SRodney W. Grimes /****************************************************************************/ 4925b81b6b3SRodney W. Grimes /* fdc in/out */ 4935b81b6b3SRodney W. Grimes /****************************************************************************/ 4945b81b6b3SRodney W. Grimes int 495f5f7ba03SJordan K. Hubbard in_fdc(fdcu) 496f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 4975b81b6b3SRodney W. Grimes { 4985b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 4995b81b6b3SRodney W. Grimes int i, j = 100000; 5005b81b6b3SRodney W. Grimes while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM)) 5015b81b6b3SRodney W. Grimes != (NE7_DIO|NE7_RQM) && j-- > 0) 5025b81b6b3SRodney W. Grimes if (i == NE7_RQM) return -1; 5035b81b6b3SRodney W. Grimes if (j <= 0) 5045b81b6b3SRodney W. Grimes return(-1); 5055b81b6b3SRodney W. Grimes #ifdef DEBUG 5065b81b6b3SRodney W. Grimes i = inb(baseport+fddata); 5075b81b6b3SRodney W. Grimes TRACE1("[fddata->0x%x]",(unsigned char)i); 5085b81b6b3SRodney W. Grimes return(i); 5095b81b6b3SRodney W. Grimes #else 5105b81b6b3SRodney W. Grimes return inb(baseport+fddata); 5115b81b6b3SRodney W. Grimes #endif 5125b81b6b3SRodney W. Grimes } 5135b81b6b3SRodney W. Grimes 514381fe1aaSGarrett Wollman int 515f5f7ba03SJordan K. Hubbard out_fdc(fdcu, x) 516f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 517f5f7ba03SJordan K. Hubbard int x; 5185b81b6b3SRodney W. Grimes { 5195b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5203b3837dbSRodney W. Grimes int i; 5215b81b6b3SRodney W. Grimes 5223b3837dbSRodney W. Grimes /* Check that the direction bit is set */ 5233b3837dbSRodney W. Grimes i = 100000; 5245b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0); 5253b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5263b3837dbSRodney W. Grimes 5273b3837dbSRodney W. Grimes /* Check that the floppy controller is ready for a command */ 5283b3837dbSRodney W. Grimes i = 100000; 5295b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0); 5303b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5313b3837dbSRodney W. Grimes 5323b3837dbSRodney W. Grimes /* Send the command and return */ 5335b81b6b3SRodney W. Grimes outb(baseport+fddata,x); 5345b81b6b3SRodney W. Grimes TRACE1("[0x%x->fddata]",x); 5355b81b6b3SRodney W. Grimes return (0); 5365b81b6b3SRodney W. Grimes } 5375b81b6b3SRodney W. Grimes 5385b81b6b3SRodney W. Grimes /****************************************************************************/ 5395b81b6b3SRodney W. Grimes /* fdopen/fdclose */ 5405b81b6b3SRodney W. Grimes /****************************************************************************/ 541381fe1aaSGarrett Wollman int 5425b81b6b3SRodney W. Grimes Fdopen(dev, flags) 5435b81b6b3SRodney W. Grimes dev_t dev; 5445b81b6b3SRodney W. Grimes int flags; 5455b81b6b3SRodney W. Grimes { 5465b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 54720a29168SAndrey A. Chernov int type = FDTYPE(minor(dev)); 5485b81b6b3SRodney W. Grimes int s; 5495b81b6b3SRodney W. Grimes 5505b81b6b3SRodney W. Grimes /* check bounds */ 551fadc21aeSAndreas Schulz if (fdu >= NFD || fd_data[fdu].fdc == NULL 552fadc21aeSAndreas Schulz || fd_data[fdu].type == NO_TYPE) return(ENXIO); 553ed2fa05eSAndrey A. Chernov if (type > NUMDENS) return(ENXIO); 5547ca0641bSAndrey A. Chernov if (type == 0) 5557ca0641bSAndrey A. Chernov type = fd_data[fdu].type; 5567ca0641bSAndrey A. Chernov else { 5577ca0641bSAndrey A. Chernov type--; 5587ca0641bSAndrey A. Chernov if (type != fd_data[fdu].type) { 559fa4700b4SAndrey A. Chernov switch (fd_data[fdu].type) { 5607ca0641bSAndrey A. Chernov case FD_360: 5617ca0641bSAndrey A. Chernov return(ENXIO); 562ed2fa05eSAndrey A. Chernov case FD_720: 563b39c878eSAndrey A. Chernov if ( type != FD_820 564b39c878eSAndrey A. Chernov && type != FD_800 565ed2fa05eSAndrey A. Chernov ) 566ed2fa05eSAndrey A. Chernov return(ENXIO); 567ed2fa05eSAndrey A. Chernov break; 5687ca0641bSAndrey A. Chernov case FD_1200: 569b39c878eSAndrey A. Chernov switch (type) { 570b39c878eSAndrey A. Chernov case FD_1480: 571b39c878eSAndrey A. Chernov type = FD_1480in5_25; 572fa4700b4SAndrey A. Chernov break; 5737ca0641bSAndrey A. Chernov case FD_1440: 574b39c878eSAndrey A. Chernov type = FD_1440in5_25; 575b39c878eSAndrey A. Chernov break; 576b39c878eSAndrey A. Chernov case FD_820: 577b39c878eSAndrey A. Chernov type = FD_820in5_25; 578b39c878eSAndrey A. Chernov break; 579b39c878eSAndrey A. Chernov case FD_800: 580b39c878eSAndrey A. Chernov type = FD_800in5_25; 581b39c878eSAndrey A. Chernov break; 582b39c878eSAndrey A. Chernov case FD_720: 583b39c878eSAndrey A. Chernov type = FD_720in5_25; 584b39c878eSAndrey A. Chernov break; 585b39c878eSAndrey A. Chernov case FD_360: 586b39c878eSAndrey A. Chernov type = FD_360in5_25; 587b39c878eSAndrey A. Chernov break; 588b39c878eSAndrey A. Chernov default: 589b39c878eSAndrey A. Chernov return(ENXIO); 590b39c878eSAndrey A. Chernov } 591b39c878eSAndrey A. Chernov break; 592b39c878eSAndrey A. Chernov case FD_1440: 593b39c878eSAndrey A. Chernov if ( type != FD_1720 594b39c878eSAndrey A. Chernov && type != FD_1480 595ed2fa05eSAndrey A. Chernov && type != FD_1200 596b39c878eSAndrey A. Chernov && type != FD_820 597b39c878eSAndrey A. Chernov && type != FD_800 598b39c878eSAndrey A. Chernov && type != FD_720 5997ca0641bSAndrey A. Chernov ) 600dffff499SAndrey A. Chernov return(ENXIO); 601fa4700b4SAndrey A. Chernov break; 6027ca0641bSAndrey A. Chernov } 6037ca0641bSAndrey A. Chernov } 604fa4700b4SAndrey A. Chernov } 605dffff499SAndrey A. Chernov fd_data[fdu].ft = fd_types + type; 6065b81b6b3SRodney W. Grimes fd_data[fdu].flags |= FD_OPEN; 6075b81b6b3SRodney W. Grimes 6085b81b6b3SRodney W. Grimes return 0; 6095b81b6b3SRodney W. Grimes } 6105b81b6b3SRodney W. Grimes 611381fe1aaSGarrett Wollman int 6125b81b6b3SRodney W. Grimes fdclose(dev, flags) 6135b81b6b3SRodney W. Grimes dev_t dev; 614381fe1aaSGarrett Wollman int flags; 6155b81b6b3SRodney W. Grimes { 6165b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 6175b81b6b3SRodney W. Grimes fd_data[fdu].flags &= ~FD_OPEN; 6185b81b6b3SRodney W. Grimes return(0); 6195b81b6b3SRodney W. Grimes } 6205b81b6b3SRodney W. Grimes 6215b81b6b3SRodney W. Grimes 6225b81b6b3SRodney W. Grimes /***************************************************************\ 6235b81b6b3SRodney W. Grimes * fdstart * 6245b81b6b3SRodney W. Grimes * We have just queued something.. if the controller is not busy * 6255b81b6b3SRodney W. Grimes * then simulate the case where it has just finished a command * 6265b81b6b3SRodney W. Grimes * So that it (the interrupt routine) looks on the queue for more* 6275b81b6b3SRodney W. Grimes * work to do and picks up what we just added. * 6285b81b6b3SRodney W. Grimes * If the controller is already busy, we need do nothing, as it * 6295b81b6b3SRodney W. Grimes * will pick up our work when the present work completes * 6305b81b6b3SRodney W. Grimes \***************************************************************/ 631381fe1aaSGarrett Wollman static void 632f5f7ba03SJordan K. Hubbard fdstart(fdcu) 633f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 6345b81b6b3SRodney W. Grimes { 6355b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 6365b81b6b3SRodney W. Grimes int s; 6375b81b6b3SRodney W. Grimes fdu_t fdu; 6385b81b6b3SRodney W. Grimes 6395b81b6b3SRodney W. Grimes s = splbio(); 6405b81b6b3SRodney W. Grimes if(fdc_data[fdcu].state == DEVIDLE) 6415b81b6b3SRodney W. Grimes { 6425b81b6b3SRodney W. Grimes fdintr(fdcu); 6435b81b6b3SRodney W. Grimes } 6445b81b6b3SRodney W. Grimes splx(s); 6455b81b6b3SRodney W. Grimes } 6465b81b6b3SRodney W. Grimes 647381fe1aaSGarrett Wollman static void 648381fe1aaSGarrett Wollman fd_timeout(caddr_t arg1, int arg2) 6495b81b6b3SRodney W. Grimes { 650381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 6515b81b6b3SRodney W. Grimes fdu_t fdu = fdc_data[fdcu].fdu; 6525b81b6b3SRodney W. Grimes int st0, st3, cyl; 6535b81b6b3SRodney W. Grimes struct buf *dp,*bp; 654f5f7ba03SJordan K. Hubbard int s; 6555b81b6b3SRodney W. Grimes 6565b81b6b3SRodney W. Grimes dp = &fdc_data[fdcu].head; 657f5f7ba03SJordan K. Hubbard s = splbio(); 6585b81b6b3SRodney W. Grimes bp = dp->b_actf; 6595b81b6b3SRodney W. Grimes 6605b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSED); 6615b81b6b3SRodney W. Grimes out_fdc(fdcu,fd_data[fdu].hddrv); 6625b81b6b3SRodney W. Grimes st3 = in_fdc(fdcu); 6635b81b6b3SRodney W. Grimes 6645b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 6655b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 6665b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 6675b81b6b3SRodney W. Grimes printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n", 6685b81b6b3SRodney W. Grimes fdu, 6695b81b6b3SRodney W. Grimes st0, 6705b81b6b3SRodney W. Grimes NE7_ST0BITS, 6715b81b6b3SRodney W. Grimes cyl, 6725b81b6b3SRodney W. Grimes st3, 6735b81b6b3SRodney W. Grimes NE7_ST3BITS); 6745b81b6b3SRodney W. Grimes 6755b81b6b3SRodney W. Grimes if (bp) 6765b81b6b3SRodney W. Grimes { 6775b81b6b3SRodney W. Grimes retrier(fdcu); 6785b81b6b3SRodney W. Grimes fdc_data[fdcu].status[0] = 0xc0; 6795b81b6b3SRodney W. Grimes fdc_data[fdcu].state = IOTIMEDOUT; 6805b81b6b3SRodney W. Grimes if( fdc_data[fdcu].retry < 6) 6815b81b6b3SRodney W. Grimes fdc_data[fdcu].retry = 6; 6825b81b6b3SRodney W. Grimes } 6835b81b6b3SRodney W. Grimes else 6845b81b6b3SRodney W. Grimes { 6855b81b6b3SRodney W. Grimes fdc_data[fdcu].fd = (fd_p) 0; 6865b81b6b3SRodney W. Grimes fdc_data[fdcu].fdu = -1; 6875b81b6b3SRodney W. Grimes fdc_data[fdcu].state = DEVIDLE; 6885b81b6b3SRodney W. Grimes } 689f5f7ba03SJordan K. Hubbard fdintr(fdcu); 690f5f7ba03SJordan K. Hubbard splx(s); 6915b81b6b3SRodney W. Grimes } 6925b81b6b3SRodney W. Grimes 6935b81b6b3SRodney W. Grimes /* just ensure it has the right spl */ 694381fe1aaSGarrett Wollman static void 695381fe1aaSGarrett Wollman fd_pseudointr(caddr_t arg1, int arg2) 6965b81b6b3SRodney W. Grimes { 697381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 6985b81b6b3SRodney W. Grimes int s; 6995b81b6b3SRodney W. Grimes s = splbio(); 7005b81b6b3SRodney W. Grimes fdintr(fdcu); 7015b81b6b3SRodney W. Grimes splx(s); 7025b81b6b3SRodney W. Grimes } 7035b81b6b3SRodney W. Grimes 7045b81b6b3SRodney W. Grimes /***********************************************************************\ 7055b81b6b3SRodney W. Grimes * fdintr * 7065b81b6b3SRodney W. Grimes * keep calling the state machine until it returns a 0 * 7075b81b6b3SRodney W. Grimes * ALWAYS called at SPLBIO * 7085b81b6b3SRodney W. Grimes \***********************************************************************/ 709381fe1aaSGarrett Wollman void 710381fe1aaSGarrett Wollman fdintr(fdcu_t fdcu) 7115b81b6b3SRodney W. Grimes { 7125b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 713381fe1aaSGarrett Wollman while(fdstate(fdcu, fdc)) 714381fe1aaSGarrett Wollman ; 7155b81b6b3SRodney W. Grimes } 7165b81b6b3SRodney W. Grimes 7175b81b6b3SRodney W. Grimes /***********************************************************************\ 7185b81b6b3SRodney W. Grimes * The controller state machine. * 7195b81b6b3SRodney W. Grimes * if it returns a non zero value, it should be called again immediatly * 7205b81b6b3SRodney W. Grimes \***********************************************************************/ 721381fe1aaSGarrett Wollman int 722381fe1aaSGarrett Wollman fdstate(fdcu, fdc) 723f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 724f5f7ba03SJordan K. Hubbard fdc_p fdc; 7255b81b6b3SRodney W. Grimes { 726b39c878eSAndrey A. Chernov int read, format, head, trac, sec = 0, i = 0, s, sectrac, cyl, st0; 7275b81b6b3SRodney W. Grimes unsigned long blknum; 7285b81b6b3SRodney W. Grimes fdu_t fdu = fdc->fdu; 7295b81b6b3SRodney W. Grimes fd_p fd; 7305b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 731b39c878eSAndrey A. Chernov struct fd_formb *finfo = NULL; 7325b81b6b3SRodney W. Grimes 7335b81b6b3SRodney W. Grimes dp = &(fdc->head); 7345b81b6b3SRodney W. Grimes bp = dp->b_actf; 7355b81b6b3SRodney W. Grimes if(!bp) 7365b81b6b3SRodney W. Grimes { 7375b81b6b3SRodney W. Grimes /***********************************************\ 7385b81b6b3SRodney W. Grimes * nothing left for this controller to do * 7395b81b6b3SRodney W. Grimes * Force into the IDLE state, * 7405b81b6b3SRodney W. Grimes \***********************************************/ 7415b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 7425b81b6b3SRodney W. Grimes if(fdc->fd) 7435b81b6b3SRodney W. Grimes { 7445b81b6b3SRodney W. Grimes printf("unexpected valid fd pointer (fdu = %d)\n" 7455b81b6b3SRodney W. Grimes ,fdc->fdu); 7465b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 7475b81b6b3SRodney W. Grimes fdc->fdu = -1; 7485b81b6b3SRodney W. Grimes } 7495b81b6b3SRodney W. Grimes TRACE1("[fdc%d IDLE]",fdcu); 7505b81b6b3SRodney W. Grimes return(0); 7515b81b6b3SRodney W. Grimes } 7525b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 7535b81b6b3SRodney W. Grimes fd = fd_data + fdu; 7545b81b6b3SRodney W. Grimes if (fdc->fd && (fd != fdc->fd)) 7555b81b6b3SRodney W. Grimes { 7565b81b6b3SRodney W. Grimes printf("confused fd pointers\n"); 7575b81b6b3SRodney W. Grimes } 7585b81b6b3SRodney W. Grimes read = bp->b_flags & B_READ; 759b39c878eSAndrey A. Chernov format = bp->b_flags & B_FORMAT; 760b39c878eSAndrey A. Chernov if(format) 761b39c878eSAndrey A. Chernov finfo = (struct fd_formb *)bp->b_un.b_addr; 7625b81b6b3SRodney W. Grimes TRACE1("fd%d",fdu); 7635b81b6b3SRodney W. Grimes TRACE1("[%s]",fdstates[fdc->state]); 7645b81b6b3SRodney W. Grimes TRACE1("(0x%x)",fd->flags); 7655b81b6b3SRodney W. Grimes untimeout(fd_turnoff, fdu); 766381fe1aaSGarrett Wollman timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); 7675b81b6b3SRodney W. Grimes switch (fdc->state) 7685b81b6b3SRodney W. Grimes { 7695b81b6b3SRodney W. Grimes case DEVIDLE: 7705b81b6b3SRodney W. Grimes case FINDWORK: /* we have found new work */ 7715b81b6b3SRodney W. Grimes fdc->retry = 0; 7725b81b6b3SRodney W. Grimes fd->skip = 0; 7735b81b6b3SRodney W. Grimes fdc->fd = fd; 7745b81b6b3SRodney W. Grimes fdc->fdu = fdu; 7755b81b6b3SRodney W. Grimes /*******************************************************\ 7765b81b6b3SRodney W. Grimes * If the next drive has a motor startup pending, then * 7775b81b6b3SRodney W. Grimes * it will start up in it's own good time * 7785b81b6b3SRodney W. Grimes \*******************************************************/ 7795b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 7805b81b6b3SRodney W. Grimes { 7815b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 7825b81b6b3SRodney W. Grimes return(0); /* come back later */ 7835b81b6b3SRodney W. Grimes } 7845b81b6b3SRodney W. Grimes /*******************************************************\ 7855b81b6b3SRodney W. Grimes * Maybe if it's not starting, it SHOULD be starting * 7865b81b6b3SRodney W. Grimes \*******************************************************/ 7875b81b6b3SRodney W. Grimes if (!(fd->flags & FD_MOTOR)) 7885b81b6b3SRodney W. Grimes { 7895b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 7905b81b6b3SRodney W. Grimes fd_turnon(fdu); 7915b81b6b3SRodney W. Grimes return(0); 7925b81b6b3SRodney W. Grimes } 7935b81b6b3SRodney W. Grimes else /* at least make sure we are selected */ 7945b81b6b3SRodney W. Grimes { 7955b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 7965b81b6b3SRodney W. Grimes } 7975b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 7985b81b6b3SRodney W. Grimes break; 7995b81b6b3SRodney W. Grimes case DOSEEK: 8005b81b6b3SRodney W. Grimes if (bp->b_cylin == fd->track) 8015b81b6b3SRodney W. Grimes { 8025b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8035b81b6b3SRodney W. Grimes break; 8045b81b6b3SRodney W. Grimes } 8055b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SEEK); /* Seek function */ 8065b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); /* Drive number */ 8075b81b6b3SRodney W. Grimes out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac); 8085b81b6b3SRodney W. Grimes fd->track = -2; 8095b81b6b3SRodney W. Grimes fdc->state = SEEKWAIT; 810381fe1aaSGarrett Wollman timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 8115b81b6b3SRodney W. Grimes return(0); /* will return later */ 8125b81b6b3SRodney W. Grimes case SEEKWAIT: 813f5f7ba03SJordan K. Hubbard untimeout(fd_timeout,fdcu); 8145b81b6b3SRodney W. Grimes /* allow heads to settle */ 815381fe1aaSGarrett Wollman timeout(fd_pseudointr, (caddr_t)fdcu, hz / 50); 8165b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8175b81b6b3SRodney W. Grimes return(0); /* will return later */ 8185b81b6b3SRodney W. Grimes break; 8195b81b6b3SRodney W. Grimes 8205b81b6b3SRodney W. Grimes case SEEKCOMPLETE : /* SEEK DONE, START DMA */ 8215b81b6b3SRodney W. Grimes /* Make sure seek really happened*/ 8225b81b6b3SRodney W. Grimes if(fd->track == -2) 8235b81b6b3SRodney W. Grimes { 8245b81b6b3SRodney W. Grimes int descyl = bp->b_cylin * fd->ft->steptrac; 8255b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 8265b81b6b3SRodney W. Grimes i = in_fdc(fdcu); 8275b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 8285b81b6b3SRodney W. Grimes if (cyl != descyl) 8295b81b6b3SRodney W. Grimes { 8305b81b6b3SRodney W. Grimes printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu, 8315b81b6b3SRodney W. Grimes descyl, cyl, i, NE7_ST0BITS); 8325b81b6b3SRodney W. Grimes return(retrier(fdcu)); 8335b81b6b3SRodney W. Grimes } 8345b81b6b3SRodney W. Grimes } 8355b81b6b3SRodney W. Grimes 8365b81b6b3SRodney W. Grimes fd->track = bp->b_cylin; 837b39c878eSAndrey A. Chernov if(format) 838b39c878eSAndrey A. Chernov fd->skip = (char *)&(finfo->fd_formb_cylno(0)) 839b39c878eSAndrey A. Chernov - (char *)finfo; 8405b81b6b3SRodney W. Grimes isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip, 841b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 8425b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 8435b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 8445b81b6b3SRodney W. Grimes sectrac = fd->ft->sectrac; 8455b81b6b3SRodney W. Grimes sec = blknum % (sectrac * fd->ft->heads); 8465b81b6b3SRodney W. Grimes head = sec / sectrac; 8475b81b6b3SRodney W. Grimes sec = sec % sectrac + 1; 8485b81b6b3SRodney W. Grimes /*XXX*/ fd->hddrv = ((head&1)<<2)+fdu; 8495b81b6b3SRodney W. Grimes 850b39c878eSAndrey A. Chernov if(format) 851b39c878eSAndrey A. Chernov { 852b39c878eSAndrey A. Chernov /* formatting */ 853b39c878eSAndrey A. Chernov out_fdc(fdcu,/* NE7CMD_FORMAT */ 0x4d); 854b39c878eSAndrey A. Chernov out_fdc(fdcu,head << 2 | fdu); 855b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_secshift); 856b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_nsecs); 857b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_gaplen); 858b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_fillbyte); 859b39c878eSAndrey A. Chernov } 860b39c878eSAndrey A. Chernov else 861b39c878eSAndrey A. Chernov { 8625b81b6b3SRodney W. Grimes if (read) 8635b81b6b3SRodney W. Grimes { 8645b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_READ); /* READ */ 8655b81b6b3SRodney W. Grimes } 8665b81b6b3SRodney W. Grimes else 8675b81b6b3SRodney W. Grimes { 8685b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_WRITE); /* WRITE */ 8695b81b6b3SRodney W. Grimes } 8705b81b6b3SRodney W. Grimes out_fdc(fdcu,head << 2 | fdu); /* head & unit */ 8715b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->track); /* track */ 8725b81b6b3SRodney W. Grimes out_fdc(fdcu,head); 8735b81b6b3SRodney W. Grimes out_fdc(fdcu,sec); /* sector XXX +1? */ 8745b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->secsize); /* sector size */ 8755b81b6b3SRodney W. Grimes out_fdc(fdcu,sectrac); /* sectors/track */ 876ed2fa05eSAndrey A. Chernov #if 0 8775b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->gap); /* gap size */ 878ed2fa05eSAndrey A. Chernov #endif 879ed2fa05eSAndrey A. Chernov out_fdc(fdcu,2); /* always use gap 2 for read/write */ 8805b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->datalen); /* data length */ 881b39c878eSAndrey A. Chernov } 8825b81b6b3SRodney W. Grimes fdc->state = IOCOMPLETE; 883381fe1aaSGarrett Wollman timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 8845b81b6b3SRodney W. Grimes return(0); /* will return later */ 8855b81b6b3SRodney W. Grimes case IOCOMPLETE: /* IO DONE, post-analyze */ 8865b81b6b3SRodney W. Grimes untimeout(fd_timeout,fdcu); 8875b81b6b3SRodney W. Grimes for(i=0;i<7;i++) 8885b81b6b3SRodney W. Grimes { 8895b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 8905b81b6b3SRodney W. Grimes } 8915b81b6b3SRodney W. Grimes case IOTIMEDOUT: /*XXX*/ 8925b81b6b3SRodney W. Grimes isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, 893b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 8945b81b6b3SRodney W. Grimes if (fdc->status[0]&0xF8) 8955b81b6b3SRodney W. Grimes { 896b39c878eSAndrey A. Chernov if (fdc->status[1] & 0x10) { 897b39c878eSAndrey A. Chernov /* 898b39c878eSAndrey A. Chernov * Operation not completed in reasonable time. 899b39c878eSAndrey A. Chernov * Just restart it, don't increment retry count. 900b39c878eSAndrey A. Chernov * (vak) 901b39c878eSAndrey A. Chernov */ 902b39c878eSAndrey A. Chernov fdc->state = SEEKCOMPLETE; 903b39c878eSAndrey A. Chernov return (1); 904b39c878eSAndrey A. Chernov } 9055b81b6b3SRodney W. Grimes return(retrier(fdcu)); 9065b81b6b3SRodney W. Grimes } 9075b81b6b3SRodney W. Grimes /* All OK */ 9085b81b6b3SRodney W. Grimes fd->skip += FDBLK; 909b39c878eSAndrey A. Chernov if (!format && fd->skip < bp->b_bcount) 9105b81b6b3SRodney W. Grimes { 9115b81b6b3SRodney W. Grimes /* set up next transfer */ 9125b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 9135b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 9145b81b6b3SRodney W. Grimes bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads)); 9155b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9165b81b6b3SRodney W. Grimes } 9175b81b6b3SRodney W. Grimes else 9185b81b6b3SRodney W. Grimes { 9195b81b6b3SRodney W. Grimes /* ALL DONE */ 9205b81b6b3SRodney W. Grimes fd->skip = 0; 9215b81b6b3SRodney W. Grimes bp->b_resid = 0; 9225b81b6b3SRodney W. Grimes dp->b_actf = bp->av_forw; 9235b81b6b3SRodney W. Grimes biodone(bp); 9245b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 9255b81b6b3SRodney W. Grimes fdc->fdu = -1; 9265b81b6b3SRodney W. Grimes fdc->state = FINDWORK; 9275b81b6b3SRodney W. Grimes } 9285b81b6b3SRodney W. Grimes return(1); 9295b81b6b3SRodney W. Grimes case RESETCTLR: 9305b81b6b3SRodney W. Grimes /* Try a reset, keep motor on */ 9315b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,1); 9325b81b6b3SRodney W. Grimes DELAY(100); 9335b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 9345b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,fd->ft->trans); 9355b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdctl]",fd->ft->trans); 9365b81b6b3SRodney W. Grimes fdc->retry++; 9375b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 9385b81b6b3SRodney W. Grimes break; 9395b81b6b3SRodney W. Grimes case STARTRECAL: 9405b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */ 9415b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 9425b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 9435b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 9445b81b6b3SRodney W. Grimes out_fdc(fdcu,fdu); 9455b81b6b3SRodney W. Grimes fdc->state = RECALWAIT; 9465b81b6b3SRodney W. Grimes return(0); /* will return later */ 9475b81b6b3SRodney W. Grimes case RECALWAIT: 9485b81b6b3SRodney W. Grimes /* allow heads to settle */ 949381fe1aaSGarrett Wollman timeout(fd_pseudointr, (caddr_t)fdcu, hz / 30); 9505b81b6b3SRodney W. Grimes fdc->state = RECALCOMPLETE; 9515b81b6b3SRodney W. Grimes return(0); /* will return later */ 9525b81b6b3SRodney W. Grimes case RECALCOMPLETE: 9535b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 9545b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 9555b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 9565b81b6b3SRodney W. Grimes if (cyl != 0) 9575b81b6b3SRodney W. Grimes { 9585b81b6b3SRodney W. Grimes printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, 9595b81b6b3SRodney W. Grimes st0, NE7_ST0BITS, cyl); 9605b81b6b3SRodney W. Grimes return(retrier(fdcu)); 9615b81b6b3SRodney W. Grimes } 9625b81b6b3SRodney W. Grimes fd->track = 0; 9635b81b6b3SRodney W. Grimes /* Seek (probably) necessary */ 9645b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9655b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 9665b81b6b3SRodney W. Grimes case MOTORWAIT: 9675b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 9685b81b6b3SRodney W. Grimes { 9695b81b6b3SRodney W. Grimes return(0); /* time's not up yet */ 9705b81b6b3SRodney W. Grimes } 9715b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9725b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 9735b81b6b3SRodney W. Grimes default: 9745b81b6b3SRodney W. Grimes printf("Unexpected FD int->"); 9755b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 9765b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 9775b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 9785b81b6b3SRodney W. Grimes printf("ST0 = %lx, PCN = %lx\n",i,sec); 9795b81b6b3SRodney W. Grimes out_fdc(fdcu,0x4A); 9805b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); 9815b81b6b3SRodney W. Grimes for(i=0;i<7;i++) { 9825b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 9835b81b6b3SRodney W. Grimes } 9845b81b6b3SRodney W. Grimes printf("intr status :%lx %lx %lx %lx %lx %lx %lx ", 9855b81b6b3SRodney W. Grimes fdc->status[0], 9865b81b6b3SRodney W. Grimes fdc->status[1], 9875b81b6b3SRodney W. Grimes fdc->status[2], 9885b81b6b3SRodney W. Grimes fdc->status[3], 9895b81b6b3SRodney W. Grimes fdc->status[4], 9905b81b6b3SRodney W. Grimes fdc->status[5], 9915b81b6b3SRodney W. Grimes fdc->status[6] ); 9925b81b6b3SRodney W. Grimes return(0); 9935b81b6b3SRodney W. Grimes } 9945b81b6b3SRodney W. Grimes return(1); /* Come back immediatly to new state */ 9955b81b6b3SRodney W. Grimes } 9965b81b6b3SRodney W. Grimes 997381fe1aaSGarrett Wollman int 998f5f7ba03SJordan K. Hubbard retrier(fdcu) 999f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 10005b81b6b3SRodney W. Grimes { 10015b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 10025b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 10035b81b6b3SRodney W. Grimes 10045b81b6b3SRodney W. Grimes dp = &(fdc->head); 10055b81b6b3SRodney W. Grimes bp = dp->b_actf; 10065b81b6b3SRodney W. Grimes 10075b81b6b3SRodney W. Grimes switch(fdc->retry) 10085b81b6b3SRodney W. Grimes { 10095b81b6b3SRodney W. Grimes case 0: case 1: case 2: 10105b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 10115b81b6b3SRodney W. Grimes break; 10125b81b6b3SRodney W. Grimes case 3: case 4: case 5: 10135b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 10145b81b6b3SRodney W. Grimes break; 10155b81b6b3SRodney W. Grimes case 6: 10165b81b6b3SRodney W. Grimes fdc->state = RESETCTLR; 10175b81b6b3SRodney W. Grimes break; 10185b81b6b3SRodney W. Grimes case 7: 10195b81b6b3SRodney W. Grimes break; 10205b81b6b3SRodney W. Grimes default: 10215b81b6b3SRodney W. Grimes { 10227ca0641bSAndrey A. Chernov dev_t sav_b_dev = bp->b_dev; 10237ca0641bSAndrey A. Chernov /* Trick diskerr */ 10247ca0641bSAndrey A. Chernov bp->b_dev = makedev(major(bp->b_dev), (FDUNIT(minor(bp->b_dev))<<3)|3); 102592ed385aSRodney W. Grimes diskerr(bp, "fd", "hard error", LOG_PRINTF, 102692ed385aSRodney W. Grimes fdc->fd->skip, (struct disklabel *)NULL); 10277ca0641bSAndrey A. Chernov bp->b_dev = sav_b_dev; 102892ed385aSRodney W. Grimes printf(" (ST0 %b ", fdc->status[0], NE7_ST0BITS); 10295b81b6b3SRodney W. Grimes printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS); 10305b81b6b3SRodney W. Grimes printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS); 10315b81b6b3SRodney W. Grimes printf("cyl %d hd %d sec %d)\n", 103292ed385aSRodney W. Grimes fdc->status[3], fdc->status[4], fdc->status[5]); 10335b81b6b3SRodney W. Grimes } 10345b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 10355b81b6b3SRodney W. Grimes bp->b_error = EIO; 10365b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount - fdc->fd->skip; 10375b81b6b3SRodney W. Grimes dp->b_actf = bp->av_forw; 10385b81b6b3SRodney W. Grimes fdc->fd->skip = 0; 10395b81b6b3SRodney W. Grimes biodone(bp); 104092ed385aSRodney W. Grimes fdc->state = FINDWORK; 10415b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 10425b81b6b3SRodney W. Grimes fdc->fdu = -1; 1043f5f7ba03SJordan K. Hubbard /* XXX abort current command, if any. */ 104492ed385aSRodney W. Grimes return(1); 10455b81b6b3SRodney W. Grimes } 10465b81b6b3SRodney W. Grimes fdc->retry++; 10475b81b6b3SRodney W. Grimes return(1); 10485b81b6b3SRodney W. Grimes } 10495b81b6b3SRodney W. Grimes 1050b39c878eSAndrey A. Chernov static int 1051b39c878eSAndrey A. Chernov fdformat(dev, finfo, p) 1052b39c878eSAndrey A. Chernov dev_t dev; 1053b39c878eSAndrey A. Chernov struct fd_formb *finfo; 1054b39c878eSAndrey A. Chernov struct proc *p; 1055b39c878eSAndrey A. Chernov { 1056b39c878eSAndrey A. Chernov fdu_t fdu; 1057b39c878eSAndrey A. Chernov fd_p fd; 1058b39c878eSAndrey A. Chernov 1059b39c878eSAndrey A. Chernov struct buf *bp; 1060b39c878eSAndrey A. Chernov int rv = 0, s; 1061b39c878eSAndrey A. Chernov 1062b39c878eSAndrey A. Chernov fdu = FDUNIT(minor(dev)); 1063b39c878eSAndrey A. Chernov fd = &fd_data[fdu]; 1064b39c878eSAndrey A. Chernov 1065b39c878eSAndrey A. Chernov /* set up a buffer header for fdstrategy() */ 1066b39c878eSAndrey A. Chernov bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 1067b39c878eSAndrey A. Chernov if(bp == 0) 1068b39c878eSAndrey A. Chernov return ENOBUFS; 1069b39c878eSAndrey A. Chernov bzero((void *)bp, sizeof(struct buf)); 1070b39c878eSAndrey A. Chernov bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 1071b39c878eSAndrey A. Chernov bp->b_proc = p; 1072b39c878eSAndrey A. Chernov bp->b_dev = dev; 1073b39c878eSAndrey A. Chernov 1074b39c878eSAndrey A. Chernov /* 1075b39c878eSAndrey A. Chernov * calculate a fake blkno, so fdstrategy() would initiate a 1076b39c878eSAndrey A. Chernov * seek to the requested cylinder 1077b39c878eSAndrey A. Chernov */ 1078b39c878eSAndrey A. Chernov bp->b_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) 1079b39c878eSAndrey A. Chernov + finfo->head * fd->ft->sectrac) * FDBLK / DEV_BSIZE; 1080b39c878eSAndrey A. Chernov 1081b39c878eSAndrey A. Chernov bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 1082b39c878eSAndrey A. Chernov bp->b_un.b_addr = (caddr_t)finfo; 1083b39c878eSAndrey A. Chernov 1084b39c878eSAndrey A. Chernov /* now do the format */ 1085b39c878eSAndrey A. Chernov fdstrategy(bp); 1086b39c878eSAndrey A. Chernov 1087b39c878eSAndrey A. Chernov /* ...and wait for it to complete */ 1088b39c878eSAndrey A. Chernov s = splbio(); 1089b39c878eSAndrey A. Chernov while(!(bp->b_flags & B_DONE)) 1090b39c878eSAndrey A. Chernov { 1091b39c878eSAndrey A. Chernov rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 1092b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1093b39c878eSAndrey A. Chernov break; 1094b39c878eSAndrey A. Chernov } 1095b39c878eSAndrey A. Chernov splx(s); 1096b39c878eSAndrey A. Chernov 1097b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1098b39c878eSAndrey A. Chernov { 1099b39c878eSAndrey A. Chernov /* timed out */ 1100b39c878eSAndrey A. Chernov biodone(bp); 1101b39c878eSAndrey A. Chernov rv = EIO; 1102b39c878eSAndrey A. Chernov } 1103b39c878eSAndrey A. Chernov free(bp, M_TEMP); 1104b39c878eSAndrey A. Chernov return rv; 1105b39c878eSAndrey A. Chernov } 1106b39c878eSAndrey A. Chernov 1107f5f7ba03SJordan K. Hubbard /* 1108f5f7ba03SJordan K. Hubbard * fdioctl() from jc@irbs.UUCP (John Capo) 1109f5f7ba03SJordan K. Hubbard * i386/i386/conf.c needs to have fdioctl() declared and remove the line that 1110f5f7ba03SJordan K. Hubbard * defines fdioctl to be enxio. 1111f5f7ba03SJordan K. Hubbard * 1112f5f7ba03SJordan K. Hubbard * TODO: Reformat. 1113f5f7ba03SJordan K. Hubbard * Think about allocating buffer off stack. 1114f5f7ba03SJordan K. Hubbard * Don't pass uncast 0's and NULL's to read/write/setdisklabel(). 1115f5f7ba03SJordan K. Hubbard * Watch out for NetBSD's different *disklabel() interface. 1116b39c878eSAndrey A. Chernov * 1117b39c878eSAndrey A. Chernov * Added functionality for floppy formatting 1118b39c878eSAndrey A. Chernov * joerg_wunsch@uriah.sax.de (Joerg Wunsch) 1119f5f7ba03SJordan K. Hubbard */ 11205b81b6b3SRodney W. Grimes 1121f5f7ba03SJordan K. Hubbard int 1122b39c878eSAndrey A. Chernov fdioctl (dev, cmd, addr, flag, p) 1123f5f7ba03SJordan K. Hubbard dev_t dev; 1124f5f7ba03SJordan K. Hubbard int cmd; 1125f5f7ba03SJordan K. Hubbard caddr_t addr; 1126f5f7ba03SJordan K. Hubbard int flag; 1127b39c878eSAndrey A. Chernov struct proc *p; 1128f5f7ba03SJordan K. Hubbard { 1129f5f7ba03SJordan K. Hubbard struct fd_type *fdt; 1130f5f7ba03SJordan K. Hubbard struct disklabel *dl; 1131f5f7ba03SJordan K. Hubbard char buffer[DEV_BSIZE]; 1132f5f7ba03SJordan K. Hubbard int error; 1133f5f7ba03SJordan K. Hubbard 1134f5f7ba03SJordan K. Hubbard error = 0; 1135f5f7ba03SJordan K. Hubbard 1136f5f7ba03SJordan K. Hubbard switch (cmd) 1137f5f7ba03SJordan K. Hubbard { 1138f5f7ba03SJordan K. Hubbard case DIOCGDINFO: 1139f5f7ba03SJordan K. Hubbard bzero(buffer, sizeof (buffer)); 1140f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)buffer; 1141f5f7ba03SJordan K. Hubbard dl->d_secsize = FDBLK; 114292ed385aSRodney W. Grimes fdt = fd_data[FDUNIT(minor(dev))].ft; 1143f5f7ba03SJordan K. Hubbard dl->d_secpercyl = fdt->size / fdt->tracks; 1144f5f7ba03SJordan K. Hubbard dl->d_type = DTYPE_FLOPPY; 1145f5f7ba03SJordan K. Hubbard 1146f5f7ba03SJordan K. Hubbard if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) 1147f5f7ba03SJordan K. Hubbard error = 0; 1148f5f7ba03SJordan K. Hubbard else 1149f5f7ba03SJordan K. Hubbard error = EINVAL; 1150f5f7ba03SJordan K. Hubbard 1151f5f7ba03SJordan K. Hubbard *(struct disklabel *)addr = *dl; 1152f5f7ba03SJordan K. Hubbard break; 1153f5f7ba03SJordan K. Hubbard 1154f5f7ba03SJordan K. Hubbard case DIOCSDINFO: 1155f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1156f5f7ba03SJordan K. Hubbard error = EBADF; 1157f5f7ba03SJordan K. Hubbard break; 1158f5f7ba03SJordan K. Hubbard 1159f5f7ba03SJordan K. Hubbard case DIOCWLABEL: 1160f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1161f5f7ba03SJordan K. Hubbard error = EBADF; 1162f5f7ba03SJordan K. Hubbard break; 1163f5f7ba03SJordan K. Hubbard 1164f5f7ba03SJordan K. Hubbard case DIOCWDINFO: 1165f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1166f5f7ba03SJordan K. Hubbard { 1167f5f7ba03SJordan K. Hubbard error = EBADF; 1168f5f7ba03SJordan K. Hubbard break; 1169f5f7ba03SJordan K. Hubbard } 1170f5f7ba03SJordan K. Hubbard 1171f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)addr; 1172f5f7ba03SJordan K. Hubbard 1173b39c878eSAndrey A. Chernov if (error = setdisklabel ((struct disklabel *)buffer, 1174b39c878eSAndrey A. Chernov dl, 0, NULL)) 1175f5f7ba03SJordan K. Hubbard break; 1176f5f7ba03SJordan K. Hubbard 1177b39c878eSAndrey A. Chernov error = writedisklabel(dev, fdstrategy, 1178b39c878eSAndrey A. Chernov (struct disklabel *)buffer, NULL); 1179b39c878eSAndrey A. Chernov break; 1180b39c878eSAndrey A. Chernov 1181b39c878eSAndrey A. Chernov case FD_FORM: 1182b39c878eSAndrey A. Chernov if((flag & FWRITE) == 0) 1183b39c878eSAndrey A. Chernov error = EBADF; /* must be opened for writing */ 1184b39c878eSAndrey A. Chernov else if(((struct fd_formb *)addr)->format_version != 1185b39c878eSAndrey A. Chernov FD_FORMAT_VERSION) 1186b39c878eSAndrey A. Chernov error = EINVAL; /* wrong version of formatting prog */ 1187b39c878eSAndrey A. Chernov else 1188b39c878eSAndrey A. Chernov error = fdformat(dev, (struct fd_formb *)addr, p); 1189b39c878eSAndrey A. Chernov break; 1190b39c878eSAndrey A. Chernov 1191b39c878eSAndrey A. Chernov case FD_GTYPE: /* get drive type */ 1192b39c878eSAndrey A. Chernov *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft; 1193f5f7ba03SJordan K. Hubbard break; 1194f5f7ba03SJordan K. Hubbard 1195f5f7ba03SJordan K. Hubbard default: 1196f5f7ba03SJordan K. Hubbard error = EINVAL; 1197f5f7ba03SJordan K. Hubbard break; 1198f5f7ba03SJordan K. Hubbard } 1199f5f7ba03SJordan K. Hubbard return (error); 1200f5f7ba03SJordan K. Hubbard } 1201f5f7ba03SJordan K. Hubbard 1202f5f7ba03SJordan K. Hubbard #endif 1203