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 38126518a1SAndrey A. Chernov * $Id: fd.c,v 1.17 1993/12/19 00:50:33 wollman 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 { 97126518a1SAndrey A. Chernov { 21,2,0xFF,0x04,82,3444,1,FDC_500KBPS,2,0x0C,2 }, /* 1.72M in HD 3.5in */ 98126518a1SAndrey A. Chernov { 18,2,0xFF,0x1B,82,2952,1,FDC_500KBPS,2,0x6C,1 }, /* 1.48M in HD 3.5in */ 99126518a1SAndrey A. Chernov { 18,2,0xFF,0x1B,80,2880,1,FDC_500KBPS,2,0x6C,1 }, /* 1.44M in HD 3.5in */ 100126518a1SAndrey A. Chernov { 15,2,0xFF,0x1B,80,2400,1,FDC_500KBPS,2,0x54,1 }, /* 1.2M in HD 5.25/3.5 */ 101126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,82,1640,1,FDC_250KBPS,2,0x2E,1 }, /* 820K in HD 3.5in */ 102126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,80,1600,1,FDC_250KBPS,2,0x2E,1 }, /* 800K in HD 3.5in */ 103126518a1SAndrey A. Chernov { 9,2,0xFF,0x20,80,1440,1,FDC_250KBPS,2,0x50,1 }, /* 720K in HD 3.5in */ 104126518a1SAndrey A. Chernov { 9,2,0xFF,0x2A,40, 720,1,FDC_300KBPS,2,0x50,1 }, /* 360K in DD 5.25in */ 105ed2fa05eSAndrey A. Chernov 106126518a1SAndrey A. Chernov { 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,0x02,2 }, /* 1.48M in HD 5.25in */ 107126518a1SAndrey A. Chernov { 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,0x02,2 }, /* 1.44M in HD 5.25in */ 108126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,82,1640,1,FDC_300KBPS,2,0x2E,1 }, /* 820K in HD 5.25in */ 109126518a1SAndrey A. Chernov { 10,2,0xFF,0x10,80,1600,1,FDC_300KBPS,2,0x2E,1 }, /* 800K in HD 5.25in */ 110126518a1SAndrey A. Chernov { 9,2,0xFF,0x20,80,1440,1,FDC_300KBPS,2,0x50,1 }, /* 720K in HD 5.25in */ 111126518a1SAndrey A. Chernov { 9,2,0xFF,0x23,40, 720,2,FDC_300KBPS,2,0x50,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 168aaf08d94SGarrett Wollman static int retrier(fdcu_t); 169aaf08d94SGarrett Wollman 1705b81b6b3SRodney W. Grimes #define DEVIDLE 0 1715b81b6b3SRodney W. Grimes #define FINDWORK 1 1725b81b6b3SRodney W. Grimes #define DOSEEK 2 1735b81b6b3SRodney W. Grimes #define SEEKCOMPLETE 3 1745b81b6b3SRodney W. Grimes #define IOCOMPLETE 4 1755b81b6b3SRodney W. Grimes #define RECALCOMPLETE 5 1765b81b6b3SRodney W. Grimes #define STARTRECAL 6 1775b81b6b3SRodney W. Grimes #define RESETCTLR 7 1785b81b6b3SRodney W. Grimes #define SEEKWAIT 8 1795b81b6b3SRodney W. Grimes #define RECALWAIT 9 1805b81b6b3SRodney W. Grimes #define MOTORWAIT 10 1815b81b6b3SRodney W. Grimes #define IOTIMEDOUT 11 1825b81b6b3SRodney W. Grimes 1835b81b6b3SRodney W. Grimes #ifdef DEBUG 1845b81b6b3SRodney W. Grimes char *fdstates[] = 1855b81b6b3SRodney W. Grimes { 1865b81b6b3SRodney W. Grimes "DEVIDLE", 1875b81b6b3SRodney W. Grimes "FINDWORK", 1885b81b6b3SRodney W. Grimes "DOSEEK", 1895b81b6b3SRodney W. Grimes "SEEKCOMPLETE", 1905b81b6b3SRodney W. Grimes "IOCOMPLETE", 1915b81b6b3SRodney W. Grimes "RECALCOMPLETE", 1925b81b6b3SRodney W. Grimes "STARTRECAL", 1935b81b6b3SRodney W. Grimes "RESETCTLR", 1945b81b6b3SRodney W. Grimes "SEEKWAIT", 1955b81b6b3SRodney W. Grimes "RECALWAIT", 1965b81b6b3SRodney W. Grimes "MOTORWAIT", 1975b81b6b3SRodney W. Grimes "IOTIMEDOUT" 1985b81b6b3SRodney W. Grimes }; 1995b81b6b3SRodney W. Grimes 2005b81b6b3SRodney W. Grimes 2015b81b6b3SRodney W. Grimes int fd_debug = 1; 2025b81b6b3SRodney W. Grimes #define TRACE0(arg) if(fd_debug) printf(arg) 2035b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2) 204381fe1aaSGarrett Wollman #else /* DEBUG */ 2055b81b6b3SRodney W. Grimes #define TRACE0(arg) 2065b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) 207381fe1aaSGarrett Wollman #endif /* DEBUG */ 2085b81b6b3SRodney W. Grimes 209381fe1aaSGarrett Wollman static void fdstart(fdcu_t); 210381fe1aaSGarrett Wollman void fdintr(fdcu_t); 211381fe1aaSGarrett Wollman static void fd_turnoff(caddr_t, int); 2125b81b6b3SRodney W. Grimes 2135b81b6b3SRodney W. Grimes /****************************************************************************/ 2145b81b6b3SRodney W. Grimes /* autoconfiguration stuff */ 2155b81b6b3SRodney W. Grimes /****************************************************************************/ 216381fe1aaSGarrett Wollman static int fdprobe(struct isa_device *); 217381fe1aaSGarrett Wollman static int fdattach(struct isa_device *); 2185b81b6b3SRodney W. Grimes 2195b81b6b3SRodney W. Grimes struct isa_driver fddriver = { 2205b81b6b3SRodney W. Grimes fdprobe, fdattach, "fd", 2215b81b6b3SRodney W. Grimes }; 2225b81b6b3SRodney W. Grimes 2235b81b6b3SRodney W. Grimes /* 2245b81b6b3SRodney W. Grimes * probe for existance of controller 2255b81b6b3SRodney W. Grimes */ 226381fe1aaSGarrett Wollman int 2275b81b6b3SRodney W. Grimes fdprobe(dev) 2285b81b6b3SRodney W. Grimes struct isa_device *dev; 2295b81b6b3SRodney W. Grimes { 2305b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2315b81b6b3SRodney W. Grimes if(fdc_data[fdcu].flags & FDC_ATTACHED) 2325b81b6b3SRodney W. Grimes { 2335b81b6b3SRodney W. Grimes printf("fdc: same unit (%d) used multiple times\n",fdcu); 2345b81b6b3SRodney W. Grimes return 0; 2355b81b6b3SRodney W. Grimes } 2365b81b6b3SRodney W. Grimes 2375b81b6b3SRodney W. Grimes fdc_data[fdcu].baseport = dev->id_iobase; 2385b81b6b3SRodney W. Grimes 23916111cedSAndrew Moore /* First - lets reset the floppy controller */ 24016111cedSAndrew Moore 24116111cedSAndrew Moore outb(dev->id_iobase+fdout,0); 24216111cedSAndrew Moore DELAY(100); 24316111cedSAndrew Moore outb(dev->id_iobase+fdout,FDO_FRST); 24416111cedSAndrew Moore 2455b81b6b3SRodney W. Grimes /* see if it can handle a command */ 2465b81b6b3SRodney W. Grimes if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0) 2475b81b6b3SRodney W. Grimes { 2485b81b6b3SRodney W. Grimes return(0); 2495b81b6b3SRodney W. Grimes } 2505b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 2515b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 2525b81b6b3SRodney W. Grimes return (IO_FDCSIZE); 2535b81b6b3SRodney W. Grimes } 2545b81b6b3SRodney W. Grimes 2555b81b6b3SRodney W. Grimes /* 2565b81b6b3SRodney W. Grimes * wire controller into system, look for floppy units 2575b81b6b3SRodney W. Grimes */ 258381fe1aaSGarrett Wollman int 2595b81b6b3SRodney W. Grimes fdattach(dev) 2605b81b6b3SRodney W. Grimes struct isa_device *dev; 2615b81b6b3SRodney W. Grimes { 2625b81b6b3SRodney W. Grimes unsigned fdt,st0, cyl; 2635b81b6b3SRodney W. Grimes int hdr; 2645b81b6b3SRodney W. Grimes fdu_t fdu; 2655b81b6b3SRodney W. Grimes fdcu_t fdcu = dev->id_unit; 2665b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 2675b81b6b3SRodney W. Grimes fd_p fd; 2685b81b6b3SRodney W. Grimes int fdsu; 2695b81b6b3SRodney W. Grimes 2705b81b6b3SRodney W. Grimes fdc->fdcu = fdcu; 2715b81b6b3SRodney W. Grimes fdc->flags |= FDC_ATTACHED; 2725b81b6b3SRodney W. Grimes fdc->dmachan = dev->id_drq; 2735b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 2745b81b6b3SRodney W. Grimes 2755b81b6b3SRodney W. Grimes fdt = rtcin(RTC_FDISKETTE); 2765b81b6b3SRodney W. Grimes hdr = 0; 2775b81b6b3SRodney W. Grimes 2785b81b6b3SRodney W. Grimes /* check for each floppy drive */ 2795b81b6b3SRodney W. Grimes for (fdu = (fdcu * DRVS_PER_CTLR),fdsu = 0; 2805b81b6b3SRodney W. Grimes ((fdu < NFD) && (fdsu < DRVS_PER_CTLR)); 2815b81b6b3SRodney W. Grimes fdu++,fdsu++) 2825b81b6b3SRodney W. Grimes { 2835b81b6b3SRodney W. Grimes /* is there a unit? */ 284f5f7ba03SJordan K. Hubbard if ((fdt & 0xf0) == RTCFDT_NONE) { 285f5f7ba03SJordan K. Hubbard #define NO_TYPE NUMTYPES 286f5f7ba03SJordan K. Hubbard fd_data[fdu].type = NO_TYPE; 2875b81b6b3SRodney W. Grimes continue; 288f5f7ba03SJordan K. Hubbard } 2895b81b6b3SRodney W. Grimes 2905b81b6b3SRodney W. Grimes #ifdef notyet 2915b81b6b3SRodney W. Grimes /* select it */ 2925b81b6b3SRodney W. Grimes fd_turnon1(fdu); 2935b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 2945b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 2955b81b6b3SRodney W. Grimes out_fdc(fdcu,fdsu); 2965b81b6b3SRodney W. Grimes spinwait(1000); /* 1 sec */ 2975b81b6b3SRodney W. Grimes 2985b81b6b3SRodney W. Grimes /* anything responding */ 2995b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 3005b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 3015b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 3025b81b6b3SRodney W. Grimes if (st0 & 0xd0) 3035b81b6b3SRodney W. Grimes continue; 3045b81b6b3SRodney W. Grimes 3055b81b6b3SRodney W. Grimes #endif 3065b81b6b3SRodney W. Grimes fd_data[fdu].track = -2; 3075b81b6b3SRodney W. Grimes fd_data[fdu].fdc = fdc; 3085b81b6b3SRodney W. Grimes fd_data[fdu].fdsu = fdsu; 3092a6c8980SDavid Greenman printf("fd%d: unit %d type ", fdcu, fdu); 3105b81b6b3SRodney W. Grimes 3117ca0641bSAndrey A. Chernov switch (fdt & 0xf0) { 3127ca0641bSAndrey A. Chernov case RTCFDT_12M: 3132a6c8980SDavid Greenman printf("1.2MB 5.25in\n"); 3147ca0641bSAndrey A. Chernov fd_data[fdu].type = FD_1200; 3157ca0641bSAndrey A. Chernov break; 3167ca0641bSAndrey A. Chernov case RTCFDT_144M: 3172a6c8980SDavid Greenman printf("1.44MB 3.5in\n"); 3187ca0641bSAndrey A. Chernov fd_data[fdu].type = FD_1440; 3197ca0641bSAndrey A. Chernov break; 3207ca0641bSAndrey A. Chernov case RTCFDT_360K: 321ed2fa05eSAndrey A. Chernov printf("360KB 5.25in\n"); 3227ca0641bSAndrey A. Chernov fd_data[fdu].type = FD_360; 3237ca0641bSAndrey A. Chernov break; 324ed2fa05eSAndrey A. Chernov case RTCFDT_720K: 325ed2fa05eSAndrey A. Chernov printf("720KB 3.5in\n"); 326ed2fa05eSAndrey A. Chernov fd_data[fdu].type = FD_720; 327ed2fa05eSAndrey A. Chernov break; 3287ca0641bSAndrey A. Chernov default: 3297ca0641bSAndrey A. Chernov printf("unknown\n"); 3307ca0641bSAndrey A. Chernov fd_data[fdu].type = NO_TYPE; 3317ca0641bSAndrey A. Chernov break; 3325b81b6b3SRodney W. Grimes } 3335b81b6b3SRodney W. Grimes 3345b81b6b3SRodney W. Grimes fdt <<= 4; 335381fe1aaSGarrett Wollman fd_turnoff((caddr_t)fdu, 0); 3365b81b6b3SRodney W. Grimes hdr = 1; 3375b81b6b3SRodney W. Grimes } 3385b81b6b3SRodney W. Grimes 3395b81b6b3SRodney W. Grimes /* Set transfer to 500kbps */ 3405b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,0); /*XXX*/ 341381fe1aaSGarrett Wollman return 1; 3425b81b6b3SRodney W. Grimes } 3435b81b6b3SRodney W. Grimes 3445b81b6b3SRodney W. Grimes int 3455b81b6b3SRodney W. Grimes fdsize(dev) 3465b81b6b3SRodney W. Grimes dev_t dev; 3475b81b6b3SRodney W. Grimes { 3485b81b6b3SRodney W. Grimes return(0); 3495b81b6b3SRodney W. Grimes } 3505b81b6b3SRodney W. Grimes 3515b81b6b3SRodney W. Grimes /****************************************************************************/ 3525b81b6b3SRodney W. Grimes /* fdstrategy */ 3535b81b6b3SRodney W. Grimes /****************************************************************************/ 354381fe1aaSGarrett Wollman void fdstrategy(struct buf *bp) 3555b81b6b3SRodney W. Grimes { 3565b81b6b3SRodney W. Grimes register struct buf *dp,*dp0,*dp1; 3575b81b6b3SRodney W. Grimes long nblocks,blknum; 3585b81b6b3SRodney W. Grimes int s; 3595b81b6b3SRodney W. Grimes fdcu_t fdcu; 3605b81b6b3SRodney W. Grimes fdu_t fdu; 3615b81b6b3SRodney W. Grimes fdc_p fdc; 3625b81b6b3SRodney W. Grimes fd_p fd; 3635b81b6b3SRodney W. Grimes 3645b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 3655b81b6b3SRodney W. Grimes fd = &fd_data[fdu]; 3665b81b6b3SRodney W. Grimes fdc = fd->fdc; 3675b81b6b3SRodney W. Grimes fdcu = fdc->fdcu; 3685b81b6b3SRodney W. Grimes /*type = FDTYPE(minor(bp->b_dev));*/ 3695b81b6b3SRodney W. Grimes 3705b81b6b3SRodney W. Grimes if ((fdu >= NFD) || (bp->b_blkno < 0)) { 3715b81b6b3SRodney W. Grimes printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n", 3725b81b6b3SRodney W. Grimes fdu, bp->b_blkno, bp->b_bcount); 3735b81b6b3SRodney W. Grimes pg("fd:error in fdstrategy"); 3745b81b6b3SRodney W. Grimes bp->b_error = EINVAL; 3755b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 3765b81b6b3SRodney W. Grimes goto bad; 3775b81b6b3SRodney W. Grimes } 3785b81b6b3SRodney W. Grimes /* 3795b81b6b3SRodney W. Grimes * Set up block calculations. 3805b81b6b3SRodney W. Grimes */ 3815b81b6b3SRodney W. Grimes blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK; 3825b81b6b3SRodney W. Grimes nblocks = fd->ft->size; 3835b81b6b3SRodney W. Grimes if (blknum + (bp->b_bcount / FDBLK) > nblocks) { 3845b81b6b3SRodney W. Grimes if (blknum == nblocks) { 3855b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount; 3865b81b6b3SRodney W. Grimes } else { 3875b81b6b3SRodney W. Grimes bp->b_error = ENOSPC; 3885b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 3895b81b6b3SRodney W. Grimes } 3905b81b6b3SRodney W. Grimes goto bad; 3915b81b6b3SRodney W. Grimes } 3925b81b6b3SRodney W. Grimes bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads); 3935b81b6b3SRodney W. Grimes dp = &(fdc->head); 3945b81b6b3SRodney W. Grimes s = splbio(); 3955b81b6b3SRodney W. Grimes disksort(dp, bp); 396aaf08d94SGarrett Wollman untimeout(fd_turnoff, (caddr_t)fdu); /* a good idea */ 3975b81b6b3SRodney W. Grimes fdstart(fdcu); 3985b81b6b3SRodney W. Grimes splx(s); 3995b81b6b3SRodney W. Grimes return; 4005b81b6b3SRodney W. Grimes 4015b81b6b3SRodney W. Grimes bad: 4025b81b6b3SRodney W. Grimes biodone(bp); 403b39c878eSAndrey A. Chernov return; 4045b81b6b3SRodney W. Grimes } 4055b81b6b3SRodney W. Grimes 4065b81b6b3SRodney W. Grimes /****************************************************************************/ 4075b81b6b3SRodney W. Grimes /* motor control stuff */ 4085b81b6b3SRodney W. Grimes /* remember to not deselect the drive we're working on */ 4095b81b6b3SRodney W. Grimes /****************************************************************************/ 410381fe1aaSGarrett Wollman void 411f5f7ba03SJordan K. Hubbard set_motor(fdcu, fdu, reset) 412f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 413f5f7ba03SJordan K. Hubbard fdu_t fdu; 414f5f7ba03SJordan K. Hubbard int reset; 4155b81b6b3SRodney W. Grimes { 4165b81b6b3SRodney W. Grimes int m0,m1; 4175b81b6b3SRodney W. Grimes int selunit; 4185b81b6b3SRodney W. Grimes fd_p fd; 4195b81b6b3SRodney W. Grimes if(fd = fdc_data[fdcu].fd)/* yes an assign! */ 4205b81b6b3SRodney W. Grimes { 4215b81b6b3SRodney W. Grimes selunit = fd->fdsu; 4225b81b6b3SRodney W. Grimes } 4235b81b6b3SRodney W. Grimes else 4245b81b6b3SRodney W. Grimes { 4255b81b6b3SRodney W. Grimes selunit = 0; 4265b81b6b3SRodney W. Grimes } 4275b81b6b3SRodney W. Grimes m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR; 4285b81b6b3SRodney W. Grimes m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR; 4295b81b6b3SRodney W. Grimes outb(fdc_data[fdcu].baseport+fdout, 4305b81b6b3SRodney W. Grimes selunit 4315b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4325b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4335b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0)); 4345b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdout]",( 4355b81b6b3SRodney W. Grimes selunit 4365b81b6b3SRodney W. Grimes | (reset ? 0 : (FDO_FRST|FDO_FDMAEN)) 4375b81b6b3SRodney W. Grimes | (m0 ? FDO_MOEN0 : 0) 4385b81b6b3SRodney W. Grimes | (m1 ? FDO_MOEN1 : 0))); 4395b81b6b3SRodney W. Grimes } 4405b81b6b3SRodney W. Grimes 441381fe1aaSGarrett Wollman static void 442381fe1aaSGarrett Wollman fd_turnoff(caddr_t arg1, int arg2) 4435b81b6b3SRodney W. Grimes { 444381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 445f5f7ba03SJordan K. Hubbard int s; 446f5f7ba03SJordan K. Hubbard 4475b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 448f5f7ba03SJordan K. Hubbard s = splbio(); 4495b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR; 4505b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 451f5f7ba03SJordan K. Hubbard splx(s); 4525b81b6b3SRodney W. Grimes } 4535b81b6b3SRodney W. Grimes 454381fe1aaSGarrett Wollman void 455381fe1aaSGarrett Wollman fd_motor_on(caddr_t arg1, int arg2) 4565b81b6b3SRodney W. Grimes { 457381fe1aaSGarrett Wollman fdu_t fdu = (fdu_t)arg1; 458f5f7ba03SJordan K. Hubbard int s; 459f5f7ba03SJordan K. Hubbard 4605b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 461f5f7ba03SJordan K. Hubbard s = splbio(); 4625b81b6b3SRodney W. Grimes fd->flags &= ~FD_MOTOR_WAIT; 4635b81b6b3SRodney W. Grimes if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) 4645b81b6b3SRodney W. Grimes { 465f5f7ba03SJordan K. Hubbard fdintr(fd->fdc->fdcu); 4665b81b6b3SRodney W. Grimes } 467f5f7ba03SJordan K. Hubbard splx(s); 4685b81b6b3SRodney W. Grimes } 4695b81b6b3SRodney W. Grimes 470381fe1aaSGarrett Wollman static void fd_turnon1(fdu_t); 471381fe1aaSGarrett Wollman 472381fe1aaSGarrett Wollman void 473f5f7ba03SJordan K. Hubbard fd_turnon(fdu) 474f5f7ba03SJordan K. Hubbard fdu_t fdu; 4755b81b6b3SRodney W. Grimes { 4765b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 4775b81b6b3SRodney W. Grimes if(!(fd->flags & FD_MOTOR)) 4785b81b6b3SRodney W. Grimes { 4795b81b6b3SRodney W. Grimes fd_turnon1(fdu); 4805b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR_WAIT; 481381fe1aaSGarrett Wollman timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ 4825b81b6b3SRodney W. Grimes } 4835b81b6b3SRodney W. Grimes } 4845b81b6b3SRodney W. Grimes 485381fe1aaSGarrett Wollman static void 486381fe1aaSGarrett Wollman fd_turnon1(fdu_t fdu) 4875b81b6b3SRodney W. Grimes { 4885b81b6b3SRodney W. Grimes fd_p fd = fd_data + fdu; 4895b81b6b3SRodney W. Grimes fd->flags |= FD_MOTOR; 4905b81b6b3SRodney W. Grimes set_motor(fd->fdc->fdcu,fd->fdsu,0); 4915b81b6b3SRodney W. Grimes } 4925b81b6b3SRodney W. Grimes 4935b81b6b3SRodney W. Grimes /****************************************************************************/ 4945b81b6b3SRodney W. Grimes /* fdc in/out */ 4955b81b6b3SRodney W. Grimes /****************************************************************************/ 4965b81b6b3SRodney W. Grimes int 497f5f7ba03SJordan K. Hubbard in_fdc(fdcu) 498f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 4995b81b6b3SRodney W. Grimes { 5005b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5015b81b6b3SRodney W. Grimes int i, j = 100000; 5025b81b6b3SRodney W. Grimes while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM)) 5035b81b6b3SRodney W. Grimes != (NE7_DIO|NE7_RQM) && j-- > 0) 5045b81b6b3SRodney W. Grimes if (i == NE7_RQM) return -1; 5055b81b6b3SRodney W. Grimes if (j <= 0) 5065b81b6b3SRodney W. Grimes return(-1); 5075b81b6b3SRodney W. Grimes #ifdef DEBUG 5085b81b6b3SRodney W. Grimes i = inb(baseport+fddata); 5095b81b6b3SRodney W. Grimes TRACE1("[fddata->0x%x]",(unsigned char)i); 5105b81b6b3SRodney W. Grimes return(i); 5115b81b6b3SRodney W. Grimes #else 5125b81b6b3SRodney W. Grimes return inb(baseport+fddata); 5135b81b6b3SRodney W. Grimes #endif 5145b81b6b3SRodney W. Grimes } 5155b81b6b3SRodney W. Grimes 516381fe1aaSGarrett Wollman int 517f5f7ba03SJordan K. Hubbard out_fdc(fdcu, x) 518f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 519f5f7ba03SJordan K. Hubbard int x; 5205b81b6b3SRodney W. Grimes { 5215b81b6b3SRodney W. Grimes int baseport = fdc_data[fdcu].baseport; 5223b3837dbSRodney W. Grimes int i; 5235b81b6b3SRodney W. Grimes 5243b3837dbSRodney W. Grimes /* Check that the direction bit is set */ 5253b3837dbSRodney W. Grimes i = 100000; 5265b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0); 5273b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5283b3837dbSRodney W. Grimes 5293b3837dbSRodney W. Grimes /* Check that the floppy controller is ready for a command */ 5303b3837dbSRodney W. Grimes i = 100000; 5315b81b6b3SRodney W. Grimes while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0); 5323b3837dbSRodney W. Grimes if (i <= 0) return (-1); /* Floppy timed out */ 5333b3837dbSRodney W. Grimes 5343b3837dbSRodney W. Grimes /* Send the command and return */ 5355b81b6b3SRodney W. Grimes outb(baseport+fddata,x); 5365b81b6b3SRodney W. Grimes TRACE1("[0x%x->fddata]",x); 5375b81b6b3SRodney W. Grimes return (0); 5385b81b6b3SRodney W. Grimes } 5395b81b6b3SRodney W. Grimes 5405b81b6b3SRodney W. Grimes /****************************************************************************/ 5415b81b6b3SRodney W. Grimes /* fdopen/fdclose */ 5425b81b6b3SRodney W. Grimes /****************************************************************************/ 543381fe1aaSGarrett Wollman int 5445b81b6b3SRodney W. Grimes Fdopen(dev, flags) 5455b81b6b3SRodney W. Grimes dev_t dev; 5465b81b6b3SRodney W. Grimes int flags; 5475b81b6b3SRodney W. Grimes { 5485b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 54920a29168SAndrey A. Chernov int type = FDTYPE(minor(dev)); 5505b81b6b3SRodney W. Grimes int s; 5515b81b6b3SRodney W. Grimes 5525b81b6b3SRodney W. Grimes /* check bounds */ 553fadc21aeSAndreas Schulz if (fdu >= NFD || fd_data[fdu].fdc == NULL 554fadc21aeSAndreas Schulz || fd_data[fdu].type == NO_TYPE) return(ENXIO); 555ed2fa05eSAndrey A. Chernov if (type > NUMDENS) return(ENXIO); 5567ca0641bSAndrey A. Chernov if (type == 0) 5577ca0641bSAndrey A. Chernov type = fd_data[fdu].type; 5587ca0641bSAndrey A. Chernov else { 5597ca0641bSAndrey A. Chernov type--; 5607ca0641bSAndrey A. Chernov if (type != fd_data[fdu].type) { 561fa4700b4SAndrey A. Chernov switch (fd_data[fdu].type) { 5627ca0641bSAndrey A. Chernov case FD_360: 5637ca0641bSAndrey A. Chernov return(ENXIO); 564ed2fa05eSAndrey A. Chernov case FD_720: 565b39c878eSAndrey A. Chernov if ( type != FD_820 566b39c878eSAndrey A. Chernov && type != FD_800 567ed2fa05eSAndrey A. Chernov ) 568ed2fa05eSAndrey A. Chernov return(ENXIO); 569ed2fa05eSAndrey A. Chernov break; 5707ca0641bSAndrey A. Chernov case FD_1200: 571b39c878eSAndrey A. Chernov switch (type) { 572b39c878eSAndrey A. Chernov case FD_1480: 573b39c878eSAndrey A. Chernov type = FD_1480in5_25; 574fa4700b4SAndrey A. Chernov break; 5757ca0641bSAndrey A. Chernov case FD_1440: 576b39c878eSAndrey A. Chernov type = FD_1440in5_25; 577b39c878eSAndrey A. Chernov break; 578b39c878eSAndrey A. Chernov case FD_820: 579b39c878eSAndrey A. Chernov type = FD_820in5_25; 580b39c878eSAndrey A. Chernov break; 581b39c878eSAndrey A. Chernov case FD_800: 582b39c878eSAndrey A. Chernov type = FD_800in5_25; 583b39c878eSAndrey A. Chernov break; 584b39c878eSAndrey A. Chernov case FD_720: 585b39c878eSAndrey A. Chernov type = FD_720in5_25; 586b39c878eSAndrey A. Chernov break; 587b39c878eSAndrey A. Chernov case FD_360: 588b39c878eSAndrey A. Chernov type = FD_360in5_25; 589b39c878eSAndrey A. Chernov break; 590b39c878eSAndrey A. Chernov default: 591b39c878eSAndrey A. Chernov return(ENXIO); 592b39c878eSAndrey A. Chernov } 593b39c878eSAndrey A. Chernov break; 594b39c878eSAndrey A. Chernov case FD_1440: 595b39c878eSAndrey A. Chernov if ( type != FD_1720 596b39c878eSAndrey A. Chernov && type != FD_1480 597ed2fa05eSAndrey A. Chernov && type != FD_1200 598b39c878eSAndrey A. Chernov && type != FD_820 599b39c878eSAndrey A. Chernov && type != FD_800 600b39c878eSAndrey A. Chernov && type != FD_720 6017ca0641bSAndrey A. Chernov ) 602dffff499SAndrey A. Chernov return(ENXIO); 603fa4700b4SAndrey A. Chernov break; 6047ca0641bSAndrey A. Chernov } 6057ca0641bSAndrey A. Chernov } 606fa4700b4SAndrey A. Chernov } 607dffff499SAndrey A. Chernov fd_data[fdu].ft = fd_types + type; 6085b81b6b3SRodney W. Grimes fd_data[fdu].flags |= FD_OPEN; 6095b81b6b3SRodney W. Grimes 6105b81b6b3SRodney W. Grimes return 0; 6115b81b6b3SRodney W. Grimes } 6125b81b6b3SRodney W. Grimes 613381fe1aaSGarrett Wollman int 6145b81b6b3SRodney W. Grimes fdclose(dev, flags) 6155b81b6b3SRodney W. Grimes dev_t dev; 616381fe1aaSGarrett Wollman int flags; 6175b81b6b3SRodney W. Grimes { 6185b81b6b3SRodney W. Grimes fdu_t fdu = FDUNIT(minor(dev)); 6195b81b6b3SRodney W. Grimes fd_data[fdu].flags &= ~FD_OPEN; 6205b81b6b3SRodney W. Grimes return(0); 6215b81b6b3SRodney W. Grimes } 6225b81b6b3SRodney W. Grimes 6235b81b6b3SRodney W. Grimes 6245b81b6b3SRodney W. Grimes /***************************************************************\ 6255b81b6b3SRodney W. Grimes * fdstart * 6265b81b6b3SRodney W. Grimes * We have just queued something.. if the controller is not busy * 6275b81b6b3SRodney W. Grimes * then simulate the case where it has just finished a command * 6285b81b6b3SRodney W. Grimes * So that it (the interrupt routine) looks on the queue for more* 6295b81b6b3SRodney W. Grimes * work to do and picks up what we just added. * 6305b81b6b3SRodney W. Grimes * If the controller is already busy, we need do nothing, as it * 6315b81b6b3SRodney W. Grimes * will pick up our work when the present work completes * 6325b81b6b3SRodney W. Grimes \***************************************************************/ 633381fe1aaSGarrett Wollman static void 634f5f7ba03SJordan K. Hubbard fdstart(fdcu) 635f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 6365b81b6b3SRodney W. Grimes { 6375b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 6385b81b6b3SRodney W. Grimes int s; 6395b81b6b3SRodney W. Grimes fdu_t fdu; 6405b81b6b3SRodney W. Grimes 6415b81b6b3SRodney W. Grimes s = splbio(); 6425b81b6b3SRodney W. Grimes if(fdc_data[fdcu].state == DEVIDLE) 6435b81b6b3SRodney W. Grimes { 6445b81b6b3SRodney W. Grimes fdintr(fdcu); 6455b81b6b3SRodney W. Grimes } 6465b81b6b3SRodney W. Grimes splx(s); 6475b81b6b3SRodney W. Grimes } 6485b81b6b3SRodney W. Grimes 649381fe1aaSGarrett Wollman static void 650381fe1aaSGarrett Wollman fd_timeout(caddr_t arg1, int arg2) 6515b81b6b3SRodney W. Grimes { 652381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 6535b81b6b3SRodney W. Grimes fdu_t fdu = fdc_data[fdcu].fdu; 6545b81b6b3SRodney W. Grimes int st0, st3, cyl; 6555b81b6b3SRodney W. Grimes struct buf *dp,*bp; 656f5f7ba03SJordan K. Hubbard int s; 6575b81b6b3SRodney W. Grimes 6585b81b6b3SRodney W. Grimes dp = &fdc_data[fdcu].head; 659f5f7ba03SJordan K. Hubbard s = splbio(); 6605b81b6b3SRodney W. Grimes bp = dp->b_actf; 6615b81b6b3SRodney W. Grimes 6625b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSED); 6635b81b6b3SRodney W. Grimes out_fdc(fdcu,fd_data[fdu].hddrv); 6645b81b6b3SRodney W. Grimes st3 = in_fdc(fdcu); 6655b81b6b3SRodney W. Grimes 6665b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 6675b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 6685b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 6695b81b6b3SRodney W. Grimes printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n", 6705b81b6b3SRodney W. Grimes fdu, 6715b81b6b3SRodney W. Grimes st0, 6725b81b6b3SRodney W. Grimes NE7_ST0BITS, 6735b81b6b3SRodney W. Grimes cyl, 6745b81b6b3SRodney W. Grimes st3, 6755b81b6b3SRodney W. Grimes NE7_ST3BITS); 6765b81b6b3SRodney W. Grimes 6775b81b6b3SRodney W. Grimes if (bp) 6785b81b6b3SRodney W. Grimes { 6795b81b6b3SRodney W. Grimes retrier(fdcu); 6805b81b6b3SRodney W. Grimes fdc_data[fdcu].status[0] = 0xc0; 6815b81b6b3SRodney W. Grimes fdc_data[fdcu].state = IOTIMEDOUT; 6825b81b6b3SRodney W. Grimes if( fdc_data[fdcu].retry < 6) 6835b81b6b3SRodney W. Grimes fdc_data[fdcu].retry = 6; 6845b81b6b3SRodney W. Grimes } 6855b81b6b3SRodney W. Grimes else 6865b81b6b3SRodney W. Grimes { 6875b81b6b3SRodney W. Grimes fdc_data[fdcu].fd = (fd_p) 0; 6885b81b6b3SRodney W. Grimes fdc_data[fdcu].fdu = -1; 6895b81b6b3SRodney W. Grimes fdc_data[fdcu].state = DEVIDLE; 6905b81b6b3SRodney W. Grimes } 691f5f7ba03SJordan K. Hubbard fdintr(fdcu); 692f5f7ba03SJordan K. Hubbard splx(s); 6935b81b6b3SRodney W. Grimes } 6945b81b6b3SRodney W. Grimes 6955b81b6b3SRodney W. Grimes /* just ensure it has the right spl */ 696381fe1aaSGarrett Wollman static void 697381fe1aaSGarrett Wollman fd_pseudointr(caddr_t arg1, int arg2) 6985b81b6b3SRodney W. Grimes { 699381fe1aaSGarrett Wollman fdcu_t fdcu = (fdcu_t)arg1; 7005b81b6b3SRodney W. Grimes int s; 7015b81b6b3SRodney W. Grimes s = splbio(); 7025b81b6b3SRodney W. Grimes fdintr(fdcu); 7035b81b6b3SRodney W. Grimes splx(s); 7045b81b6b3SRodney W. Grimes } 7055b81b6b3SRodney W. Grimes 7065b81b6b3SRodney W. Grimes /***********************************************************************\ 7075b81b6b3SRodney W. Grimes * fdintr * 7085b81b6b3SRodney W. Grimes * keep calling the state machine until it returns a 0 * 7095b81b6b3SRodney W. Grimes * ALWAYS called at SPLBIO * 7105b81b6b3SRodney W. Grimes \***********************************************************************/ 711381fe1aaSGarrett Wollman void 712381fe1aaSGarrett Wollman fdintr(fdcu_t fdcu) 7135b81b6b3SRodney W. Grimes { 7145b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 715381fe1aaSGarrett Wollman while(fdstate(fdcu, fdc)) 716381fe1aaSGarrett Wollman ; 7175b81b6b3SRodney W. Grimes } 7185b81b6b3SRodney W. Grimes 7195b81b6b3SRodney W. Grimes /***********************************************************************\ 7205b81b6b3SRodney W. Grimes * The controller state machine. * 7215b81b6b3SRodney W. Grimes * if it returns a non zero value, it should be called again immediatly * 7225b81b6b3SRodney W. Grimes \***********************************************************************/ 723381fe1aaSGarrett Wollman int 724381fe1aaSGarrett Wollman fdstate(fdcu, fdc) 725f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 726f5f7ba03SJordan K. Hubbard fdc_p fdc; 7275b81b6b3SRodney W. Grimes { 728b39c878eSAndrey A. Chernov int read, format, head, trac, sec = 0, i = 0, s, sectrac, cyl, st0; 7295b81b6b3SRodney W. Grimes unsigned long blknum; 7305b81b6b3SRodney W. Grimes fdu_t fdu = fdc->fdu; 7315b81b6b3SRodney W. Grimes fd_p fd; 7325b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 733b39c878eSAndrey A. Chernov struct fd_formb *finfo = NULL; 7345b81b6b3SRodney W. Grimes 7355b81b6b3SRodney W. Grimes dp = &(fdc->head); 7365b81b6b3SRodney W. Grimes bp = dp->b_actf; 7375b81b6b3SRodney W. Grimes if(!bp) 7385b81b6b3SRodney W. Grimes { 7395b81b6b3SRodney W. Grimes /***********************************************\ 7405b81b6b3SRodney W. Grimes * nothing left for this controller to do * 7415b81b6b3SRodney W. Grimes * Force into the IDLE state, * 7425b81b6b3SRodney W. Grimes \***********************************************/ 7435b81b6b3SRodney W. Grimes fdc->state = DEVIDLE; 7445b81b6b3SRodney W. Grimes if(fdc->fd) 7455b81b6b3SRodney W. Grimes { 7465b81b6b3SRodney W. Grimes printf("unexpected valid fd pointer (fdu = %d)\n" 7475b81b6b3SRodney W. Grimes ,fdc->fdu); 7485b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 7495b81b6b3SRodney W. Grimes fdc->fdu = -1; 7505b81b6b3SRodney W. Grimes } 7515b81b6b3SRodney W. Grimes TRACE1("[fdc%d IDLE]",fdcu); 7525b81b6b3SRodney W. Grimes return(0); 7535b81b6b3SRodney W. Grimes } 7545b81b6b3SRodney W. Grimes fdu = FDUNIT(minor(bp->b_dev)); 7555b81b6b3SRodney W. Grimes fd = fd_data + fdu; 7565b81b6b3SRodney W. Grimes if (fdc->fd && (fd != fdc->fd)) 7575b81b6b3SRodney W. Grimes { 7585b81b6b3SRodney W. Grimes printf("confused fd pointers\n"); 7595b81b6b3SRodney W. Grimes } 7605b81b6b3SRodney W. Grimes read = bp->b_flags & B_READ; 761b39c878eSAndrey A. Chernov format = bp->b_flags & B_FORMAT; 762b39c878eSAndrey A. Chernov if(format) 763b39c878eSAndrey A. Chernov finfo = (struct fd_formb *)bp->b_un.b_addr; 7645b81b6b3SRodney W. Grimes TRACE1("fd%d",fdu); 7655b81b6b3SRodney W. Grimes TRACE1("[%s]",fdstates[fdc->state]); 7665b81b6b3SRodney W. Grimes TRACE1("(0x%x)",fd->flags); 767aaf08d94SGarrett Wollman untimeout(fd_turnoff, (caddr_t)fdu); 768381fe1aaSGarrett Wollman timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); 7695b81b6b3SRodney W. Grimes switch (fdc->state) 7705b81b6b3SRodney W. Grimes { 7715b81b6b3SRodney W. Grimes case DEVIDLE: 7725b81b6b3SRodney W. Grimes case FINDWORK: /* we have found new work */ 7735b81b6b3SRodney W. Grimes fdc->retry = 0; 7745b81b6b3SRodney W. Grimes fd->skip = 0; 7755b81b6b3SRodney W. Grimes fdc->fd = fd; 7765b81b6b3SRodney W. Grimes fdc->fdu = fdu; 7775b81b6b3SRodney W. Grimes /*******************************************************\ 7785b81b6b3SRodney W. Grimes * If the next drive has a motor startup pending, then * 7795b81b6b3SRodney W. Grimes * it will start up in it's own good time * 7805b81b6b3SRodney W. Grimes \*******************************************************/ 7815b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 7825b81b6b3SRodney W. Grimes { 7835b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 7845b81b6b3SRodney W. Grimes return(0); /* come back later */ 7855b81b6b3SRodney W. Grimes } 7865b81b6b3SRodney W. Grimes /*******************************************************\ 7875b81b6b3SRodney W. Grimes * Maybe if it's not starting, it SHOULD be starting * 7885b81b6b3SRodney W. Grimes \*******************************************************/ 7895b81b6b3SRodney W. Grimes if (!(fd->flags & FD_MOTOR)) 7905b81b6b3SRodney W. Grimes { 7915b81b6b3SRodney W. Grimes fdc->state = MOTORWAIT; 7925b81b6b3SRodney W. Grimes fd_turnon(fdu); 7935b81b6b3SRodney W. Grimes return(0); 7945b81b6b3SRodney W. Grimes } 7955b81b6b3SRodney W. Grimes else /* at least make sure we are selected */ 7965b81b6b3SRodney W. Grimes { 7975b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 7985b81b6b3SRodney W. Grimes } 7995b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 8005b81b6b3SRodney W. Grimes break; 8015b81b6b3SRodney W. Grimes case DOSEEK: 8025b81b6b3SRodney W. Grimes if (bp->b_cylin == fd->track) 8035b81b6b3SRodney W. Grimes { 8045b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8055b81b6b3SRodney W. Grimes break; 8065b81b6b3SRodney W. Grimes } 8075b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SEEK); /* Seek function */ 8085b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); /* Drive number */ 8095b81b6b3SRodney W. Grimes out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac); 8105b81b6b3SRodney W. Grimes fd->track = -2; 8115b81b6b3SRodney W. Grimes fdc->state = SEEKWAIT; 812381fe1aaSGarrett Wollman timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 8135b81b6b3SRodney W. Grimes return(0); /* will return later */ 8145b81b6b3SRodney W. Grimes case SEEKWAIT: 815aaf08d94SGarrett Wollman untimeout(fd_timeout, (caddr_t)fdcu); 8165b81b6b3SRodney W. Grimes /* allow heads to settle */ 817381fe1aaSGarrett Wollman timeout(fd_pseudointr, (caddr_t)fdcu, hz / 50); 8185b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 8195b81b6b3SRodney W. Grimes return(0); /* will return later */ 8205b81b6b3SRodney W. Grimes break; 8215b81b6b3SRodney W. Grimes 8225b81b6b3SRodney W. Grimes case SEEKCOMPLETE : /* SEEK DONE, START DMA */ 8235b81b6b3SRodney W. Grimes /* Make sure seek really happened*/ 8245b81b6b3SRodney W. Grimes if(fd->track == -2) 8255b81b6b3SRodney W. Grimes { 8265b81b6b3SRodney W. Grimes int descyl = bp->b_cylin * fd->ft->steptrac; 8275b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 8285b81b6b3SRodney W. Grimes i = in_fdc(fdcu); 8295b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 8305b81b6b3SRodney W. Grimes if (cyl != descyl) 8315b81b6b3SRodney W. Grimes { 8325b81b6b3SRodney W. Grimes printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu, 8335b81b6b3SRodney W. Grimes descyl, cyl, i, NE7_ST0BITS); 8345b81b6b3SRodney W. Grimes return(retrier(fdcu)); 8355b81b6b3SRodney W. Grimes } 8365b81b6b3SRodney W. Grimes } 8375b81b6b3SRodney W. Grimes 8385b81b6b3SRodney W. Grimes fd->track = bp->b_cylin; 839b39c878eSAndrey A. Chernov if(format) 840b39c878eSAndrey A. Chernov fd->skip = (char *)&(finfo->fd_formb_cylno(0)) 841b39c878eSAndrey A. Chernov - (char *)finfo; 8425b81b6b3SRodney W. Grimes isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip, 843b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 8445b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 8455b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 8465b81b6b3SRodney W. Grimes sectrac = fd->ft->sectrac; 8475b81b6b3SRodney W. Grimes sec = blknum % (sectrac * fd->ft->heads); 8485b81b6b3SRodney W. Grimes head = sec / sectrac; 8495b81b6b3SRodney W. Grimes sec = sec % sectrac + 1; 8505b81b6b3SRodney W. Grimes /*XXX*/ fd->hddrv = ((head&1)<<2)+fdu; 8515b81b6b3SRodney W. Grimes 852b39c878eSAndrey A. Chernov if(format) 853b39c878eSAndrey A. Chernov { 854b39c878eSAndrey A. Chernov /* formatting */ 855b39c878eSAndrey A. Chernov out_fdc(fdcu,/* NE7CMD_FORMAT */ 0x4d); 856b39c878eSAndrey A. Chernov out_fdc(fdcu,head << 2 | fdu); 857b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_secshift); 858b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_nsecs); 859b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_gaplen); 860b39c878eSAndrey A. Chernov out_fdc(fdcu,finfo->fd_formb_fillbyte); 861b39c878eSAndrey A. Chernov } 862b39c878eSAndrey A. Chernov else 863b39c878eSAndrey A. Chernov { 8645b81b6b3SRodney W. Grimes if (read) 8655b81b6b3SRodney W. Grimes { 8665b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_READ); /* READ */ 8675b81b6b3SRodney W. Grimes } 8685b81b6b3SRodney W. Grimes else 8695b81b6b3SRodney W. Grimes { 8705b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_WRITE); /* WRITE */ 8715b81b6b3SRodney W. Grimes } 8725b81b6b3SRodney W. Grimes out_fdc(fdcu,head << 2 | fdu); /* head & unit */ 8735b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->track); /* track */ 8745b81b6b3SRodney W. Grimes out_fdc(fdcu,head); 8755b81b6b3SRodney W. Grimes out_fdc(fdcu,sec); /* sector XXX +1? */ 8765b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->secsize); /* sector size */ 8775b81b6b3SRodney W. Grimes out_fdc(fdcu,sectrac); /* sectors/track */ 8785b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->gap); /* gap size */ 8795b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->ft->datalen); /* data length */ 880b39c878eSAndrey A. Chernov } 8815b81b6b3SRodney W. Grimes fdc->state = IOCOMPLETE; 882381fe1aaSGarrett Wollman timeout(fd_timeout, (caddr_t)fdcu, 2 * hz); 8835b81b6b3SRodney W. Grimes return(0); /* will return later */ 8845b81b6b3SRodney W. Grimes case IOCOMPLETE: /* IO DONE, post-analyze */ 885aaf08d94SGarrett Wollman untimeout(fd_timeout, (caddr_t)fdcu); 8865b81b6b3SRodney W. Grimes for(i=0;i<7;i++) 8875b81b6b3SRodney W. Grimes { 8885b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 8895b81b6b3SRodney W. Grimes } 8905b81b6b3SRodney W. Grimes case IOTIMEDOUT: /*XXX*/ 8915b81b6b3SRodney W. Grimes isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip, 892b39c878eSAndrey A. Chernov format ? bp->b_bcount : FDBLK, fdc->dmachan); 8935b81b6b3SRodney W. Grimes if (fdc->status[0]&0xF8) 8945b81b6b3SRodney W. Grimes { 895b39c878eSAndrey A. Chernov if (fdc->status[1] & 0x10) { 896b39c878eSAndrey A. Chernov /* 897b39c878eSAndrey A. Chernov * Operation not completed in reasonable time. 898b39c878eSAndrey A. Chernov * Just restart it, don't increment retry count. 899b39c878eSAndrey A. Chernov * (vak) 900b39c878eSAndrey A. Chernov */ 901b39c878eSAndrey A. Chernov fdc->state = SEEKCOMPLETE; 902b39c878eSAndrey A. Chernov return (1); 903b39c878eSAndrey A. Chernov } 9045b81b6b3SRodney W. Grimes return(retrier(fdcu)); 9055b81b6b3SRodney W. Grimes } 9065b81b6b3SRodney W. Grimes /* All OK */ 9075b81b6b3SRodney W. Grimes fd->skip += FDBLK; 908b39c878eSAndrey A. Chernov if (!format && fd->skip < bp->b_bcount) 9095b81b6b3SRodney W. Grimes { 9105b81b6b3SRodney W. Grimes /* set up next transfer */ 9115b81b6b3SRodney W. Grimes blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK 9125b81b6b3SRodney W. Grimes + fd->skip/FDBLK; 9135b81b6b3SRodney W. Grimes bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads)); 9145b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9155b81b6b3SRodney W. Grimes } 9165b81b6b3SRodney W. Grimes else 9175b81b6b3SRodney W. Grimes { 9185b81b6b3SRodney W. Grimes /* ALL DONE */ 9195b81b6b3SRodney W. Grimes fd->skip = 0; 9205b81b6b3SRodney W. Grimes bp->b_resid = 0; 9215b81b6b3SRodney W. Grimes dp->b_actf = bp->av_forw; 9225b81b6b3SRodney W. Grimes biodone(bp); 9235b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 9245b81b6b3SRodney W. Grimes fdc->fdu = -1; 9255b81b6b3SRodney W. Grimes fdc->state = FINDWORK; 9265b81b6b3SRodney W. Grimes } 9275b81b6b3SRodney W. Grimes return(1); 9285b81b6b3SRodney W. Grimes case RESETCTLR: 9295b81b6b3SRodney W. Grimes /* Try a reset, keep motor on */ 9305b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,1); 9315b81b6b3SRodney W. Grimes DELAY(100); 9325b81b6b3SRodney W. Grimes set_motor(fdcu,fd->fdsu,0); 9335b81b6b3SRodney W. Grimes outb(fdc->baseport+fdctl,fd->ft->trans); 9345b81b6b3SRodney W. Grimes TRACE1("[0x%x->fdctl]",fd->ft->trans); 9355b81b6b3SRodney W. Grimes fdc->retry++; 9365b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 9375b81b6b3SRodney W. Grimes break; 9385b81b6b3SRodney W. Grimes case STARTRECAL: 9395b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */ 9405b81b6b3SRodney W. Grimes out_fdc(fdcu,0xDF); 9415b81b6b3SRodney W. Grimes out_fdc(fdcu,2); 9425b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */ 9435b81b6b3SRodney W. Grimes out_fdc(fdcu,fdu); 9445b81b6b3SRodney W. Grimes fdc->state = RECALWAIT; 9455b81b6b3SRodney W. Grimes return(0); /* will return later */ 9465b81b6b3SRodney W. Grimes case RECALWAIT: 9475b81b6b3SRodney W. Grimes /* allow heads to settle */ 948381fe1aaSGarrett Wollman timeout(fd_pseudointr, (caddr_t)fdcu, hz / 30); 9495b81b6b3SRodney W. Grimes fdc->state = RECALCOMPLETE; 9505b81b6b3SRodney W. Grimes return(0); /* will return later */ 9515b81b6b3SRodney W. Grimes case RECALCOMPLETE: 9525b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 9535b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 9545b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 9555b81b6b3SRodney W. Grimes if (cyl != 0) 9565b81b6b3SRodney W. Grimes { 9575b81b6b3SRodney W. Grimes printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, 9585b81b6b3SRodney W. Grimes st0, NE7_ST0BITS, cyl); 9595b81b6b3SRodney W. Grimes return(retrier(fdcu)); 9605b81b6b3SRodney W. Grimes } 9615b81b6b3SRodney W. Grimes fd->track = 0; 9625b81b6b3SRodney W. Grimes /* Seek (probably) necessary */ 9635b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9645b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 9655b81b6b3SRodney W. Grimes case MOTORWAIT: 9665b81b6b3SRodney W. Grimes if(fd->flags & FD_MOTOR_WAIT) 9675b81b6b3SRodney W. Grimes { 9685b81b6b3SRodney W. Grimes return(0); /* time's not up yet */ 9695b81b6b3SRodney W. Grimes } 9705b81b6b3SRodney W. Grimes fdc->state = DOSEEK; 9715b81b6b3SRodney W. Grimes return(1); /* will return immediatly */ 9725b81b6b3SRodney W. Grimes default: 9735b81b6b3SRodney W. Grimes printf("Unexpected FD int->"); 9745b81b6b3SRodney W. Grimes out_fdc(fdcu,NE7CMD_SENSEI); 9755b81b6b3SRodney W. Grimes st0 = in_fdc(fdcu); 9765b81b6b3SRodney W. Grimes cyl = in_fdc(fdcu); 9775b81b6b3SRodney W. Grimes printf("ST0 = %lx, PCN = %lx\n",i,sec); 9785b81b6b3SRodney W. Grimes out_fdc(fdcu,0x4A); 9795b81b6b3SRodney W. Grimes out_fdc(fdcu,fd->fdsu); 9805b81b6b3SRodney W. Grimes for(i=0;i<7;i++) { 9815b81b6b3SRodney W. Grimes fdc->status[i] = in_fdc(fdcu); 9825b81b6b3SRodney W. Grimes } 9835b81b6b3SRodney W. Grimes printf("intr status :%lx %lx %lx %lx %lx %lx %lx ", 9845b81b6b3SRodney W. Grimes fdc->status[0], 9855b81b6b3SRodney W. Grimes fdc->status[1], 9865b81b6b3SRodney W. Grimes fdc->status[2], 9875b81b6b3SRodney W. Grimes fdc->status[3], 9885b81b6b3SRodney W. Grimes fdc->status[4], 9895b81b6b3SRodney W. Grimes fdc->status[5], 9905b81b6b3SRodney W. Grimes fdc->status[6] ); 9915b81b6b3SRodney W. Grimes return(0); 9925b81b6b3SRodney W. Grimes } 9935b81b6b3SRodney W. Grimes return(1); /* Come back immediatly to new state */ 9945b81b6b3SRodney W. Grimes } 9955b81b6b3SRodney W. Grimes 996aaf08d94SGarrett Wollman static int 997f5f7ba03SJordan K. Hubbard retrier(fdcu) 998f5f7ba03SJordan K. Hubbard fdcu_t fdcu; 9995b81b6b3SRodney W. Grimes { 10005b81b6b3SRodney W. Grimes fdc_p fdc = fdc_data + fdcu; 10015b81b6b3SRodney W. Grimes register struct buf *dp,*bp; 10025b81b6b3SRodney W. Grimes 10035b81b6b3SRodney W. Grimes dp = &(fdc->head); 10045b81b6b3SRodney W. Grimes bp = dp->b_actf; 10055b81b6b3SRodney W. Grimes 10065b81b6b3SRodney W. Grimes switch(fdc->retry) 10075b81b6b3SRodney W. Grimes { 10085b81b6b3SRodney W. Grimes case 0: case 1: case 2: 10095b81b6b3SRodney W. Grimes fdc->state = SEEKCOMPLETE; 10105b81b6b3SRodney W. Grimes break; 10115b81b6b3SRodney W. Grimes case 3: case 4: case 5: 10125b81b6b3SRodney W. Grimes fdc->state = STARTRECAL; 10135b81b6b3SRodney W. Grimes break; 10145b81b6b3SRodney W. Grimes case 6: 10155b81b6b3SRodney W. Grimes fdc->state = RESETCTLR; 10165b81b6b3SRodney W. Grimes break; 10175b81b6b3SRodney W. Grimes case 7: 10185b81b6b3SRodney W. Grimes break; 10195b81b6b3SRodney W. Grimes default: 10205b81b6b3SRodney W. Grimes { 10217ca0641bSAndrey A. Chernov dev_t sav_b_dev = bp->b_dev; 10227ca0641bSAndrey A. Chernov /* Trick diskerr */ 10237ca0641bSAndrey A. Chernov bp->b_dev = makedev(major(bp->b_dev), (FDUNIT(minor(bp->b_dev))<<3)|3); 102492ed385aSRodney W. Grimes diskerr(bp, "fd", "hard error", LOG_PRINTF, 102592ed385aSRodney W. Grimes fdc->fd->skip, (struct disklabel *)NULL); 10267ca0641bSAndrey A. Chernov bp->b_dev = sav_b_dev; 102792ed385aSRodney W. Grimes printf(" (ST0 %b ", fdc->status[0], NE7_ST0BITS); 10285b81b6b3SRodney W. Grimes printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS); 10295b81b6b3SRodney W. Grimes printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS); 10305b81b6b3SRodney W. Grimes printf("cyl %d hd %d sec %d)\n", 103192ed385aSRodney W. Grimes fdc->status[3], fdc->status[4], fdc->status[5]); 10325b81b6b3SRodney W. Grimes } 10335b81b6b3SRodney W. Grimes bp->b_flags |= B_ERROR; 10345b81b6b3SRodney W. Grimes bp->b_error = EIO; 10355b81b6b3SRodney W. Grimes bp->b_resid = bp->b_bcount - fdc->fd->skip; 10365b81b6b3SRodney W. Grimes dp->b_actf = bp->av_forw; 10375b81b6b3SRodney W. Grimes fdc->fd->skip = 0; 10385b81b6b3SRodney W. Grimes biodone(bp); 103992ed385aSRodney W. Grimes fdc->state = FINDWORK; 10405b81b6b3SRodney W. Grimes fdc->fd = (fd_p) 0; 10415b81b6b3SRodney W. Grimes fdc->fdu = -1; 1042f5f7ba03SJordan K. Hubbard /* XXX abort current command, if any. */ 104392ed385aSRodney W. Grimes return(1); 10445b81b6b3SRodney W. Grimes } 10455b81b6b3SRodney W. Grimes fdc->retry++; 10465b81b6b3SRodney W. Grimes return(1); 10475b81b6b3SRodney W. Grimes } 10485b81b6b3SRodney W. Grimes 1049b39c878eSAndrey A. Chernov static int 1050b39c878eSAndrey A. Chernov fdformat(dev, finfo, p) 1051b39c878eSAndrey A. Chernov dev_t dev; 1052b39c878eSAndrey A. Chernov struct fd_formb *finfo; 1053b39c878eSAndrey A. Chernov struct proc *p; 1054b39c878eSAndrey A. Chernov { 1055b39c878eSAndrey A. Chernov fdu_t fdu; 1056b39c878eSAndrey A. Chernov fd_p fd; 1057b39c878eSAndrey A. Chernov 1058b39c878eSAndrey A. Chernov struct buf *bp; 1059b39c878eSAndrey A. Chernov int rv = 0, s; 1060b39c878eSAndrey A. Chernov 1061b39c878eSAndrey A. Chernov fdu = FDUNIT(minor(dev)); 1062b39c878eSAndrey A. Chernov fd = &fd_data[fdu]; 1063b39c878eSAndrey A. Chernov 1064b39c878eSAndrey A. Chernov /* set up a buffer header for fdstrategy() */ 1065b39c878eSAndrey A. Chernov bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT); 1066b39c878eSAndrey A. Chernov if(bp == 0) 1067b39c878eSAndrey A. Chernov return ENOBUFS; 1068b39c878eSAndrey A. Chernov bzero((void *)bp, sizeof(struct buf)); 1069b39c878eSAndrey A. Chernov bp->b_flags = B_BUSY | B_PHYS | B_FORMAT; 1070b39c878eSAndrey A. Chernov bp->b_proc = p; 1071b39c878eSAndrey A. Chernov bp->b_dev = dev; 1072b39c878eSAndrey A. Chernov 1073b39c878eSAndrey A. Chernov /* 1074b39c878eSAndrey A. Chernov * calculate a fake blkno, so fdstrategy() would initiate a 1075b39c878eSAndrey A. Chernov * seek to the requested cylinder 1076b39c878eSAndrey A. Chernov */ 1077b39c878eSAndrey A. Chernov bp->b_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) 1078b39c878eSAndrey A. Chernov + finfo->head * fd->ft->sectrac) * FDBLK / DEV_BSIZE; 1079b39c878eSAndrey A. Chernov 1080b39c878eSAndrey A. Chernov bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; 1081b39c878eSAndrey A. Chernov bp->b_un.b_addr = (caddr_t)finfo; 1082b39c878eSAndrey A. Chernov 1083b39c878eSAndrey A. Chernov /* now do the format */ 1084b39c878eSAndrey A. Chernov fdstrategy(bp); 1085b39c878eSAndrey A. Chernov 1086b39c878eSAndrey A. Chernov /* ...and wait for it to complete */ 1087b39c878eSAndrey A. Chernov s = splbio(); 1088b39c878eSAndrey A. Chernov while(!(bp->b_flags & B_DONE)) 1089b39c878eSAndrey A. Chernov { 1090b39c878eSAndrey A. Chernov rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); 1091b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1092b39c878eSAndrey A. Chernov break; 1093b39c878eSAndrey A. Chernov } 1094b39c878eSAndrey A. Chernov splx(s); 1095b39c878eSAndrey A. Chernov 1096b39c878eSAndrey A. Chernov if(rv == EWOULDBLOCK) 1097b39c878eSAndrey A. Chernov { 1098b39c878eSAndrey A. Chernov /* timed out */ 1099b39c878eSAndrey A. Chernov biodone(bp); 1100b39c878eSAndrey A. Chernov rv = EIO; 1101b39c878eSAndrey A. Chernov } 1102b39c878eSAndrey A. Chernov free(bp, M_TEMP); 1103b39c878eSAndrey A. Chernov return rv; 1104b39c878eSAndrey A. Chernov } 1105b39c878eSAndrey A. Chernov 1106f5f7ba03SJordan K. Hubbard /* 1107f5f7ba03SJordan K. Hubbard * fdioctl() from jc@irbs.UUCP (John Capo) 1108f5f7ba03SJordan K. Hubbard * i386/i386/conf.c needs to have fdioctl() declared and remove the line that 1109f5f7ba03SJordan K. Hubbard * defines fdioctl to be enxio. 1110f5f7ba03SJordan K. Hubbard * 1111f5f7ba03SJordan K. Hubbard * TODO: Reformat. 1112f5f7ba03SJordan K. Hubbard * Think about allocating buffer off stack. 1113f5f7ba03SJordan K. Hubbard * Don't pass uncast 0's and NULL's to read/write/setdisklabel(). 1114f5f7ba03SJordan K. Hubbard * Watch out for NetBSD's different *disklabel() interface. 1115b39c878eSAndrey A. Chernov * 1116b39c878eSAndrey A. Chernov * Added functionality for floppy formatting 1117b39c878eSAndrey A. Chernov * joerg_wunsch@uriah.sax.de (Joerg Wunsch) 1118f5f7ba03SJordan K. Hubbard */ 11195b81b6b3SRodney W. Grimes 1120f5f7ba03SJordan K. Hubbard int 1121b39c878eSAndrey A. Chernov fdioctl (dev, cmd, addr, flag, p) 1122f5f7ba03SJordan K. Hubbard dev_t dev; 1123f5f7ba03SJordan K. Hubbard int cmd; 1124f5f7ba03SJordan K. Hubbard caddr_t addr; 1125f5f7ba03SJordan K. Hubbard int flag; 1126b39c878eSAndrey A. Chernov struct proc *p; 1127f5f7ba03SJordan K. Hubbard { 1128f5f7ba03SJordan K. Hubbard struct fd_type *fdt; 1129f5f7ba03SJordan K. Hubbard struct disklabel *dl; 1130f5f7ba03SJordan K. Hubbard char buffer[DEV_BSIZE]; 1131f5f7ba03SJordan K. Hubbard int error; 1132f5f7ba03SJordan K. Hubbard 1133f5f7ba03SJordan K. Hubbard error = 0; 1134f5f7ba03SJordan K. Hubbard 1135f5f7ba03SJordan K. Hubbard switch (cmd) 1136f5f7ba03SJordan K. Hubbard { 1137f5f7ba03SJordan K. Hubbard case DIOCGDINFO: 1138f5f7ba03SJordan K. Hubbard bzero(buffer, sizeof (buffer)); 1139f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)buffer; 1140f5f7ba03SJordan K. Hubbard dl->d_secsize = FDBLK; 114192ed385aSRodney W. Grimes fdt = fd_data[FDUNIT(minor(dev))].ft; 1142f5f7ba03SJordan K. Hubbard dl->d_secpercyl = fdt->size / fdt->tracks; 1143f5f7ba03SJordan K. Hubbard dl->d_type = DTYPE_FLOPPY; 1144f5f7ba03SJordan K. Hubbard 1145f5f7ba03SJordan K. Hubbard if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) 1146f5f7ba03SJordan K. Hubbard error = 0; 1147f5f7ba03SJordan K. Hubbard else 1148f5f7ba03SJordan K. Hubbard error = EINVAL; 1149f5f7ba03SJordan K. Hubbard 1150f5f7ba03SJordan K. Hubbard *(struct disklabel *)addr = *dl; 1151f5f7ba03SJordan K. Hubbard break; 1152f5f7ba03SJordan K. Hubbard 1153f5f7ba03SJordan K. Hubbard case DIOCSDINFO: 1154f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1155f5f7ba03SJordan K. Hubbard error = EBADF; 1156f5f7ba03SJordan K. Hubbard break; 1157f5f7ba03SJordan K. Hubbard 1158f5f7ba03SJordan K. Hubbard case DIOCWLABEL: 1159f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1160f5f7ba03SJordan K. Hubbard error = EBADF; 1161f5f7ba03SJordan K. Hubbard break; 1162f5f7ba03SJordan K. Hubbard 1163f5f7ba03SJordan K. Hubbard case DIOCWDINFO: 1164f5f7ba03SJordan K. Hubbard if ((flag & FWRITE) == 0) 1165f5f7ba03SJordan K. Hubbard { 1166f5f7ba03SJordan K. Hubbard error = EBADF; 1167f5f7ba03SJordan K. Hubbard break; 1168f5f7ba03SJordan K. Hubbard } 1169f5f7ba03SJordan K. Hubbard 1170f5f7ba03SJordan K. Hubbard dl = (struct disklabel *)addr; 1171f5f7ba03SJordan K. Hubbard 1172b39c878eSAndrey A. Chernov if (error = setdisklabel ((struct disklabel *)buffer, 1173b39c878eSAndrey A. Chernov dl, 0, NULL)) 1174f5f7ba03SJordan K. Hubbard break; 1175f5f7ba03SJordan K. Hubbard 1176b39c878eSAndrey A. Chernov error = writedisklabel(dev, fdstrategy, 1177b39c878eSAndrey A. Chernov (struct disklabel *)buffer, NULL); 1178b39c878eSAndrey A. Chernov break; 1179b39c878eSAndrey A. Chernov 1180b39c878eSAndrey A. Chernov case FD_FORM: 1181b39c878eSAndrey A. Chernov if((flag & FWRITE) == 0) 1182b39c878eSAndrey A. Chernov error = EBADF; /* must be opened for writing */ 1183b39c878eSAndrey A. Chernov else if(((struct fd_formb *)addr)->format_version != 1184b39c878eSAndrey A. Chernov FD_FORMAT_VERSION) 1185b39c878eSAndrey A. Chernov error = EINVAL; /* wrong version of formatting prog */ 1186b39c878eSAndrey A. Chernov else 1187b39c878eSAndrey A. Chernov error = fdformat(dev, (struct fd_formb *)addr, p); 1188b39c878eSAndrey A. Chernov break; 1189b39c878eSAndrey A. Chernov 1190b39c878eSAndrey A. Chernov case FD_GTYPE: /* get drive type */ 1191b39c878eSAndrey A. Chernov *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft; 1192f5f7ba03SJordan K. Hubbard break; 1193f5f7ba03SJordan K. Hubbard 1194f5f7ba03SJordan K. Hubbard default: 1195f5f7ba03SJordan K. Hubbard error = EINVAL; 1196f5f7ba03SJordan K. Hubbard break; 1197f5f7ba03SJordan K. Hubbard } 1198f5f7ba03SJordan K. Hubbard return (error); 1199f5f7ba03SJordan K. Hubbard } 1200f5f7ba03SJordan K. Hubbard 1201f5f7ba03SJordan K. Hubbard #endif 1202