Home | History | Annotate | Line # | Download | only in obio
iwm_fd.c revision 1.7
      1  1.7   scottr /*	$NetBSD: iwm_fd.c,v 1.7 2000/02/24 05:02:33 scottr Exp $	*/
      2  1.1   scottr 
      3  1.1   scottr /*
      4  1.1   scottr  * Copyright (c) 1997, 1998 Hauke Fath.  All rights reserved.
      5  1.1   scottr  *
      6  1.1   scottr  * Redistribution and use in source and binary forms, with or without
      7  1.1   scottr  * modification, are permitted provided that the following conditions
      8  1.1   scottr  * are met:
      9  1.1   scottr  * 1. Redistributions of source code must retain the above copyright
     10  1.1   scottr  *    notice, this list of conditions and the following disclaimer.
     11  1.1   scottr  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1   scottr  *    notice, this list of conditions and the following disclaimer in the
     13  1.1   scottr  *    documentation and/or other materials provided with the distribution.
     14  1.1   scottr  * 3. The name of the author may not be used to endorse or promote products
     15  1.1   scottr  *    derived from this software without specific prior written permission.
     16  1.1   scottr  *
     17  1.1   scottr  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  1.1   scottr  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  1.1   scottr  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  1.1   scottr  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  1.1   scottr  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  1.1   scottr  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  1.1   scottr  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  1.1   scottr  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  1.1   scottr  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  1.1   scottr  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  1.1   scottr  */
     28  1.1   scottr 
     29  1.1   scottr /*
     30  1.2   scottr  * iwm_fd.c -- Sony (floppy disk) driver for m68k Macintoshes
     31  1.1   scottr  *
     32  1.2   scottr  * The present implementation supports the GCR format (800K) on
     33  1.2   scottr  * non-{DMA,IOP} machines.
     34  1.1   scottr  */
     35  1.1   scottr #include <sys/param.h>
     36  1.1   scottr #include <sys/systm.h>
     37  1.1   scottr #include <sys/kernel.h>
     38  1.1   scottr #include <sys/file.h>
     39  1.1   scottr #include <sys/ioctl.h>
     40  1.1   scottr #include <sys/malloc.h>
     41  1.1   scottr #include <sys/device.h>
     42  1.1   scottr 
     43  1.1   scottr #define FSTYPENAMES
     44  1.2   scottr #define DKTYPENAMES
     45  1.1   scottr #include <sys/disklabel.h>
     46  1.1   scottr 
     47  1.1   scottr #include <sys/disk.h>
     48  1.1   scottr #include <sys/dkbad.h>
     49  1.1   scottr #include <sys/buf.h>
     50  1.1   scottr #include <sys/uio.h>
     51  1.1   scottr #include <sys/stat.h>
     52  1.1   scottr #include <sys/syslog.h>
     53  1.1   scottr #include <sys/conf.h>
     54  1.1   scottr 
     55  1.1   scottr #include <machine/autoconf.h>
     56  1.1   scottr #include <machine/cpu.h>
     57  1.1   scottr 
     58  1.1   scottr #include <mac68k/obio/iwmreg.h>
     59  1.1   scottr #include <mac68k/obio/iwm_fdvar.h>
     60  1.1   scottr 
     61  1.1   scottr 
     62  1.1   scottr /**
     63  1.1   scottr  **	Private functions
     64  1.1   scottr  **/
     65  1.2   scottr static int map_iwm_base __P((vm_offset_t base));
     66  1.1   scottr 
     67  1.1   scottr /* Autoconfig */
     68  1.1   scottr int	iwm_match __P((struct device *, struct cfdata *, void *));
     69  1.1   scottr void	iwm_attach __P((struct device *, struct device *, void *));
     70  1.1   scottr int	iwm_print __P((void *, const char *));
     71  1.1   scottr int	fd_match __P((struct device *, struct cfdata *, void *));
     72  1.1   scottr void	fd_attach __P((struct device *, struct device *, void *));
     73  1.1   scottr int	fd_print __P((void *, const char *));
     74  1.1   scottr 
     75  1.1   scottr /* Disklabel stuff */
     76  1.2   scottr static void fdGetDiskLabel __P((fd_softc_t *fd, dev_t dev));
     77  1.2   scottr static void fdPrintDiskLabel __P((struct disklabel *lp));
     78  1.1   scottr 
     79  1.2   scottr static fdInfo_t *getFDType __P((short unit));
     80  1.2   scottr static fdInfo_t *fdDeviceToType __P((fd_softc_t *fd, dev_t dev));
     81  1.1   scottr 
     82  1.2   scottr static void fdstart __P((fd_softc_t *fd));
     83  1.2   scottr static void remap_geometry __P((daddr_t block, int heads, diskPosition_t *loc));
     84  1.2   scottr static void motor_off __P((void *param));
     85  1.2   scottr static int seek __P((fd_softc_t *fd, int style));
     86  1.2   scottr static int checkTrack __P((diskPosition_t *loc, int debugFlag));
     87  1.2   scottr static int initCylinderCache __P((fd_softc_t *fd));
     88  1.2   scottr static void invalidateCylinderCache __P((fd_softc_t *fd));
     89  1.1   scottr 
     90  1.1   scottr #ifdef _LKM
     91  1.2   scottr static int probe_fd __P((void));
     92  1.1   scottr #endif
     93  1.1   scottr 
     94  1.2   scottr static int fdstart_Init __P((fd_softc_t *fd));
     95  1.2   scottr static int fdstart_Seek __P((fd_softc_t *fd));
     96  1.2   scottr static int fdstart_Read __P((fd_softc_t *fd));
     97  1.2   scottr static int fdstart_Write __P((fd_softc_t *fd));
     98  1.2   scottr static int fdstart_Flush __P((fd_softc_t *fd));
     99  1.2   scottr static int fdstart_IOFinish __P((fd_softc_t *fd));
    100  1.2   scottr static int fdstart_IOErr __P((fd_softc_t *fd));
    101  1.2   scottr static int fdstart_Fault __P((fd_softc_t *fd));
    102  1.2   scottr static int fdstart_Exit __P((fd_softc_t *fd));
    103  1.2   scottr 
    104  1.1   scottr 
    105  1.1   scottr /**
    106  1.1   scottr  **	Driver debugging
    107  1.1   scottr  **/
    108  1.1   scottr 
    109  1.2   scottr #ifdef DEBUG
    110  1.2   scottr #define IWM_DEBUG
    111  1.2   scottr #endif
    112  1.2   scottr 
    113  1.2   scottr 
    114  1.2   scottr static void hexDump __P((u_char *buf, int len));
    115  1.1   scottr 
    116  1.1   scottr /*
    117  1.2   scottr  * Stuff taken from Egan/Teixeira ch 8: 'if(TRACE_FOO)' debug output
    118  1.2   scottr  * statements don't break indentation, and when DEBUG is not defined,
    119  1.2   scottr  * the compiler code optimizer drops them as dead code.
    120  1.1   scottr  */
    121  1.2   scottr #ifdef IWM_DEBUG
    122  1.1   scottr #define M_TRACE_CONFIG	0x0001
    123  1.1   scottr #define M_TRACE_OPEN	0x0002
    124  1.1   scottr #define M_TRACE_CLOSE	0x0004
    125  1.1   scottr #define M_TRACE_READ	0x0008
    126  1.1   scottr #define M_TRACE_WRITE	0x0010
    127  1.1   scottr #define M_TRACE_STRAT	(M_TRACE_READ | M_TRACE_WRITE)
    128  1.1   scottr #define M_TRACE_IOCTL	0x0020
    129  1.1   scottr #define M_TRACE_STEP	0x0040
    130  1.1   scottr #define M_TRACE_ALL	0xFFFF
    131  1.1   scottr 
    132  1.1   scottr #define TRACE_CONFIG	(iwmDebugging & M_TRACE_CONFIG)
    133  1.1   scottr #define TRACE_OPEN	(iwmDebugging & M_TRACE_OPEN)
    134  1.1   scottr #define TRACE_CLOSE	(iwmDebugging & M_TRACE_CLOSE)
    135  1.1   scottr #define TRACE_READ	(iwmDebugging & M_TRACE_READ)
    136  1.1   scottr #define TRACE_WRITE	(iwmDebugging & M_TRACE_WRITE)
    137  1.1   scottr #define TRACE_STRAT	(iwmDebugging & M_TRACE_STRAT)
    138  1.1   scottr #define TRACE_IOCTL	(iwmDebugging & M_TRACE_IOCTL)
    139  1.1   scottr #define TRACE_STEP	(iwmDebugging & M_TRACE_STEP)
    140  1.1   scottr #define TRACE_ALL	(iwmDebugging & M_TRACE_ALL)
    141  1.1   scottr 
    142  1.1   scottr  /* -1 = all active */
    143  1.2   scottr int     iwmDebugging = 0 /* | M_TRACE_OPEN | M_TRACE_STRAT | M_TRACE_IOCTL */ ;
    144  1.1   scottr 
    145  1.1   scottr #else
    146  1.1   scottr #define TRACE_CONFIG	0
    147  1.1   scottr #define TRACE_OPEN	0
    148  1.1   scottr #define TRACE_CLOSE	0
    149  1.1   scottr #define TRACE_READ	0
    150  1.1   scottr #define TRACE_WRITE	0
    151  1.1   scottr #define TRACE_STRAT	0
    152  1.1   scottr #define TRACE_IOCTL	0
    153  1.1   scottr #define TRACE_STEP	0
    154  1.1   scottr #define TRACE_ALL	0
    155  1.1   scottr #endif
    156  1.1   scottr 
    157  1.1   scottr #define DISABLED 	0
    158  1.1   scottr 
    159  1.1   scottr 
    160  1.1   scottr 
    161  1.1   scottr /**
    162  1.1   scottr  ** Module-global Variables
    163  1.1   scottr  **/
    164  1.1   scottr 
    165  1.1   scottr /* The IWM base address */
    166  1.1   scottr u_long IWMBase;
    167  1.1   scottr 
    168  1.1   scottr /*
    169  1.1   scottr  * Table of supported disk types.
    170  1.1   scottr  * The table order seems to be pretty standardized across NetBSD ports, but
    171  1.1   scottr  * then, they are all MFM... So we roll our own for now.
    172  1.1   scottr  */
    173  1.1   scottr static fdInfo_t fdTypes[] = {
    174  1.1   scottr 	{1, 80, 512, 10, 10,  800, 12, 2, IWM_GCR, "400K Sony"},
    175  1.1   scottr 	{2, 80, 512, 10, 20, 1600, 12, 2, IWM_GCR, "800K Sony"}
    176  1.1   scottr };
    177  1.1   scottr 
    178  1.1   scottr /* Table of GCR disk zones for one side (see IM II-211, The Disk Driver) */
    179  1.1   scottr static diskZone_t diskZones[] = {
    180  1.1   scottr 	{16, 12,   0, 191},
    181  1.1   scottr 	{16, 11, 192, 367},
    182  1.1   scottr 	{16, 10, 368, 527},
    183  1.1   scottr 	{16,  9, 528, 671},
    184  1.1   scottr 	{16,  8, 672, 799}
    185  1.1   scottr };
    186  1.1   scottr 
    187  1.1   scottr /* disk(9) framework device switch */
    188  1.1   scottr struct dkdriver fd_dkDriver = {
    189  1.1   scottr 	fdstrategy
    190  1.1   scottr };
    191  1.1   scottr 
    192  1.1   scottr /* Drive format codes/indexes */
    193  1.1   scottr enum {
    194  1.2   scottr 	IWM_400K_GCR = 0,
    195  1.2   scottr 	IWM_800K_GCR = 1,
    196  1.2   scottr 	IWM_720K_MFM = 2,
    197  1.2   scottr 	IWM_1440K_MFM = 3
    198  1.1   scottr };
    199  1.1   scottr 
    200  1.1   scottr 
    201  1.1   scottr /**
    202  1.1   scottr  ** Autoconfiguration code
    203  1.1   scottr  **/
    204  1.1   scottr 
    205  1.1   scottr /*
    206  1.1   scottr  * Autoconfig data structures
    207  1.1   scottr  *
    208  1.1   scottr  * These data structures (see <sys/device.h>) are referenced in
    209  1.1   scottr  * compile/$KERNEL/ioconf.c, which is generated by config(8).
    210  1.1   scottr  * Their names are formed like {device}_{ca,cd}.
    211  1.1   scottr  *
    212  1.2   scottr  * {device}_ca
    213  1.1   scottr  * is used for dynamically allocating driver data, probing and
    214  1.1   scottr  * attaching a device;
    215  1.1   scottr  *
    216  1.1   scottr  * {device}_cd
    217  1.1   scottr  * references all found devices of a type.
    218  1.1   scottr  */
    219  1.1   scottr #ifdef _LKM
    220  1.1   scottr 
    221  1.1   scottr struct cfdriver iwm_cd = {
    222  1.1   scottr 	NULL,			/* Ptr to array of devices found	 */
    223  1.1   scottr 	"iwm",			/* Device name string			 */
    224  1.1   scottr 	DV_DULL,		/* Device classification		 */
    225  1.1   scottr 	0			/* Number of devices found		 */
    226  1.1   scottr };
    227  1.1   scottr struct cfdriver fd_cd = {
    228  1.1   scottr 	NULL,
    229  1.1   scottr 	"fd",
    230  1.1   scottr 	DV_DISK,
    231  1.1   scottr 	0
    232  1.1   scottr };
    233  1.1   scottr 
    234  1.1   scottr #else /* defined _LKM */
    235  1.1   scottr 
    236  1.1   scottr extern struct cfdriver iwm_cd;
    237  1.1   scottr extern struct cfdriver fd_cd;
    238  1.1   scottr 
    239  1.1   scottr #endif /* defined _LKM */
    240  1.1   scottr 
    241  1.1   scottr /* IWM floppy disk controller */
    242  1.1   scottr struct cfattach iwm_ca = {
    243  1.1   scottr 	sizeof(iwm_softc_t),	/* Size of device data for malloc()	 */
    244  1.1   scottr 	iwm_match,		/* Probe device and return match level	 */
    245  1.1   scottr 	iwm_attach		/* Initialize and attach device		 */
    246  1.1   scottr };
    247  1.1   scottr 
    248  1.1   scottr /* Attached floppy disk drives */
    249  1.1   scottr struct cfattach fd_ca = {
    250  1.1   scottr 	sizeof(fd_softc_t),
    251  1.1   scottr 	fd_match,
    252  1.1   scottr 	fd_attach
    253  1.1   scottr };
    254  1.1   scottr 
    255  1.1   scottr 
    256  1.1   scottr 
    257  1.1   scottr /***  Configure the IWM controller  ***/
    258  1.1   scottr 
    259  1.1   scottr /*
    260  1.1   scottr  * iwm_match
    261  1.1   scottr  *
    262  1.2   scottr  * Is the IWM chip present? Here, *auxp is a ptr to struct confargs
    263  1.2   scottr  * (see <mac68k/mac68k/autoconf.h>), which does not hold any information
    264  1.2   scottr  * to match against. After all, that's what the obio concept is
    265  1.2   scottr  * about: Onboard components that are present depending (only)
    266  1.2   scottr  * on machine type.
    267  1.1   scottr  */
    268  1.1   scottr int
    269  1.1   scottr iwm_match(parent, match, auxp)
    270  1.1   scottr 	struct device *parent;
    271  1.1   scottr 	struct cfdata *match;
    272  1.1   scottr 	void *auxp;
    273  1.1   scottr {
    274  1.1   scottr 	int matched;
    275  1.1   scottr #ifdef _LKM
    276  1.1   scottr 	int iwmErr;
    277  1.1   scottr #endif
    278  1.1   scottr 	extern u_long IOBase;		/* from mac68k/machdep.c */
    279  1.1   scottr 	extern u_long IWMBase;
    280  1.1   scottr 
    281  1.1   scottr 	if (0 == map_iwm_base(IOBase)) {
    282  1.1   scottr 		/*
    283  1.1   scottr 		 * Unknown machine HW:
    284  1.1   scottr 		 * The SWIM II/III chips that are present in post-Q700
    285  1.1   scottr 		 * '040 Macs have dropped the IWM register structure.
    286  1.1   scottr 		 * We know next to nothing about the SWIM.
    287  1.1   scottr 		 */
    288  1.1   scottr 		matched = 0;
    289  1.7   scottr 		if (TRACE_CONFIG)
    290  1.7   scottr 			printf("IWM or SWIM not found: Unknown location (SWIM II?).\n");
    291  1.1   scottr 	} else {
    292  1.1   scottr 		matched = 1;
    293  1.1   scottr 		if (TRACE_CONFIG) {
    294  1.1   scottr 			printf("iwm: IWMBase mapped to 0x%lx in VM.\n",
    295  1.1   scottr 			    IWMBase);
    296  1.1   scottr 		}
    297  1.1   scottr #ifdef _LKM
    298  1.1   scottr 		iwmErr = iwmInit();
    299  1.1   scottr 		if (TRACE_CONFIG)
    300  1.1   scottr 			printf("initIWM() says %d.\n", iwmErr);
    301  1.1   scottr 		matched = (iwmErr == 0) ? 1 : 0;
    302  1.1   scottr #endif
    303  1.1   scottr 	}
    304  1.1   scottr 	return matched;
    305  1.1   scottr }
    306  1.1   scottr 
    307  1.1   scottr 
    308  1.1   scottr /*
    309  1.1   scottr  * iwm_attach
    310  1.1   scottr  *
    311  1.1   scottr  * The IWM is present, initialize it. Then look up the connected drives
    312  1.1   scottr  * and attach them.
    313  1.1   scottr  */
    314  1.1   scottr void
    315  1.1   scottr iwm_attach(parent, self, auxp)
    316  1.1   scottr 	struct device *parent;
    317  1.1   scottr 	struct device *self;
    318  1.1   scottr 	void *auxp;
    319  1.1   scottr {
    320  1.1   scottr 	int iwmErr;
    321  1.1   scottr 	iwm_softc_t *iwm;
    322  1.1   scottr 	iwmAttachArgs_t ia;
    323  1.1   scottr 
    324  1.1   scottr 	printf(": Apple GCR floppy disk controller\n");
    325  1.1   scottr 	iwm = (iwm_softc_t *)self;
    326  1.1   scottr 
    327  1.1   scottr 	iwmErr = iwmInit();
    328  1.1   scottr 	if (TRACE_CONFIG)
    329  1.1   scottr 		printf("initIWM() says %d.\n", iwmErr);
    330  1.1   scottr 
    331  1.1   scottr 	if (0 == iwmErr) {
    332  1.1   scottr 		/* Set up the IWM softc */
    333  1.1   scottr 		iwm->maxRetries = 10;
    334  1.1   scottr 
    335  1.1   scottr 		/* Look for attached drives */
    336  1.1   scottr 		for (ia.unit = 0; ia.unit < IWM_MAX_DRIVE; ia.unit++) {
    337  1.1   scottr 			iwm->fd[ia.unit] = NULL;
    338  1.1   scottr 			ia.driveType = getFDType(ia.unit);
    339  1.1   scottr 			if (NULL != ia.driveType)
    340  1.1   scottr 				config_found_sm(self, (void *)&ia,
    341  1.1   scottr 				    fd_print, NULL);
    342  1.1   scottr 		}
    343  1.1   scottr 		if (TRACE_CONFIG)
    344  1.1   scottr 			printf("iwm: Initialization completed.\n");
    345  1.1   scottr 	} else {
    346  1.2   scottr 		printf("iwm: Chip revision not supported (%d)\n", iwmErr);
    347  1.1   scottr 	}
    348  1.1   scottr }
    349  1.1   scottr 
    350  1.1   scottr 
    351  1.1   scottr /*
    352  1.1   scottr  * iwm_print -- print device configuration.
    353  1.1   scottr  *
    354  1.2   scottr  * If the device is not configured 'controller' it is NULL and
    355  1.2   scottr  * we print a message in the *Attach routine; the return value
    356  1.2   scottr  * of *Print() is ignored.
    357  1.1   scottr  */
    358  1.1   scottr int
    359  1.1   scottr iwm_print(auxp, controller)
    360  1.1   scottr 	void *auxp;
    361  1.1   scottr 	const char *controller;
    362  1.1   scottr {
    363  1.1   scottr 	return UNCONF;
    364  1.1   scottr }
    365  1.1   scottr 
    366  1.2   scottr 
    367  1.1   scottr /*
    368  1.1   scottr  * map_iwm_base
    369  1.1   scottr  *
    370  1.1   scottr  * Map physical IO address of IWM to VM address
    371  1.1   scottr  */
    372  1.1   scottr static int
    373  1.2   scottr map_iwm_base(base)
    374  1.2   scottr 	vm_offset_t base;
    375  1.1   scottr {
    376  1.1   scottr 	int known;
    377  1.1   scottr 	extern u_long IWMBase;
    378  1.1   scottr 
    379  1.1   scottr 	switch (current_mac_model->class) {
    380  1.1   scottr 	case MACH_CLASSQ:
    381  1.1   scottr 	case MACH_CLASSQ2:
    382  1.1   scottr 	case MACH_CLASSP580:
    383  1.1   scottr 		IWMBase = base + 0x1E000;
    384  1.1   scottr 		known = 1;
    385  1.1   scottr 		break;
    386  1.1   scottr 	case MACH_CLASSII:
    387  1.1   scottr 	case MACH_CLASSPB:
    388  1.1   scottr 	case MACH_CLASSDUO:
    389  1.1   scottr 	case MACH_CLASSIIci:
    390  1.1   scottr 	case MACH_CLASSIIsi:
    391  1.1   scottr 	case MACH_CLASSIIvx:
    392  1.1   scottr 	case MACH_CLASSLC:
    393  1.1   scottr 		IWMBase = base + 0x16000;
    394  1.1   scottr 		known = 1;
    395  1.1   scottr 		break;
    396  1.1   scottr 	case MACH_CLASSIIfx:
    397  1.1   scottr 	case MACH_CLASSAV:
    398  1.1   scottr 	default:
    399  1.2   scottr 		/*
    400  1.2   scottr 		 * Neither IIfx/Q9[05]0 style IOP controllers nor
    401  1.2   scottr 		 * Q[68]40AV DMA based controllers are supported.
    402  1.2   scottr 		 */
    403  1.7   scottr 		if (TRACE_CONFIG)
    404  1.7   scottr 			printf("Unknown floppy controller chip.\n");
    405  1.1   scottr 		IWMBase = 0L;
    406  1.1   scottr 		known = 0;
    407  1.1   scottr 		break;
    408  1.1   scottr 	}
    409  1.1   scottr 	return known;
    410  1.1   scottr }
    411  1.1   scottr 
    412  1.1   scottr 
    413  1.1   scottr /***  Configure Sony disk drive(s)  ***/
    414  1.1   scottr 
    415  1.1   scottr /*
    416  1.1   scottr  * fd_match
    417  1.1   scottr  */
    418  1.1   scottr int
    419  1.1   scottr fd_match(parent, match, auxp)
    420  1.1   scottr 	struct device *parent;
    421  1.1   scottr 	struct cfdata *match;
    422  1.1   scottr 	void *auxp;
    423  1.1   scottr {
    424  1.1   scottr 	int matched, cfUnit;
    425  1.1   scottr 	struct cfdata *cfp;
    426  1.1   scottr 	iwmAttachArgs_t *fdParams;
    427  1.1   scottr 
    428  1.1   scottr 	cfp = match;
    429  1.1   scottr 	fdParams = (iwmAttachArgs_t *)auxp;
    430  1.1   scottr 	cfUnit = cfp->cf_loc[0];
    431  1.1   scottr 	matched = (cfUnit == fdParams->unit || cfUnit == -1) ? 1 : 0;
    432  1.1   scottr 	if (TRACE_CONFIG) {
    433  1.1   scottr 		printf("fdMatch() drive %d ? cfUnit = %d\n",
    434  1.1   scottr 		    fdParams->unit, cfp->cf_loc[0]);
    435  1.1   scottr 	}
    436  1.1   scottr 	return matched;
    437  1.1   scottr }
    438  1.1   scottr 
    439  1.1   scottr 
    440  1.1   scottr /*
    441  1.1   scottr  * fd_attach
    442  1.1   scottr  *
    443  1.1   scottr  * We have checked that the IWM is fine and the drive is present,
    444  1.1   scottr  * so we can attach it.
    445  1.1   scottr  */
    446  1.1   scottr void
    447  1.1   scottr fd_attach(parent, self, auxp)
    448  1.1   scottr 	struct device *parent;
    449  1.1   scottr 	struct device *self;
    450  1.1   scottr 	void *auxp;
    451  1.1   scottr {
    452  1.1   scottr 	iwm_softc_t *iwm;
    453  1.1   scottr 	fd_softc_t *fd;
    454  1.1   scottr 	iwmAttachArgs_t *ia;
    455  1.1   scottr 	int driveInfo;
    456  1.1   scottr 
    457  1.1   scottr 	iwm = (iwm_softc_t *)parent;
    458  1.1   scottr 	fd = (fd_softc_t *)self;
    459  1.1   scottr 	ia = (iwmAttachArgs_t *)auxp;
    460  1.1   scottr 
    461  1.1   scottr 	driveInfo = iwmCheckDrive(ia->unit);
    462  1.1   scottr 
    463  1.1   scottr 	fd->currentType = ia->driveType;
    464  1.1   scottr 	fd->unit = ia->unit;
    465  1.2   scottr 	fd->defaultType = &fdTypes[IWM_800K_GCR];
    466  1.1   scottr 	fd->stepDirection = 0;
    467  1.1   scottr 
    468  1.1   scottr 	iwm->fd[ia->unit] = fd;		/* iwm has ptr to this drive */
    469  1.1   scottr 	iwm->drives++;
    470  1.5    ender 
    471  1.5    ender 	BUFQ_INIT(&fd->bufQueue);
    472  1.5    ender 
    473  1.1   scottr 	printf(" drive %d: ", fd->unit);
    474  1.1   scottr 
    475  1.1   scottr 	if (IWM_NO_DISK & driveInfo) {
    476  1.1   scottr 		printf("(drive empty)\n");
    477  1.1   scottr 	} else
    478  1.1   scottr 		if (!(IWM_DD_DISK & driveInfo)) {
    479  1.1   scottr 			printf("(HD disk -- not supported)\n");
    480  1.1   scottr 			iwmDiskEject(fd->unit);	/* XXX */
    481  1.1   scottr 		} else {
    482  1.1   scottr 			printf("%s %d cyl, %d head(s)\n",
    483  1.1   scottr 			    fd->currentType->description,
    484  1.1   scottr 			    fd->currentType->tracks,
    485  1.1   scottr 			    fd->currentType->heads);
    486  1.1   scottr 		}
    487  1.1   scottr 	if (TRACE_CONFIG) {
    488  1.1   scottr 		int reg, flags, spl;
    489  1.1   scottr 
    490  1.1   scottr 		/* List contents of drive status registers */
    491  1.2   scottr 		spl = spl6();
    492  1.1   scottr 		for (reg = 0; reg < 0x10; reg++) {
    493  1.1   scottr 			flags = iwmQueryDrvFlag(fd->unit, reg);
    494  1.1   scottr 			printf("iwm: Drive register 0x%x = 0x%x\n", reg, flags);
    495  1.1   scottr 		}
    496  1.1   scottr 		splx(spl);
    497  1.1   scottr 	}
    498  1.1   scottr 	fd->diskInfo.dk_name = fd->devInfo.dv_xname;
    499  1.1   scottr 	fd->diskInfo.dk_driver = &fd_dkDriver;
    500  1.1   scottr 	disk_attach(&fd->diskInfo);
    501  1.1   scottr }
    502  1.1   scottr 
    503  1.1   scottr 
    504  1.1   scottr /*
    505  1.1   scottr  * fdPrint -- print device configuration.
    506  1.1   scottr  *
    507  1.1   scottr  * If the device is not configured 'controller' refers to a name string
    508  1.1   scottr  * we print here.
    509  1.1   scottr  * Else it is NULL and we print a message in the *Attach routine; the
    510  1.1   scottr  * return value of *Print() is ignored.
    511  1.1   scottr  */
    512  1.1   scottr int
    513  1.1   scottr fd_print(auxp, controller)
    514  1.1   scottr 	void *auxp;
    515  1.1   scottr 	const char *controller;
    516  1.1   scottr {
    517  1.1   scottr 	iwmAttachArgs_t *ia;
    518  1.1   scottr 
    519  1.1   scottr 	ia = (iwmAttachArgs_t *)auxp;
    520  1.1   scottr 	if (NULL != controller)
    521  1.1   scottr 		printf("fd%d at %s", ia->unit, controller);
    522  1.1   scottr 	return UNCONF;
    523  1.1   scottr }
    524  1.1   scottr 
    525  1.1   scottr 
    526  1.1   scottr #ifdef _LKM
    527  1.1   scottr 
    528  1.1   scottr static iwm_softc_t *iwm;
    529  1.1   scottr 
    530  1.1   scottr /*
    531  1.1   scottr  * fd_mod_init
    532  1.1   scottr  *
    533  1.1   scottr  * Any initializations necessary after loading the module happen here.
    534  1.1   scottr  */
    535  1.1   scottr int
    536  1.1   scottr fd_mod_init(void)
    537  1.1   scottr {
    538  1.1   scottr 	int err;
    539  1.1   scottr 
    540  1.1   scottr 	iwm = (iwm_softc_t *)malloc(sizeof(iwm_softc_t), M_DEVBUF, M_WAITOK);
    541  1.1   scottr 
    542  1.1   scottr 	err = (1 == iwm_match(NULL, NULL, NULL)) ? 0 : EIO;
    543  1.1   scottr 	if (!err) {
    544  1.2   scottr 		memset(iwm, 0, sizeof(iwm_softc_t));
    545  1.1   scottr 		iwm->maxRetries = 10;
    546  1.1   scottr 		err = (0 == probe_fd()) ? 0 : EIO;
    547  1.1   scottr 	}
    548  1.1   scottr 	return err;
    549  1.1   scottr }
    550  1.1   scottr 
    551  1.1   scottr 
    552  1.1   scottr /*
    553  1.1   scottr  * fd_mod_free
    554  1.1   scottr  *
    555  1.1   scottr  * Necessary clean-up before unloading the module.
    556  1.1   scottr  */
    557  1.1   scottr void
    558  1.1   scottr fd_mod_free(void)
    559  1.1   scottr {
    560  1.1   scottr 	int unit, spl;
    561  1.1   scottr 
    562  1.1   scottr 	spl = splbio();
    563  1.1   scottr 	/* Release any allocated memory */
    564  1.1   scottr 	for (unit = 0; unit < IWM_MAX_DRIVE; unit++)
    565  1.1   scottr 		if (iwm->fd[unit] != NULL) {
    566  1.1   scottr 			/*
    567  1.1   scottr 			 * Let's hope there is only one task per drive,
    568  1.1   scottr 			 * see timeout(9).
    569  1.1   scottr 			 */
    570  1.1   scottr 			untimeout(motor_off, iwm->fd[unit]);
    571  1.1   scottr 			disk_detach(&iwm->fd[unit]->diskInfo);
    572  1.1   scottr 			free(iwm->fd[unit], M_DEVBUF);
    573  1.1   scottr 			iwm->fd[unit] = NULL;
    574  1.1   scottr 		}
    575  1.1   scottr 	free(iwm, M_DEVBUF);
    576  1.1   scottr 	splx(spl);
    577  1.1   scottr }
    578  1.1   scottr 
    579  1.1   scottr 
    580  1.1   scottr /*
    581  1.1   scottr  * probe_fd
    582  1.1   scottr  *
    583  1.1   scottr  * See if there are any drives out there and configure them.
    584  1.1   scottr  * If we find a drive we allocate a softc structure for it and
    585  1.1   scottr  * insert its address into the iwm_softc.
    586  1.1   scottr  *
    587  1.1   scottr  * XXX Merge the remainder of probeFD() with the autoconfig framework.
    588  1.1   scottr  */
    589  1.1   scottr static int
    590  1.1   scottr probe_fd(void)
    591  1.1   scottr {
    592  1.1   scottr 	fd_softc_t *fd;
    593  1.1   scottr 	iwmAttachArgs_t ia;
    594  1.1   scottr 	int err, unit;
    595  1.1   scottr 
    596  1.1   scottr 	err = 0;
    597  1.1   scottr 	for (ia.unit = 0; ia.unit < IWM_MAX_DRIVE; ia.unit++) {
    598  1.1   scottr 		ia.driveType = getFDType(ia.unit);
    599  1.1   scottr 		if (NULL == ia.driveType) {
    600  1.1   scottr 			iwm->fd[ia.unit] = NULL;
    601  1.1   scottr 			continue;
    602  1.1   scottr 		}
    603  1.1   scottr 		fd = (fd_softc_t *)malloc(sizeof(fd_softc_t),
    604  1.1   scottr 		    M_DEVBUF, M_WAITOK);
    605  1.1   scottr 		if (fd == NULL) {
    606  1.1   scottr 			err = ENOMEM;
    607  1.1   scottr 			break;
    608  1.1   scottr 		} else {
    609  1.2   scottr 			memset(fd, 0, sizeof(fd_softc_t));
    610  1.1   scottr 
    611  1.1   scottr 			/* This is usually set by the autoconfig framework */
    612  1.1   scottr 			sprintf(fd->devInfo.dv_xname, "fd%d%c", ia.unit, 'a');
    613  1.1   scottr 			fd_attach((struct device *)iwm, (struct device *)fd,
    614  1.1   scottr 			    &ia);
    615  1.1   scottr 		}
    616  1.1   scottr 	}
    617  1.1   scottr 	if (err) {
    618  1.1   scottr 		/* Release any allocated memory */
    619  1.1   scottr 		for (unit = 0; unit < IWM_MAX_DRIVE; unit++)
    620  1.1   scottr 			if (iwm->fd[unit] != NULL) {
    621  1.1   scottr 				free(iwm->fd[unit], M_DEVBUF);
    622  1.1   scottr 				iwm->fd[unit] = NULL;
    623  1.1   scottr 			}
    624  1.1   scottr 	}
    625  1.1   scottr 	return err;
    626  1.1   scottr }
    627  1.1   scottr 
    628  1.1   scottr #endif /* defined _LKM */
    629  1.1   scottr 
    630  1.1   scottr 
    631  1.1   scottr /**
    632  1.1   scottr  ** Implementation section of driver interface
    633  1.1   scottr  **
    634  1.1   scottr  ** The prototypes for these functions are set up automagically
    635  1.1   scottr  ** by macros in mac68k/conf.c. Their names are generated from {fd}
    636  1.1   scottr  ** and {open,close,strategy,dump,size,read,write}. The driver entry
    637  1.1   scottr  ** points are then plugged into bdevsw[] and cdevsw[].
    638  1.1   scottr  **/
    639  1.1   scottr 
    640  1.1   scottr 
    641  1.1   scottr /*
    642  1.1   scottr  * fdopen
    643  1.1   scottr  *
    644  1.1   scottr  * Open a floppy disk device.
    645  1.1   scottr  */
    646  1.1   scottr int
    647  1.1   scottr fdopen(dev, flags, devType, proc)
    648  1.1   scottr 	dev_t dev;
    649  1.1   scottr 	int flags;
    650  1.1   scottr 	int devType;
    651  1.1   scottr 	struct proc *proc;
    652  1.1   scottr {
    653  1.1   scottr 	fd_softc_t *fd;
    654  1.1   scottr 	fdInfo_t *info;
    655  1.1   scottr 	int partitionMask;
    656  1.1   scottr 	int fdType, fdUnit;
    657  1.1   scottr 	int ierr, err;
    658  1.1   scottr #ifndef _LKM
    659  1.1   scottr 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
    660  1.1   scottr #endif
    661  1.1   scottr 	info = NULL;		/* XXX shut up egcs */
    662  1.1   scottr 
    663  1.1   scottr 	/*
    664  1.1   scottr 	 * See <device.h> for struct cfdriver, <disklabel.h> for
    665  1.2   scottr 	 * DISKUNIT() and <atari/atari/device.h> for getsoftc().
    666  1.1   scottr 	 */
    667  1.1   scottr 	fdType = minor(dev) % MAXPARTITIONS;
    668  1.1   scottr 	fdUnit = minor(dev) / MAXPARTITIONS;
    669  1.1   scottr 	if (TRACE_OPEN)
    670  1.1   scottr 		printf("iwm: Open drive %d", fdUnit);
    671  1.1   scottr 
    672  1.1   scottr 	/* Check if device # is valid */
    673  1.1   scottr 	err = (iwm->drives < fdUnit) ? ENXIO : 0;
    674  1.1   scottr 	if (!err) {
    675  1.1   scottr 		(void)iwmSelectDrive(fdUnit);
    676  1.1   scottr 		if (TRACE_OPEN)
    677  1.1   scottr 			printf(".\n Get softc");
    678  1.1   scottr 
    679  1.1   scottr 		/* Get fd state */
    680  1.1   scottr 		fd = iwm->fd[fdUnit];
    681  1.1   scottr 		err = (NULL == fd) ? ENXIO : 0;
    682  1.1   scottr 	}
    683  1.1   scottr 	if (!err) {
    684  1.1   scottr 		if (fd->state & IWM_FD_IS_OPEN) {
    685  1.1   scottr 			/*
    686  1.1   scottr 			 * Allow multiple open calls only if for identical
    687  1.1   scottr 			 * floppy format.
    688  1.1   scottr 			 */
    689  1.1   scottr 			if (TRACE_OPEN)
    690  1.1   scottr 				printf(".\n Drive already opened!\n");
    691  1.1   scottr 			err = (fd->partition == fdType) ? 0 : ENXIO;
    692  1.1   scottr 		} else {
    693  1.1   scottr 			if (TRACE_OPEN)
    694  1.1   scottr 				printf(".\n Get format info");
    695  1.1   scottr 
    696  1.1   scottr 			/* Get format type */
    697  1.1   scottr 			info = fdDeviceToType(fd, dev);
    698  1.1   scottr 			if (NULL == info) {
    699  1.1   scottr 				err = ENXIO;
    700  1.1   scottr 				if (TRACE_OPEN)
    701  1.1   scottr 					printf(".\n No such drive.\n");
    702  1.1   scottr 			}
    703  1.1   scottr 		}
    704  1.1   scottr 	}
    705  1.1   scottr 	if (!err && !(fd->state & IWM_FD_IS_OPEN)) {
    706  1.1   scottr 		if (TRACE_OPEN)
    707  1.1   scottr 			printf(".\n Set diskInfo flags.\n");
    708  1.1   scottr 
    709  1.2   scottr 		fd->writeLabel = 0;		/* XXX currently unused */
    710  1.1   scottr 		fd->partition = fdType;
    711  1.1   scottr 		fd->currentType = info;
    712  1.1   scottr 		fd->drvFlags = iwmCheckDrive(fd->unit);
    713  1.1   scottr 
    714  1.1   scottr 		if (fd->drvFlags & IWM_NO_DISK) {
    715  1.1   scottr 			err = EIO;
    716  1.1   scottr #ifdef DIAGNOSTIC
    717  1.1   scottr 			printf(" Drive %d is empty.\n", fd->unit);
    718  1.1   scottr #endif
    719  1.2   scottr 		} else {
    720  1.1   scottr 			if (!(fd->drvFlags & IWM_WRITEABLE) && (flags & FWRITE)) {
    721  1.2   scottr 
    722  1.1   scottr 				err = EPERM;
    723  1.1   scottr #ifdef DIAGNOSTIC
    724  1.1   scottr 				printf(" Disk is write protected.\n");
    725  1.1   scottr #endif
    726  1.2   scottr 			} else {
    727  1.1   scottr 				if (!(fd->drvFlags & IWM_DD_DISK)) {
    728  1.1   scottr 					err = ENXIO;
    729  1.1   scottr #ifdef DIAGNOSTIC
    730  1.1   scottr 					printf(" HD format not supported.\n");
    731  1.1   scottr #endif
    732  1.1   scottr 					(void)iwmDiskEject(fd->unit);
    733  1.2   scottr 				} else {
    734  1.1   scottr 					/* We're open now! */
    735  1.1   scottr 					fd->state |= IWM_FD_IS_OPEN;
    736  1.2   scottr 					err = initCylinderCache(fd);
    737  1.2   scottr 				}
    738  1.2   scottr 			}
    739  1.2   scottr 		}
    740  1.1   scottr 	}
    741  1.1   scottr 	if (!err) {
    742  1.1   scottr 		/*
    743  1.1   scottr 		 * Later, we might not want to recalibrate the drive when it
    744  1.1   scottr 		 * is already open. For now, it doesn't hurt.
    745  1.1   scottr 		 */
    746  1.1   scottr 		if (TRACE_OPEN)
    747  1.1   scottr 			printf(" Seek track 00 says");
    748  1.1   scottr 
    749  1.2   scottr 		memset(&fd->pos, 0, sizeof(diskPosition_t));
    750  1.2   scottr 		ierr = seek(fd, IWM_SEEK_RECAL);
    751  1.1   scottr 		if (TRACE_OPEN)
    752  1.1   scottr 			printf(" %d.\n", ierr);
    753  1.2   scottr 		err = (0 == ierr) ? 0 : EIO;
    754  1.1   scottr 	}
    755  1.1   scottr 	if (!err) {
    756  1.1   scottr 		/*
    757  1.1   scottr 		 * Update disklabel if we are not yet open.
    758  1.1   scottr 		 * (We shouldn't be: We are synchronous.)
    759  1.1   scottr 		 */
    760  1.1   scottr 		if (fd->diskInfo.dk_openmask == 0)
    761  1.1   scottr 			fdGetDiskLabel(fd, dev);
    762  1.1   scottr 
    763  1.1   scottr 		partitionMask = (1 << fdType);
    764  1.1   scottr 
    765  1.1   scottr 		switch (devType) {
    766  1.1   scottr 		case S_IFCHR:
    767  1.1   scottr 			fd->diskInfo.dk_copenmask |= partitionMask;
    768  1.1   scottr 			break;
    769  1.1   scottr 
    770  1.1   scottr 		case S_IFBLK:
    771  1.1   scottr 			fd->diskInfo.dk_bopenmask |= partitionMask;
    772  1.1   scottr 			break;
    773  1.1   scottr 		}
    774  1.1   scottr 		fd->diskInfo.dk_openmask =
    775  1.1   scottr 		    fd->diskInfo.dk_copenmask | fd->diskInfo.dk_bopenmask;
    776  1.1   scottr 	}
    777  1.1   scottr 	if (TRACE_OPEN)
    778  1.1   scottr 		printf("iwm: fdopen() says %d.\n", err);
    779  1.1   scottr 	return err;
    780  1.1   scottr }
    781  1.1   scottr 
    782  1.1   scottr 
    783  1.1   scottr /*
    784  1.1   scottr  * fdclose
    785  1.1   scottr  */
    786  1.1   scottr int
    787  1.1   scottr fdclose(dev, flags, devType, proc)
    788  1.1   scottr 	dev_t dev;
    789  1.1   scottr 	int flags;
    790  1.1   scottr 	int devType;
    791  1.1   scottr 	struct proc *proc;
    792  1.1   scottr {
    793  1.1   scottr 	fd_softc_t *fd;
    794  1.1   scottr 	int partitionMask, fdUnit, fdType;
    795  1.1   scottr #ifndef _LKM
    796  1.1   scottr 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
    797  1.1   scottr #endif
    798  1.1   scottr 
    799  1.1   scottr 	if (TRACE_CLOSE)
    800  1.1   scottr 		printf("iwm: Closing driver.");
    801  1.1   scottr 	fdUnit = minor(dev) / MAXPARTITIONS;
    802  1.1   scottr 	fdType = minor(dev) % MAXPARTITIONS;
    803  1.1   scottr 	fd = iwm->fd[fdUnit];
    804  1.2   scottr 	/* release cylinder cache memory */
    805  1.2   scottr 	if (fd->cbuf != NULL)
    806  1.2   scottr 		     free(fd->cbuf, M_DEVBUF);
    807  1.2   scottr 
    808  1.1   scottr 	partitionMask = (1 << fdType);
    809  1.1   scottr 
    810  1.1   scottr 	/* Set state flag. */
    811  1.1   scottr 	fd->state &= ~IWM_FD_IS_OPEN;
    812  1.1   scottr 
    813  1.1   scottr 	switch (devType) {
    814  1.1   scottr 	case S_IFCHR:
    815  1.1   scottr 		fd->diskInfo.dk_copenmask &= ~partitionMask;
    816  1.1   scottr 		break;
    817  1.1   scottr 
    818  1.1   scottr 	case S_IFBLK:
    819  1.1   scottr 		fd->diskInfo.dk_bopenmask &= ~partitionMask;
    820  1.1   scottr 		break;
    821  1.1   scottr 	}
    822  1.1   scottr 	fd->diskInfo.dk_openmask =
    823  1.1   scottr 	    fd->diskInfo.dk_copenmask | fd->diskInfo.dk_bopenmask;
    824  1.1   scottr 	return 0;
    825  1.1   scottr }
    826  1.1   scottr 
    827  1.1   scottr 
    828  1.1   scottr /*
    829  1.1   scottr  * fdioctl
    830  1.1   scottr  *
    831  1.1   scottr  * We deal with all the disk-specific ioctls in <sys/dkio.h> here even if
    832  1.1   scottr  * we do not support them.
    833  1.1   scottr  */
    834  1.1   scottr int
    835  1.1   scottr fdioctl(dev, cmd, data, flags, proc)
    836  1.1   scottr 	dev_t dev;
    837  1.1   scottr 	u_long cmd;
    838  1.1   scottr 	caddr_t data;
    839  1.1   scottr 	int flags;
    840  1.1   scottr 	struct proc *proc;
    841  1.1   scottr {
    842  1.1   scottr 	int result, fdUnit, fdType;
    843  1.1   scottr 	fd_softc_t *fd;
    844  1.1   scottr #ifndef _LKM
    845  1.1   scottr 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
    846  1.1   scottr #endif
    847  1.1   scottr 
    848  1.1   scottr 	if (TRACE_IOCTL)
    849  1.1   scottr 		printf("iwm: Execute ioctl... ");
    850  1.1   scottr 
    851  1.1   scottr 	/* Check if device # is valid and get its softc */
    852  1.1   scottr 	fdUnit = minor(dev) / MAXPARTITIONS;
    853  1.1   scottr 	fdType = minor(dev) % MAXPARTITIONS;
    854  1.1   scottr 	if (fdUnit >= iwm->drives) {
    855  1.1   scottr 		if (TRACE_IOCTL) {
    856  1.1   scottr 			printf("iwm: Wanted device no (%d) is >= %d.\n",
    857  1.1   scottr 			    fdUnit, iwm->drives);
    858  1.1   scottr 		}
    859  1.1   scottr 		return ENXIO;
    860  1.1   scottr 	}
    861  1.1   scottr 	fd = iwm->fd[fdUnit];
    862  1.1   scottr 	result = 0;
    863  1.1   scottr 
    864  1.1   scottr 	switch (cmd) {
    865  1.1   scottr 	case DIOCGDINFO:
    866  1.1   scottr 		if (TRACE_IOCTL)
    867  1.1   scottr 			printf(" DIOCGDINFO: Get in-core disklabel.\n");
    868  1.1   scottr 		*(struct disklabel *) data = *(fd->diskInfo.dk_label);
    869  1.1   scottr 		result = 0;
    870  1.1   scottr 		break;
    871  1.1   scottr 
    872  1.1   scottr 	case DIOCSDINFO:
    873  1.1   scottr 		if (TRACE_IOCTL)
    874  1.1   scottr 			printf(" DIOCSDINFO: Set in-core disklabel.\n");
    875  1.1   scottr 		result = ((flags & FWRITE) == 0) ? EBADF : 0;
    876  1.1   scottr 		if (result == 0)
    877  1.1   scottr 			result = setdisklabel(fd->diskInfo.dk_label,
    878  1.1   scottr 			    (struct disklabel *)data, 0,
    879  1.1   scottr 			    fd->diskInfo.dk_cpulabel);
    880  1.1   scottr 		break;
    881  1.1   scottr 
    882  1.1   scottr 	case DIOCWDINFO:
    883  1.1   scottr 		if (TRACE_IOCTL)
    884  1.1   scottr 			printf(" DIOCWDINFO: Set in-core disklabel "
    885  1.1   scottr 			    "& update disk.\n");
    886  1.1   scottr 		result = ((flags & FWRITE) == 0) ? EBADF : 0;
    887  1.1   scottr 
    888  1.1   scottr 		if (result == 0)
    889  1.1   scottr 			result = setdisklabel(fd->diskInfo.dk_label,
    890  1.1   scottr 			    (struct disklabel *)data, 0,
    891  1.1   scottr 			    fd->diskInfo.dk_cpulabel);
    892  1.1   scottr 		if (result == 0)
    893  1.1   scottr 			result = writedisklabel(dev, fdstrategy,
    894  1.1   scottr 			    fd->diskInfo.dk_label,
    895  1.1   scottr 			    fd->diskInfo.dk_cpulabel);
    896  1.1   scottr 		break;
    897  1.1   scottr 
    898  1.1   scottr 	case DIOCGPART:
    899  1.1   scottr 		if (TRACE_IOCTL)
    900  1.1   scottr 			printf(" DIOCGPART: Get disklabel & partition table.\n");
    901  1.1   scottr 		((struct partinfo *)data)->disklab = fd->diskInfo.dk_label;
    902  1.1   scottr 		((struct partinfo *)data)->part =
    903  1.1   scottr 		    &fd->diskInfo.dk_label->d_partitions[fdType];
    904  1.1   scottr 		result = 0;
    905  1.1   scottr 		break;
    906  1.1   scottr 
    907  1.1   scottr 	case DIOCRFORMAT:
    908  1.1   scottr 	case DIOCWFORMAT:
    909  1.1   scottr 		if (TRACE_IOCTL)
    910  1.1   scottr 			printf(" DIOC{R,W}FORMAT: No formatter support (yet?).\n");
    911  1.1   scottr 		result = EINVAL;
    912  1.1   scottr 		break;
    913  1.1   scottr 
    914  1.1   scottr 	case DIOCSSTEP:
    915  1.1   scottr 		if (TRACE_IOCTL)
    916  1.1   scottr 			printf(" DIOCSSTEP: IWM does step handshake.\n");
    917  1.1   scottr 		result = EINVAL;
    918  1.1   scottr 		break;
    919  1.1   scottr 
    920  1.1   scottr 	case DIOCSRETRIES:
    921  1.1   scottr 		if (TRACE_IOCTL)
    922  1.1   scottr 			printf(" DIOCSRETRIES: Set max. # of retries.\n");
    923  1.1   scottr 		if (*(int *)data < 0)
    924  1.1   scottr 			result = EINVAL;
    925  1.1   scottr 		else {
    926  1.1   scottr 			iwm->maxRetries = *(int *)data;
    927  1.1   scottr 			result = 0;
    928  1.1   scottr 		}
    929  1.1   scottr 		break;
    930  1.1   scottr 
    931  1.1   scottr 	case DIOCWLABEL:
    932  1.1   scottr 		if (TRACE_IOCTL)
    933  1.1   scottr 			printf(" DIOCWLABEL: Set write access to disklabel.\n");
    934  1.1   scottr 		result = ((flags & FWRITE) == 0) ? EBADF : 0;
    935  1.1   scottr 
    936  1.1   scottr 		if (result == 0)
    937  1.1   scottr 			fd->writeLabel = *(int *)data;
    938  1.1   scottr 		break;
    939  1.1   scottr 
    940  1.1   scottr 	case DIOCSBAD:
    941  1.1   scottr 		if (TRACE_IOCTL)
    942  1.1   scottr 			printf(" DIOCSBAD: No bad144-style handling.\n");
    943  1.1   scottr 		result = EINVAL;
    944  1.1   scottr 		break;
    945  1.1   scottr 
    946  1.2   scottr 	case ODIOCEJECT:
    947  1.1   scottr 	case DIOCEJECT:
    948  1.1   scottr 		/* XXX Eject disk only when unlocked */
    949  1.1   scottr 		if (TRACE_IOCTL)
    950  1.1   scottr 			printf(" DIOCEJECT: Eject disk from unit %d.\n",
    951  1.1   scottr 			    fd->unit);
    952  1.1   scottr 		result = iwmDiskEject(fd->unit);
    953  1.1   scottr 		break;
    954  1.1   scottr 
    955  1.1   scottr 	case DIOCLOCK:
    956  1.1   scottr 		/* XXX Use lock to prevent ejectimg a mounted disk */
    957  1.1   scottr 		if (TRACE_IOCTL)
    958  1.1   scottr 			printf(" DIOCLOCK: No need to (un)lock Sony drive.\n");
    959  1.1   scottr 		result = 0;
    960  1.1   scottr 		break;
    961  1.1   scottr 
    962  1.1   scottr 	default:
    963  1.1   scottr 		if (TRACE_IOCTL)
    964  1.1   scottr 			printf(" Not a disk related ioctl!\n");
    965  1.1   scottr 		result = ENOTTY;
    966  1.1   scottr 		break;
    967  1.1   scottr 	}
    968  1.1   scottr 	return result;
    969  1.1   scottr }
    970  1.1   scottr 
    971  1.1   scottr 
    972  1.1   scottr /*
    973  1.1   scottr  * fddump -- We don't dump to a floppy disk.
    974  1.1   scottr  */
    975  1.1   scottr int
    976  1.1   scottr fddump(dev, blkno, va, size)
    977  1.1   scottr 	dev_t dev;
    978  1.1   scottr 	daddr_t blkno;
    979  1.1   scottr 	caddr_t va;
    980  1.1   scottr 	size_t size;
    981  1.1   scottr {
    982  1.1   scottr 	return ENXIO;
    983  1.1   scottr }
    984  1.1   scottr 
    985  1.1   scottr 
    986  1.1   scottr /*
    987  1.1   scottr  * fdsize -- We don't dump to a floppy disk.
    988  1.1   scottr  */
    989  1.1   scottr int
    990  1.1   scottr fdsize(dev)
    991  1.1   scottr 	dev_t dev;
    992  1.1   scottr {
    993  1.1   scottr 	return -1;
    994  1.1   scottr }
    995  1.1   scottr 
    996  1.1   scottr 
    997  1.1   scottr /*
    998  1.1   scottr  * fdread
    999  1.1   scottr  */
   1000  1.1   scottr int
   1001  1.1   scottr fdread(dev, uio, flags)
   1002  1.1   scottr 	dev_t dev;
   1003  1.1   scottr 	struct uio *uio;
   1004  1.1   scottr 	int flags;
   1005  1.1   scottr {
   1006  1.2   scottr 	return physio(fdstrategy, NULL, dev, B_READ, minphys, uio);
   1007  1.1   scottr }
   1008  1.1   scottr 
   1009  1.1   scottr 
   1010  1.1   scottr /*
   1011  1.1   scottr  * fdwrite
   1012  1.1   scottr  */
   1013  1.1   scottr int
   1014  1.1   scottr fdwrite(dev, uio, flags)
   1015  1.1   scottr 	dev_t dev;
   1016  1.1   scottr 	struct uio *uio;
   1017  1.1   scottr 	int flags;
   1018  1.1   scottr {
   1019  1.2   scottr 	return physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio);
   1020  1.1   scottr }
   1021  1.1   scottr 
   1022  1.1   scottr 
   1023  1.1   scottr /*
   1024  1.2   scottr  * fdstrategy
   1025  1.1   scottr  *
   1026  1.2   scottr  * Entry point for read and write requests. The strategy routine usually
   1027  1.2   scottr  * queues io requests and kicks off the next transfer if the device is idle;
   1028  1.2   scottr  * but we get no interrupts from the IWM and have to do synchronous
   1029  1.2   scottr  * transfers - no queue.
   1030  1.1   scottr  */
   1031  1.2   scottr void
   1032  1.2   scottr fdstrategy(bp)
   1033  1.2   scottr 	struct buf *bp;
   1034  1.2   scottr {
   1035  1.2   scottr 	int fdUnit, err, done, spl;
   1036  1.2   scottr 	int sectSize, transferSize;
   1037  1.2   scottr 	diskPosition_t physDiskLoc;
   1038  1.1   scottr 	fd_softc_t *fd;
   1039  1.1   scottr #ifndef _LKM
   1040  1.1   scottr 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
   1041  1.1   scottr #endif
   1042  1.1   scottr 
   1043  1.2   scottr 	err = 0;
   1044  1.2   scottr 	done = 0;
   1045  1.1   scottr 
   1046  1.2   scottr 	fdUnit = minor(bp->b_dev) / MAXPARTITIONS;
   1047  1.2   scottr 	if (TRACE_STRAT) {
   1048  1.2   scottr 		printf("iwm: fdstrategy()...\n");
   1049  1.2   scottr 		printf("     struct buf is at %p\n", bp);
   1050  1.2   scottr 		printf("     Allocated buffer size (b_bufsize): 0x0%lx\n",
   1051  1.2   scottr 		    bp->b_bufsize);
   1052  1.2   scottr 		printf("     Base address of buffer (b_un.b_addr): %p\n",
   1053  1.2   scottr 		    bp->b_un.b_addr);
   1054  1.2   scottr 		printf("     Bytes to be transferred (b_bcount): 0x0%lx\n",
   1055  1.2   scottr 		    bp->b_bcount);
   1056  1.2   scottr 		printf("     Remaining I/O (b_resid): 0x0%lx\n",
   1057  1.2   scottr 		    bp->b_resid);
   1058  1.1   scottr 	}
   1059  1.2   scottr 	/* Check for valid fd unit, controller and io request */
   1060  1.1   scottr 
   1061  1.2   scottr 	if (fdUnit >= iwm->drives) {
   1062  1.1   scottr 		if (TRACE_STRAT)
   1063  1.2   scottr 			printf(" No such unit (%d)\n", fdUnit);
   1064  1.2   scottr 		err = EINVAL;
   1065  1.2   scottr 	}
   1066  1.2   scottr 	if (!err) {
   1067  1.2   scottr 		fd = iwm->fd[fdUnit];
   1068  1.2   scottr 		err = (NULL == fd) ? EINVAL : 0;
   1069  1.2   scottr 	}
   1070  1.2   scottr 	if (!err) {
   1071  1.2   scottr 		sectSize = fd->currentType->sectorSize;
   1072  1.2   scottr 		if (bp->b_blkno < 0
   1073  1.2   scottr 		    || (bp->b_bcount % sectSize) != 0) {
   1074  1.1   scottr 			if (TRACE_STRAT)
   1075  1.2   scottr 				printf(" Illegal transfer size: "
   1076  1.2   scottr 				    "block %d, %ld bytes\n",
   1077  1.2   scottr 				    bp->b_blkno, bp->b_bcount);
   1078  1.2   scottr 			err = EINVAL;
   1079  1.2   scottr 		}
   1080  1.2   scottr 	}
   1081  1.2   scottr 	if (!err) {
   1082  1.2   scottr 		/* Null transfer: Return, nothing to do. */
   1083  1.2   scottr 		if (0 == bp->b_bcount) {
   1084  1.1   scottr 			if (TRACE_STRAT)
   1085  1.2   scottr 				printf(" Zero transfer length.\n");
   1086  1.2   scottr 			done = 1;
   1087  1.2   scottr 		}
   1088  1.2   scottr 	}
   1089  1.2   scottr 	if (!err && !done) {
   1090  1.2   scottr 		/* What to do if we touch the boundaries of the disk? */
   1091  1.2   scottr 		transferSize = (bp->b_bcount + (sectSize - 1)) / sectSize;
   1092  1.2   scottr 		if (bp->b_blkno + transferSize > fd->currentType->secPerDisk) {
   1093  1.2   scottr 			if (TRACE_STRAT) {
   1094  1.2   scottr 				printf("iwm: Transfer beyond end of disk!\n" \
   1095  1.2   scottr 				    " (Starting block %d, # of blocks %d," \
   1096  1.2   scottr 				    " last disk block %d).\n",
   1097  1.2   scottr 				    bp->b_blkno, transferSize,
   1098  1.2   scottr 				    fd->currentType->secPerDisk);
   1099  1.2   scottr 			}
   1100  1.2   scottr 			/* Return EOF if we are exactly at the end of the
   1101  1.2   scottr 			 * disk, EINVAL if we try to reach past the end; else
   1102  1.2   scottr 			 * truncate the request. */
   1103  1.2   scottr 			transferSize = fd->currentType->secPerDisk -
   1104  1.2   scottr 			    bp->b_blkno;
   1105  1.2   scottr 			if (0 == transferSize) {
   1106  1.2   scottr 				bp->b_resid = bp->b_bcount;
   1107  1.2   scottr 				done = 1;
   1108  1.2   scottr 			} else
   1109  1.2   scottr 				if (0 > transferSize)
   1110  1.2   scottr 					err = EINVAL;
   1111  1.2   scottr 				else
   1112  1.2   scottr 					bp->b_bcount = transferSize << DEV_BSHIFT;
   1113  1.2   scottr 		}
   1114  1.2   scottr 	}
   1115  1.2   scottr 	if (!err && !done) {
   1116  1.2   scottr 		/*
   1117  1.2   scottr 		 * Calculate cylinder # for disksort().
   1118  1.2   scottr 		 *
   1119  1.2   scottr 		 * XXX Shouldn't we use the (fake) logical cyl no here?
   1120  1.2   scottr 		 */
   1121  1.2   scottr 		remap_geometry(bp->b_blkno, fd->currentType->heads,
   1122  1.2   scottr 		    &physDiskLoc);
   1123  1.6  thorpej 		bp->b_rawblkno = bp->b_blkno;
   1124  1.2   scottr 		bp->b_cylinder = physDiskLoc.track;
   1125  1.2   scottr 
   1126  1.2   scottr 		if (TRACE_STRAT) {
   1127  1.2   scottr 			printf(" This job starts at b_blkno %d; ",
   1128  1.2   scottr 			    bp->b_blkno);
   1129  1.2   scottr 			printf("it gets sorted for cylinder # %ld.\n",
   1130  1.2   scottr 			    bp->b_cylinder);
   1131  1.2   scottr 		}
   1132  1.2   scottr 		spl = splbio();
   1133  1.2   scottr 		untimeout(motor_off, fd);
   1134  1.4  thorpej 		disksort_cylinder(&fd->bufQueue, bp);
   1135  1.4  thorpej 		if (fd->sc_active == 0)
   1136  1.2   scottr 			fdstart(fd);
   1137  1.2   scottr 		splx(spl);
   1138  1.2   scottr 	}
   1139  1.2   scottr 	/* Clean up, if necessary */
   1140  1.2   scottr 	else {
   1141  1.2   scottr 		if (TRACE_STRAT)
   1142  1.2   scottr 			printf(" fdstrategy() finished early, err = %d.\n",
   1143  1.2   scottr 			    err);
   1144  1.2   scottr 		if (err) {
   1145  1.2   scottr 			bp->b_error = err;
   1146  1.2   scottr 			bp->b_flags |= B_ERROR;
   1147  1.2   scottr 		}
   1148  1.2   scottr 		bp->b_resid = bp->b_bcount;
   1149  1.2   scottr 		biodone(bp);
   1150  1.2   scottr 	}
   1151  1.2   scottr 	/* Comment on results */
   1152  1.2   scottr 	if (TRACE_STRAT) {
   1153  1.2   scottr 		printf("iwm: fdstrategy() done.\n");
   1154  1.2   scottr 		printf("     We have b_resid = %ld bytes left, " \
   1155  1.2   scottr 		    "b_error is %d;\n", bp->b_resid, bp->b_error);
   1156  1.2   scottr 		printf("     b_flags are 0x0%lx.\n", bp->b_flags);
   1157  1.2   scottr 	}
   1158  1.2   scottr }
   1159  1.2   scottr 
   1160  1.2   scottr 
   1161  1.2   scottr 
   1162  1.2   scottr /* ======================================================================== */
   1163  1.2   scottr 
   1164  1.2   scottr 
   1165  1.2   scottr /*
   1166  1.2   scottr  * fdstart
   1167  1.2   scottr  *
   1168  1.2   scottr  * we are called from the strategy() routine to perform a data transfer.
   1169  1.2   scottr  *
   1170  1.2   scottr  * The disk(9) framework demands we run at splbio(); our caller
   1171  1.2   scottr  * takes care of that.
   1172  1.2   scottr  *
   1173  1.2   scottr  * Wish we had pascalish local functions here...
   1174  1.2   scottr  */
   1175  1.2   scottr 
   1176  1.2   scottr /* fdstart FSM states */
   1177  1.2   scottr enum {
   1178  1.2   scottr 	state_Init = 0,
   1179  1.2   scottr 	state_Seek,
   1180  1.2   scottr 	state_Read,
   1181  1.2   scottr 	state_Write,
   1182  1.2   scottr 	state_Flush,
   1183  1.2   scottr 	state_IOFinish,
   1184  1.2   scottr 	state_IOErr,
   1185  1.2   scottr 	state_Fault,
   1186  1.2   scottr 	state_Exit,
   1187  1.2   scottr 	state_Done
   1188  1.2   scottr };
   1189  1.2   scottr 
   1190  1.2   scottr static void
   1191  1.2   scottr fdstart(fd)
   1192  1.2   scottr 	fd_softc_t *fd;
   1193  1.2   scottr {
   1194  1.2   scottr 	int st;
   1195  1.2   scottr 
   1196  1.2   scottr 	static char *stateDesc[] = {
   1197  1.2   scottr 		"Init",
   1198  1.2   scottr 		"Seek",
   1199  1.2   scottr 		"Read",
   1200  1.2   scottr 		"Write",
   1201  1.2   scottr 		"Flush",
   1202  1.2   scottr 		"IOFinish",
   1203  1.2   scottr 		"IOErr",
   1204  1.2   scottr 		"Fault",
   1205  1.2   scottr 		"Exit",
   1206  1.2   scottr 		"Done"
   1207  1.2   scottr 	};
   1208  1.2   scottr 	int (*state[])(fd_softc_t *fd) = {
   1209  1.2   scottr 		fdstart_Init,
   1210  1.2   scottr 		fdstart_Seek,
   1211  1.2   scottr 		fdstart_Read,
   1212  1.2   scottr 		fdstart_Write,
   1213  1.2   scottr 		fdstart_Flush,
   1214  1.2   scottr 		fdstart_IOFinish,
   1215  1.2   scottr 		fdstart_IOErr,
   1216  1.2   scottr 		fdstart_Fault,
   1217  1.2   scottr 		fdstart_Exit
   1218  1.2   scottr 	};
   1219  1.2   scottr 
   1220  1.2   scottr 	st = state_Init;
   1221  1.2   scottr 	do {
   1222  1.2   scottr 		if (TRACE_STRAT)
   1223  1.2   scottr 			printf(" fdstart state %d [%s] ",
   1224  1.2   scottr 			    st, stateDesc[st]);
   1225  1.2   scottr 
   1226  1.2   scottr 		st = (*state[st])(fd);
   1227  1.2   scottr 
   1228  1.2   scottr 		if (TRACE_STRAT)
   1229  1.2   scottr 			printf(".\n");
   1230  1.2   scottr 	} while (st != state_Done);
   1231  1.2   scottr }
   1232  1.2   scottr 
   1233  1.2   scottr 
   1234  1.2   scottr /*
   1235  1.2   scottr  * fdstart_Init
   1236  1.2   scottr  *
   1237  1.2   scottr  * Set up things
   1238  1.2   scottr  */
   1239  1.2   scottr static int
   1240  1.2   scottr fdstart_Init(fd)
   1241  1.2   scottr 	fd_softc_t *fd;
   1242  1.2   scottr {
   1243  1.2   scottr 	struct buf *bp;
   1244  1.2   scottr 
   1245  1.2   scottr 	/*
   1246  1.2   scottr 	 * Get the first entry from the queue. This is the buf we gave to
   1247  1.2   scottr 	 * fdstrategy(); disksort() put it into our softc.
   1248  1.2   scottr 	 */
   1249  1.4  thorpej 	bp = BUFQ_FIRST(&fd->bufQueue);
   1250  1.2   scottr 	if (NULL == bp) {
   1251  1.2   scottr 		if (TRACE_STRAT)
   1252  1.2   scottr 			printf("Queue empty: Nothing to do");
   1253  1.2   scottr 		return state_Done;
   1254  1.2   scottr 	}
   1255  1.2   scottr 	fd->ioDirection = bp->b_flags & B_READ;
   1256  1.2   scottr 
   1257  1.2   scottr 	disk_busy(&fd->diskInfo);
   1258  1.2   scottr 	if (!(fd->state & IWM_FD_MOTOR_ON)) {
   1259  1.2   scottr 		iwmMotor(fd->unit, 1);
   1260  1.2   scottr 		fd->state |= IWM_FD_MOTOR_ON;
   1261  1.2   scottr 	}
   1262  1.2   scottr 	fd->current_buffer = bp->b_un.b_addr;
   1263  1.2   scottr 
   1264  1.2   scottr 	/* XXX - assumes blocks of 512 bytes */
   1265  1.2   scottr 	fd->startBlk = bp->b_blkno;
   1266  1.2   scottr 
   1267  1.2   scottr 	fd->iwmErr = 0;
   1268  1.2   scottr 	fd->ioRetries = 0;		/* XXX */
   1269  1.2   scottr 	fd->seekRetries = 0;
   1270  1.2   scottr 	fd->bytesDone = 0;
   1271  1.2   scottr 	fd->bytesLeft = bp->b_bcount;
   1272  1.2   scottr 	return state_Seek;
   1273  1.2   scottr }
   1274  1.2   scottr 
   1275  1.2   scottr 
   1276  1.2   scottr /*
   1277  1.2   scottr  * fdstart_Seek
   1278  1.2   scottr  */
   1279  1.2   scottr static int
   1280  1.2   scottr fdstart_Seek(fd)
   1281  1.2   scottr 	fd_softc_t *fd;
   1282  1.2   scottr {
   1283  1.2   scottr 	int state;
   1284  1.2   scottr 
   1285  1.2   scottr 	/* Calculate the side/track/sector our block is at. */
   1286  1.2   scottr 	if (TRACE_STRAT)
   1287  1.2   scottr 		printf(" Remap block %d ", fd->startBlk);
   1288  1.2   scottr 	remap_geometry(fd->startBlk,
   1289  1.2   scottr 	    fd->currentType->heads, &fd->pos);
   1290  1.2   scottr 	if (TRACE_STRAT)
   1291  1.2   scottr 		printf("to c%d_h%d_s%d ", fd->pos.track,
   1292  1.2   scottr 		    fd->pos.side, fd->pos.sector);
   1293  1.2   scottr 
   1294  1.2   scottr 	if (fd->cachedSide != fd->pos.side) {
   1295  1.2   scottr 		if (TRACE_STRAT)
   1296  1.2   scottr 			printf(" (invalidate cache) ");
   1297  1.2   scottr 		invalidateCylinderCache(fd);
   1298  1.2   scottr 		fd->cachedSide = fd->pos.side;
   1299  1.2   scottr 	}
   1300  1.2   scottr 
   1301  1.2   scottr 	/*
   1302  1.2   scottr 	 * If necessary, seek to wanted track. Note that
   1303  1.2   scottr 	 * seek() performs any necessary retries.
   1304  1.2   scottr 	 */
   1305  1.2   scottr 	if (fd->pos.track != fd->pos.oldTrack &&
   1306  1.2   scottr 	    0 != (fd->iwmErr = seek(fd, IWM_SEEK_VANILLA))) {
   1307  1.2   scottr 		state = state_Fault;
   1308  1.2   scottr 	} else {
   1309  1.2   scottr 		state = (fd->ioDirection == IWM_WRITE)
   1310  1.2   scottr 		    ? state_Write : state_Read;
   1311  1.2   scottr 	}
   1312  1.2   scottr 	return state;
   1313  1.2   scottr }
   1314  1.2   scottr 
   1315  1.2   scottr 
   1316  1.2   scottr /*
   1317  1.2   scottr  * fdstart_Read
   1318  1.2   scottr  *
   1319  1.2   scottr  * Transfer a sector from disk. Get it from the track cache, if available;
   1320  1.2   scottr  * otherwise, while we are at it, store in the cache all the sectors we find
   1321  1.2   scottr  * on the way.
   1322  1.2   scottr  *
   1323  1.2   scottr  * Track buffering reads:
   1324  1.2   scottr  * o  Look if the sector is already cached.
   1325  1.2   scottr  * o  Else, read sectors into track cache until we meet the header of
   1326  1.2   scottr  *    the sector we want.
   1327  1.2   scottr  * o  Read that sector directly to fs buffer and return.
   1328  1.2   scottr  */
   1329  1.2   scottr static int
   1330  1.2   scottr fdstart_Read(fd)
   1331  1.2   scottr 	fd_softc_t *fd;
   1332  1.2   scottr {
   1333  1.2   scottr 	int i;
   1334  1.2   scottr 	diskPosition_t *pos;
   1335  1.2   scottr 	sectorHdr_t *shdr;
   1336  1.2   scottr #ifndef _LKM
   1337  1.2   scottr 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
   1338  1.2   scottr #endif
   1339  1.2   scottr 
   1340  1.2   scottr 	/* Initialize retry counters */
   1341  1.2   scottr 	fd->seekRetries = 0;
   1342  1.2   scottr 	fd->sectRetries = 0;
   1343  1.2   scottr 	pos = &fd->pos;
   1344  1.2   scottr 	shdr = &fd->sHdr;
   1345  1.2   scottr 
   1346  1.2   scottr 	if (TRACE_STRAT)
   1347  1.2   scottr 		printf("<%s c%d_h%d_s%d> ",
   1348  1.2   scottr 		    fd->ioDirection ? "Read" : "Write",
   1349  1.2   scottr 		    pos->track, pos->side, pos->sector);
   1350  1.2   scottr 
   1351  1.2   scottr 	/* Sector already cached? */
   1352  1.2   scottr 	i = pos->sector;
   1353  1.2   scottr 	if (fd->r_slots[i].valid) {
   1354  1.2   scottr 		if (TRACE_STRAT)
   1355  1.2   scottr 			printf("(cached)");
   1356  1.2   scottr 		memcpy(fd->current_buffer, fd->r_slots[i].secbuf,
   1357  1.2   scottr 		    fd->currentType->sectorSize);
   1358  1.2   scottr 		return state_IOFinish;
   1359  1.2   scottr 	}
   1360  1.2   scottr 
   1361  1.2   scottr 	/* Get sector from disk */
   1362  1.2   scottr 	shdr->side = pos->side;
   1363  1.2   scottr 	shdr->sector = pos->sector;
   1364  1.2   scottr 	shdr->track = pos->track;
   1365  1.2   scottr 
   1366  1.2   scottr 	(void)iwmSelectSide(pos->side);
   1367  1.2   scottr 	fd->iwmErr = iwmReadSector(&fd->sHdr, fd->r_slots,
   1368  1.2   scottr 	    fd->current_buffer);
   1369  1.2   scottr 
   1370  1.2   scottr 	/* Check possible error conditions */
   1371  1.2   scottr 	if (TRACE_STRAT)
   1372  1.2   scottr 		printf("c%d_h%d_s%d_err(%d)_sr%d ",
   1373  1.2   scottr 		    shdr->track, shdr->side >> 3,
   1374  1.2   scottr 		    shdr->sector, fd->iwmErr, fd->sectRetries);
   1375  1.2   scottr 
   1376  1.2   scottr 	/* IWM IO error? */
   1377  1.2   scottr 	if (fd->iwmErr != 0)
   1378  1.2   scottr 		return state_IOErr;
   1379  1.2   scottr 
   1380  1.2   scottr 	/* Bad seek? Retry */
   1381  1.2   scottr 	if (shdr->track != pos->track) {
   1382  1.2   scottr 		if (TRACE_STRAT) {
   1383  1.2   scottr 			printf("Wanted track %d, got %d, %d seek retries.\n",
   1384  1.2   scottr 			    pos->track, shdr->track, fd->seekRetries);
   1385  1.2   scottr 		}
   1386  1.2   scottr 		if (iwm->maxRetries > fd->seekRetries++) {
   1387  1.2   scottr 			fd->iwmErr = seek(fd, IWM_SEEK_RECAL);
   1388  1.2   scottr 			if (TRACE_STRAT) {
   1389  1.2   scottr 				printf("[%d]", fd->seekRetries);
   1390  1.2   scottr 				(void)checkTrack(&fd->pos, 1);
   1391  1.2   scottr 			}
   1392  1.2   scottr 		} else
   1393  1.2   scottr 			fd->iwmErr = seekErr;
   1394  1.2   scottr 		return (0 == fd->iwmErr) ? state_Read : state_Fault;
   1395  1.2   scottr 	}
   1396  1.2   scottr 
   1397  1.2   scottr 	/* Sector not found? */
   1398  1.2   scottr 	if (shdr->sector != pos->sector) {
   1399  1.2   scottr 		if (TRACE_STRAT)
   1400  1.2   scottr 			printf("c%d_h%d_s%d sect not found, %d retries ",
   1401  1.2   scottr 			    shdr->track, shdr->side >> 3,
   1402  1.2   scottr 			    shdr->sector, fd->sectRetries);
   1403  1.2   scottr 		fd->iwmErr = noAdrMkErr;
   1404  1.2   scottr 		return state_Fault;
   1405  1.2   scottr 	}
   1406  1.2   scottr 
   1407  1.2   scottr 	/* Success */
   1408  1.2   scottr 	return state_IOFinish;
   1409  1.2   scottr }
   1410  1.2   scottr 
   1411  1.2   scottr 
   1412  1.2   scottr /*
   1413  1.2   scottr  * fdstart_Write
   1414  1.2   scottr  *
   1415  1.2   scottr  * Insert a sector into a write buffer slot and mark the slot dirty.
   1416  1.2   scottr  */
   1417  1.2   scottr static int
   1418  1.2   scottr fdstart_Write(fd)
   1419  1.2   scottr 	fd_softc_t *fd;
   1420  1.2   scottr {
   1421  1.2   scottr 	int i;
   1422  1.2   scottr 
   1423  1.2   scottr 	/* XXX let's see... */
   1424  1.2   scottr 	fd->sHdr.side = fd->pos.side;
   1425  1.2   scottr 	fd->sHdr.sector = fd->pos.sector;
   1426  1.2   scottr 	fd->sHdr.track = fd->pos.track;
   1427  1.2   scottr 
   1428  1.2   scottr 	i = fd->pos.sector;
   1429  1.2   scottr 	fd->w_slots[i].secbuf = fd->current_buffer;
   1430  1.2   scottr 	fd->w_slots[i].valid = 1;	/* "valid" is a dirty buffer here */
   1431  1.2   scottr 
   1432  1.2   scottr 	if (TRACE_STRAT)
   1433  1.2   scottr 		printf("<%s c%d_h%d_s%d> (cached) ",
   1434  1.2   scottr 		    fd->ioDirection ? "Read" : "Write",
   1435  1.2   scottr 		    fd->pos.track, fd->pos.side, fd->pos.sector);
   1436  1.2   scottr 	return state_IOFinish;
   1437  1.2   scottr }
   1438  1.2   scottr 
   1439  1.2   scottr 
   1440  1.2   scottr 
   1441  1.2   scottr /*
   1442  1.2   scottr  * fdstart_Flush
   1443  1.2   scottr  *
   1444  1.2   scottr  * Flush dirty buffers in the track cache to disk.
   1445  1.2   scottr  */
   1446  1.2   scottr static int
   1447  1.2   scottr fdstart_Flush(fd)
   1448  1.2   scottr 	fd_softc_t *fd;
   1449  1.2   scottr {
   1450  1.2   scottr 	int state;
   1451  1.2   scottr 	int i, dcnt;
   1452  1.2   scottr 	diskPosition_t *pos;
   1453  1.2   scottr 	sectorHdr_t *shdr;
   1454  1.2   scottr #ifndef _LKM
   1455  1.2   scottr 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
   1456  1.2   scottr #endif
   1457  1.2   scottr 	dcnt = 0;
   1458  1.2   scottr 	pos = &fd->pos;
   1459  1.2   scottr 	shdr = &fd->sHdr;
   1460  1.2   scottr 
   1461  1.2   scottr 	if (TRACE_STRAT) {
   1462  1.2   scottr 		for (i=0; i < IWM_MAX_GCR_SECTORS; i++)
   1463  1.2   scottr 			if (fd->w_slots[i].valid) {
   1464  1.2   scottr 				printf("|%d", i);
   1465  1.2   scottr 				dcnt++;
   1466  1.2   scottr 			}
   1467  1.2   scottr 		printf("|\n");
   1468  1.2   scottr 
   1469  1.2   scottr 		printf(" <%s c%d_h%d_#s%d>\n",
   1470  1.2   scottr 		    fd->ioDirection ? "Read" : "Write",
   1471  1.2   scottr 		    pos->track, pos->side, dcnt);
   1472  1.2   scottr 	}
   1473  1.2   scottr 	(void)iwmSelectSide(pos->side);
   1474  1.2   scottr 	fd->iwmErr = iwmWriteSector(&fd->sHdr, fd->w_slots);
   1475  1.2   scottr 
   1476  1.2   scottr 	switch (fd->iwmErr) {
   1477  1.2   scottr 	case noErr:		/* Success */
   1478  1.2   scottr #ifdef DIAGNOSTIC
   1479  1.2   scottr 		/* XXX Panic if buffer not clean? */
   1480  1.2   scottr 		for (i=0; i<IWM_MAX_GCR_SECTORS; i++)
   1481  1.2   scottr 			if (0 != fd->w_slots[i].valid)
   1482  1.2   scottr 				printf("Oops! <c%d_h%d_s%d> not flushed.\n",
   1483  1.2   scottr 				    fd->pos.track, fd->pos.side,
   1484  1.2   scottr 				    fd->pos.sector);
   1485  1.2   scottr #endif
   1486  1.2   scottr 		if (TRACE_STRAT)
   1487  1.2   scottr 			printf("(Cache flushed, re-initialize) ");
   1488  1.2   scottr 		for (i=0; i < IWM_MAX_GCR_SECTORS; i++) {
   1489  1.2   scottr 			fd->w_slots[i].valid = 0;
   1490  1.2   scottr 			fd->w_slots[i].secbuf = NULL;
   1491  1.2   scottr 		}
   1492  1.2   scottr 		fd->seekRetries = 0;
   1493  1.2   scottr 		state = state_Exit;
   1494  1.2   scottr 		break;
   1495  1.2   scottr 
   1496  1.2   scottr 	case seekErr:		/* Bad seek? Retry */
   1497  1.2   scottr 		if (TRACE_STRAT) {
   1498  1.2   scottr 			printf("Wanted track %d, got %d, %d seek retries.\n",
   1499  1.2   scottr 			    pos->track, shdr->track, fd->seekRetries);
   1500  1.2   scottr 		}
   1501  1.2   scottr 		if (iwm->maxRetries > fd->seekRetries++) {
   1502  1.2   scottr 			fd->iwmErr = seek(fd, IWM_SEEK_RECAL);
   1503  1.2   scottr 			if (TRACE_STRAT) {
   1504  1.2   scottr 				printf("[%d]", fd->seekRetries);
   1505  1.1   scottr 			}
   1506  1.2   scottr 		}
   1507  1.2   scottr 		state = (0 == fd->iwmErr) ? state_Exit : state_Fault;
   1508  1.2   scottr 		break;
   1509  1.2   scottr 
   1510  1.2   scottr 	default:		/* General IWM IO error? */
   1511  1.2   scottr 		state = state_IOErr;
   1512  1.2   scottr 	}
   1513  1.2   scottr 	return state;
   1514  1.2   scottr }
   1515  1.2   scottr 
   1516  1.1   scottr 
   1517  1.2   scottr /*
   1518  1.2   scottr  * fdstart_IOFinish
   1519  1.2   scottr  *
   1520  1.2   scottr  * Prepare for next block, if any is available
   1521  1.2   scottr  */
   1522  1.2   scottr static int
   1523  1.2   scottr fdstart_IOFinish(fd)
   1524  1.2   scottr 	fd_softc_t *fd;
   1525  1.2   scottr {
   1526  1.2   scottr 	int state;
   1527  1.1   scottr 
   1528  1.2   scottr 	if (DISABLED && TRACE_STRAT)
   1529  1.2   scottr 		printf("%s c%d_h%d_s%d ok ",
   1530  1.2   scottr 		    fd->ioDirection ? "Read" : "Write",
   1531  1.2   scottr 		    fd->sHdr.track, fd->sHdr.side >> 3, fd->sHdr.sector);
   1532  1.2   scottr 
   1533  1.2   scottr 	fd->bytesDone += fd->currentType->sectorSize;
   1534  1.2   scottr 	fd->bytesLeft -= fd->currentType->sectorSize;
   1535  1.2   scottr 	fd->current_buffer += fd->currentType->sectorSize;
   1536  1.2   scottr 	/*
   1537  1.2   scottr 	 * Instead of recalculating the chs mapping for
   1538  1.2   scottr 	 * each and every sector, check for
   1539  1.2   scottr 	 * 'current sector# <= max sector#' and recalculate
   1540  1.2   scottr 	 * after overflow.
   1541  1.2   scottr 	 */
   1542  1.2   scottr 	fd->startBlk++;
   1543  1.2   scottr 	if (fd->bytesLeft > 0) {
   1544  1.2   scottr 		if (++fd->pos.sector < fd->pos.maxSect) {
   1545  1.1   scottr 			if (TRACE_STRAT)
   1546  1.2   scottr 				printf("continue");
   1547  1.2   scottr 			state = (fd->ioDirection == IWM_WRITE)
   1548  1.2   scottr 			    ? state_Write : state_Read;
   1549  1.2   scottr 		}
   1550  1.2   scottr 		else {
   1551  1.1   scottr 			/*
   1552  1.2   scottr 			 * Invalidate read cache when changing track;
   1553  1.2   scottr 			 * flush write cache to disk.
   1554  1.1   scottr 			 */
   1555  1.2   scottr 			if (fd->ioDirection == IWM_WRITE) {
   1556  1.2   scottr 				if (TRACE_STRAT)
   1557  1.2   scottr 					printf("flush ");
   1558  1.2   scottr 				state = (state_Exit == fdstart_Flush(fd))
   1559  1.2   scottr 				    ? state_Seek : state_IOErr;
   1560  1.1   scottr 			}
   1561  1.2   scottr 			else {
   1562  1.1   scottr 				if (TRACE_STRAT)
   1563  1.2   scottr 					printf("step ");
   1564  1.2   scottr 				invalidateCylinderCache(fd);
   1565  1.2   scottr 				state = state_Seek;
   1566  1.1   scottr 			}
   1567  1.2   scottr 		}
   1568  1.2   scottr 	} else {
   1569  1.2   scottr 		state = (fd->ioDirection == IWM_WRITE)
   1570  1.2   scottr 		    ? state_Flush : state_Exit;
   1571  1.2   scottr 	}
   1572  1.2   scottr 	return state;
   1573  1.2   scottr }
   1574  1.1   scottr 
   1575  1.1   scottr 
   1576  1.2   scottr /*
   1577  1.2   scottr  * fdstart_IOErr
   1578  1.2   scottr  *
   1579  1.2   scottr  * Bad IO, repeat
   1580  1.2   scottr  */
   1581  1.2   scottr static int
   1582  1.2   scottr fdstart_IOErr(fd)
   1583  1.2   scottr 	fd_softc_t *fd;
   1584  1.2   scottr {
   1585  1.2   scottr 	int state;
   1586  1.2   scottr #ifndef _LKM
   1587  1.2   scottr 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
   1588  1.2   scottr #endif
   1589  1.2   scottr 
   1590  1.2   scottr #ifdef DIAGNOSTIC
   1591  1.2   scottr 	printf("iwm%sSector() err = %d, %d retries, on c%d_h%d_s%d.\n",
   1592  1.2   scottr 	    fd->ioDirection ? "Read" : "Write",
   1593  1.2   scottr 	    fd->iwmErr, fd->ioRetries, fd->pos.track,
   1594  1.2   scottr 	    fd->pos.side, fd->pos.sector);
   1595  1.2   scottr #endif
   1596  1.2   scottr 	/* XXX Do statistics */
   1597  1.2   scottr 	if (fd->ioRetries++ < iwm->maxRetries)
   1598  1.2   scottr 		state = (fd->ioDirection == IWM_WRITE)
   1599  1.2   scottr 		    ? state_Flush : state_Read;
   1600  1.2   scottr 	else
   1601  1.2   scottr 		state = state_Fault;
   1602  1.2   scottr 	return state;
   1603  1.2   scottr }
   1604  1.1   scottr 
   1605  1.1   scottr 
   1606  1.2   scottr /*
   1607  1.2   scottr  * fdstart_Fault
   1608  1.2   scottr  *
   1609  1.2   scottr  * A non-recoverable error
   1610  1.2   scottr  */
   1611  1.2   scottr static int
   1612  1.2   scottr fdstart_Fault(fd)
   1613  1.2   scottr 	fd_softc_t *fd;
   1614  1.2   scottr {
   1615  1.1   scottr #ifdef DIAGNOSTIC
   1616  1.2   scottr 	printf("Seek retries %d, IO retries %d, sect retries %d :\n" \
   1617  1.2   scottr 	    "\t\t only found c%d_h%d_s%d \n",
   1618  1.2   scottr 	    fd->seekRetries, fd->ioRetries, fd->sectRetries,
   1619  1.2   scottr 	    fd->sHdr.track, fd->sHdr.side >> 3, fd->sHdr.sector);
   1620  1.2   scottr 	printf("A non-recoverable error: %d ", fd->iwmErr);
   1621  1.2   scottr #else
   1622  1.2   scottr 	/* ARGSUSED */
   1623  1.2   scottr #endif
   1624  1.2   scottr 	return state_Exit;
   1625  1.2   scottr }
   1626  1.2   scottr 
   1627  1.1   scottr 
   1628  1.2   scottr /*
   1629  1.2   scottr  * fdstart_Exit
   1630  1.2   scottr  *
   1631  1.2   scottr  * We are done, for good or bad
   1632  1.2   scottr  */
   1633  1.2   scottr static int
   1634  1.2   scottr fdstart_Exit(fd)
   1635  1.2   scottr 	fd_softc_t *fd;
   1636  1.2   scottr {
   1637  1.3   kleink 	struct buf *bp;
   1638  1.3   kleink #ifdef DIAGNOSTIC
   1639  1.2   scottr 	int i;
   1640  1.3   kleink #endif
   1641  1.2   scottr 
   1642  1.2   scottr 	invalidateCylinderCache(fd);
   1643  1.1   scottr 
   1644  1.2   scottr #ifdef DIAGNOSTIC
   1645  1.2   scottr 	/* XXX Panic if buffer not clean? */
   1646  1.2   scottr 	for (i=0; i<IWM_MAX_GCR_SECTORS; i++)
   1647  1.2   scottr 		if (0 != fd->w_slots[i].valid)
   1648  1.2   scottr 			printf("Oops! <c%d_h%d_s%d> not flushed.\n",
   1649  1.2   scottr 			    fd->pos.track, fd->pos.side, fd->pos.sector);
   1650  1.2   scottr #endif
   1651  1.1   scottr 
   1652  1.4  thorpej 	bp = BUFQ_FIRST(&fd->bufQueue);
   1653  1.1   scottr 
   1654  1.2   scottr 	bp->b_resid = fd->bytesLeft;
   1655  1.2   scottr 	bp->b_error = (0 == fd->iwmErr) ? 0 : EIO;
   1656  1.2   scottr 	if (fd->iwmErr)
   1657  1.2   scottr 		bp->b_flags |= B_ERROR;
   1658  1.1   scottr 
   1659  1.2   scottr 	if (TRACE_STRAT) {
   1660  1.2   scottr 		printf(" fdstart() finished job; fd->iwmErr = %d, b_error = %d",
   1661  1.2   scottr 		    fd->iwmErr, bp->b_error);
   1662  1.2   scottr 		if (DISABLED)
   1663  1.2   scottr 			hexDump(bp->b_un.b_addr, bp->b_bcount);
   1664  1.2   scottr 	}
   1665  1.2   scottr 	/*
   1666  1.2   scottr 	 * Remove requested buf from beginning of queue
   1667  1.2   scottr 	 * and release it.
   1668  1.2   scottr 	 */
   1669  1.4  thorpej 	BUFQ_REMOVE(&fd->bufQueue, bp);
   1670  1.2   scottr 	if (DISABLED && TRACE_STRAT)
   1671  1.4  thorpej 		printf(" Next buf (bufQueue first) at %p\n",
   1672  1.4  thorpej 		    BUFQ_FIRST(&fd->bufQueue));
   1673  1.2   scottr 	disk_unbusy(&fd->diskInfo, bp->b_bcount - bp->b_resid);
   1674  1.2   scottr 	biodone(bp);
   1675  1.2   scottr 	/*
   1676  1.2   scottr 	 * Stop motor after 10s
   1677  1.2   scottr 	 *
   1678  1.2   scottr 	 * XXX Unloading the module while the timeout is still
   1679  1.2   scottr 	 *     running WILL crash the machine.
   1680  1.2   scottr 	 */
   1681  1.2   scottr 	timeout(motor_off, fd, 10 * hz);
   1682  1.1   scottr 
   1683  1.2   scottr 	return state_Done;
   1684  1.1   scottr }
   1685  1.1   scottr 
   1686  1.1   scottr 
   1687  1.1   scottr /*
   1688  1.2   scottr  * remap_geometry
   1689  1.2   scottr  *
   1690  1.1   scottr  * Remap the rigid UN*X view of a disk's cylinder/sector geometry
   1691  1.1   scottr  * to our zone recorded real Sony drive by splitting the disk
   1692  1.1   scottr  * into zones.
   1693  1.1   scottr  *
   1694  1.1   scottr  * Loop {
   1695  1.1   scottr  * 	Look if logical block number is in current zone
   1696  1.1   scottr  *	NO:	Add # of tracks for current zone to track counter
   1697  1.1   scottr  *		Process next zone
   1698  1.1   scottr  *
   1699  1.1   scottr  *	YES:	Subtract (number of first sector of current zone times heads)
   1700  1.1   scottr  *		from logical block number, then break up the difference
   1701  1.1   scottr  *		in tracks/side/sectors (spt is constant within a zone).
   1702  1.1   scottr  *		Done
   1703  1.1   scottr  * }
   1704  1.1   scottr  */
   1705  1.1   scottr static void
   1706  1.1   scottr remap_geometry(block, heads, loc)
   1707  1.1   scottr 	daddr_t block;
   1708  1.1   scottr 	int heads;
   1709  1.1   scottr 	diskPosition_t *loc;
   1710  1.1   scottr {
   1711  1.1   scottr 	int zone, spt;
   1712  1.1   scottr 	extern diskZone_t diskZones[];
   1713  1.1   scottr 
   1714  1.1   scottr 	spt = 0;		/* XXX Shut up egcs warning */
   1715  1.1   scottr 	loc->oldTrack = loc->track;
   1716  1.1   scottr 	loc->track = 0;
   1717  1.1   scottr 
   1718  1.1   scottr 	for (zone = 0; zone < IWM_GCR_DISK_ZONES; zone++) {
   1719  1.1   scottr 		if (block >= heads * (diskZones[zone].lastBlock + 1)) {
   1720  1.1   scottr 			/* Process full zones */
   1721  1.1   scottr 			loc->track += diskZones[zone].tracks;
   1722  1.1   scottr 		} else {
   1723  1.1   scottr 			/* Process partial zone */
   1724  1.1   scottr 			spt = diskZones[zone].sectPerTrack;
   1725  1.1   scottr 			block -= heads * diskZones[zone].firstBlock;
   1726  1.1   scottr 			loc->track += block / (spt * heads);
   1727  1.1   scottr 			loc->sector = (block % spt);
   1728  1.1   scottr 			loc->side = (block % (spt * heads)) / spt;
   1729  1.1   scottr 			break;
   1730  1.1   scottr 		}
   1731  1.1   scottr 	}
   1732  1.1   scottr 	loc->maxSect = spt;
   1733  1.1   scottr }
   1734  1.1   scottr 
   1735  1.1   scottr 
   1736  1.1   scottr /*
   1737  1.1   scottr  * motor_off
   1738  1.1   scottr  *
   1739  1.1   scottr  * Callback for timeout()
   1740  1.1   scottr  */
   1741  1.1   scottr static void
   1742  1.1   scottr motor_off(param)
   1743  1.1   scottr 	void *param;
   1744  1.1   scottr {
   1745  1.1   scottr 	int spl;
   1746  1.1   scottr 	fd_softc_t *fd;
   1747  1.1   scottr 
   1748  1.1   scottr 	fd = (fd_softc_t *)param;
   1749  1.1   scottr 	if (TRACE_STRAT)
   1750  1.1   scottr 		printf("iwm: Switching motor OFF (timeout).\n");
   1751  1.2   scottr 	spl = spl6();
   1752  1.1   scottr 	(void)iwmMotor(fd->unit, 0);
   1753  1.1   scottr 	fd->state &= ~IWM_FD_MOTOR_ON;
   1754  1.1   scottr 	splx(spl);
   1755  1.1   scottr }
   1756  1.1   scottr 
   1757  1.1   scottr 
   1758  1.1   scottr /*
   1759  1.1   scottr  * fdGetDiskLabel
   1760  1.1   scottr  *
   1761  1.1   scottr  * Set up disk label with parameters from current disk type.
   1762  1.1   scottr  * Then call the generic disklabel read routine which tries to
   1763  1.1   scottr  * read a label from disk and insert it. If it doesn't exist use
   1764  1.1   scottr  * our defaults.
   1765  1.1   scottr  */
   1766  1.1   scottr static void
   1767  1.1   scottr fdGetDiskLabel(fd, dev)
   1768  1.1   scottr 	fd_softc_t *fd;
   1769  1.1   scottr 	dev_t dev;
   1770  1.1   scottr {
   1771  1.1   scottr 	char *msg;
   1772  1.1   scottr 	int fdType;
   1773  1.1   scottr 	struct disklabel *lp;
   1774  1.1   scottr 	struct cpu_disklabel *clp;
   1775  1.1   scottr 
   1776  1.1   scottr 	if (TRACE_IOCTL)
   1777  1.1   scottr 		printf("iwm: fdGetDiskLabel() for disk %d.\n",
   1778  1.1   scottr 		    minor(dev) / MAXPARTITIONS);
   1779  1.1   scottr 	fdType = minor(dev) % MAXPARTITIONS;
   1780  1.1   scottr 	lp = fd->diskInfo.dk_label;
   1781  1.1   scottr 	clp = fd->diskInfo.dk_cpulabel;
   1782  1.2   scottr 	memset(lp, 0, sizeof(struct disklabel));
   1783  1.2   scottr 	memset(clp, 0, sizeof(struct cpu_disklabel));
   1784  1.1   scottr 	/*
   1785  1.1   scottr 	 * How to describe a drive with a variable # of sectors per
   1786  1.1   scottr 	 * track (8..12) and variable rpm (300..550)? Apple came up
   1787  1.1   scottr 	 * with ZBR in 1983! Un*x drive management sucks.
   1788  1.1   scottr 	 */
   1789  1.1   scottr 	lp->d_type = DTYPE_FLOPPY;
   1790  1.1   scottr 	lp->d_rpm = 300;
   1791  1.1   scottr 	lp->d_secsize = fd->currentType->sectorSize;
   1792  1.1   scottr 	lp->d_ntracks = fd->currentType->heads;
   1793  1.1   scottr 	lp->d_ncylinders = fd->currentType->tracks;
   1794  1.1   scottr 	lp->d_nsectors = fd->currentType->secPerTrack;
   1795  1.1   scottr 	lp->d_secpercyl = fd->currentType->secPerCyl;
   1796  1.1   scottr 	lp->d_secperunit = fd->currentType->secPerDisk;
   1797  1.1   scottr 	lp->d_interleave = fd->currentType->interleave;
   1798  1.2   scottr 	lp->d_trkseek = fd->currentType->stepRate;
   1799  1.1   scottr 
   1800  1.2   scottr 	strcpy(lp->d_typename, dktypenames[DTYPE_FLOPPY]);
   1801  1.1   scottr 	strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
   1802  1.1   scottr 
   1803  1.1   scottr 	lp->d_npartitions = fdType + 1;
   1804  1.1   scottr 	lp->d_partitions[fdType].p_offset = 0;
   1805  1.1   scottr 	lp->d_partitions[fdType].p_size = lp->d_secperunit;
   1806  1.1   scottr 	lp->d_partitions[fdType].p_fstype = FS_BSDFFS;
   1807  1.1   scottr 	lp->d_partitions[fdType].p_fsize = 512;
   1808  1.1   scottr 	lp->d_partitions[fdType].p_frag = 8;
   1809  1.1   scottr 
   1810  1.1   scottr 	lp->d_magic = DISKMAGIC;
   1811  1.1   scottr 	lp->d_magic2 = DISKMAGIC;
   1812  1.1   scottr 	lp->d_checksum = dkcksum(lp);
   1813  1.1   scottr 	/*
   1814  1.1   scottr 	 * Call the generic disklabel extraction routine.  If we don't
   1815  1.1   scottr 	 * find a label on disk, keep our faked one.
   1816  1.1   scottr 	 */
   1817  1.1   scottr 	if (TRACE_OPEN)
   1818  1.1   scottr 		printf(" now calling readdisklabel()...\n");
   1819  1.1   scottr 
   1820  1.1   scottr 	msg = readdisklabel(dev, fdstrategy, lp, clp);
   1821  1.1   scottr 	if (msg == NULL) {
   1822  1.1   scottr 		strncpy(lp->d_packname, "default label",
   1823  1.1   scottr 		    sizeof(lp->d_packname));	/* XXX - ?? */
   1824  1.1   scottr 	}
   1825  1.2   scottr #ifdef IWM_DEBUG
   1826  1.1   scottr 	else
   1827  1.1   scottr 		printf("iwm: %s.\n", msg);
   1828  1.1   scottr #endif
   1829  1.1   scottr 	if (TRACE_OPEN)
   1830  1.1   scottr 		fdPrintDiskLabel(lp);
   1831  1.1   scottr }
   1832  1.1   scottr 
   1833  1.1   scottr 
   1834  1.2   scottr 
   1835  1.2   scottr /*
   1836  1.2   scottr  * initCylinderCache
   1837  1.2   scottr  *
   1838  1.2   scottr  * Allocate cylinder cache and set up pointers to sectors.
   1839  1.2   scottr  */
   1840  1.2   scottr static int
   1841  1.2   scottr initCylinderCache(fd)
   1842  1.2   scottr 	fd_softc_t *fd;
   1843  1.2   scottr {
   1844  1.2   scottr 	int i;
   1845  1.2   scottr 	int err;
   1846  1.2   scottr 	int secsize;
   1847  1.2   scottr 
   1848  1.2   scottr 	err = 0;
   1849  1.2   scottr 	secsize = fd->currentType->sectorSize;
   1850  1.2   scottr 	fd->cachedSide = 0;
   1851  1.2   scottr 
   1852  1.2   scottr 	fd->cbuf = (unsigned char *) malloc(IWM_MAX_GCR_SECTORS
   1853  1.2   scottr 	    * secsize, M_DEVBUF, M_WAITOK);
   1854  1.2   scottr 	if (NULL == fd->cbuf)
   1855  1.2   scottr 		err = ENOMEM;
   1856  1.2   scottr 	else
   1857  1.2   scottr 		for (i=0; i < IWM_MAX_GCR_SECTORS; i++) {
   1858  1.2   scottr 			fd->w_slots[i].valid = 0;
   1859  1.2   scottr 			fd->w_slots[i].secbuf = NULL;
   1860  1.2   scottr 
   1861  1.2   scottr 			fd->r_slots[i].valid = 0;
   1862  1.2   scottr 			fd->r_slots[i].secbuf = fd->cbuf + i * secsize;
   1863  1.2   scottr 		}
   1864  1.2   scottr 	return err;
   1865  1.2   scottr }
   1866  1.2   scottr 
   1867  1.2   scottr 
   1868  1.2   scottr /*
   1869  1.2   scottr  * invalidateCylinderCache
   1870  1.2   scottr  *
   1871  1.2   scottr  * Switching cylinders (tracks?) invalidates the read cache.
   1872  1.2   scottr  */
   1873  1.2   scottr static void
   1874  1.2   scottr invalidateCylinderCache(fd)
   1875  1.2   scottr 	fd_softc_t *fd;
   1876  1.2   scottr {
   1877  1.2   scottr 	int i;
   1878  1.2   scottr 
   1879  1.2   scottr 	fd->cachedSide = 0;
   1880  1.2   scottr 	for (i=0; i < IWM_MAX_GCR_SECTORS; i++) {
   1881  1.2   scottr 		fd->r_slots[i].valid = 0;
   1882  1.2   scottr 	}
   1883  1.2   scottr }
   1884  1.2   scottr 
   1885  1.2   scottr 
   1886  1.1   scottr /*
   1887  1.1   scottr  * getFDType
   1888  1.1   scottr  *
   1889  1.1   scottr  * return pointer to disk format description
   1890  1.1   scottr  */
   1891  1.1   scottr static fdInfo_t *
   1892  1.1   scottr getFDType(unit)
   1893  1.1   scottr 	short unit;
   1894  1.1   scottr {
   1895  1.1   scottr 	int driveFlags;
   1896  1.1   scottr 	fdInfo_t *thisType;
   1897  1.1   scottr 	extern fdInfo_t fdTypes[];
   1898  1.1   scottr 
   1899  1.1   scottr 	driveFlags = iwmCheckDrive(unit);
   1900  1.1   scottr /*
   1901  1.1   scottr  * Drive flags are: Bit  0 - 1 = Drive is double sided
   1902  1.1   scottr  *			 1 - 1 = No disk inserted
   1903  1.1   scottr  *			 2 - 1 = Motor is off
   1904  1.1   scottr  *			 3 - 1 = Disk is writeable
   1905  1.1   scottr  *			 4 - 1 = Disk is DD (800/720K)
   1906  1.1   scottr  *			31 - 1 = No drive / invalid drive #
   1907  1.1   scottr  */
   1908  1.1   scottr 	if (TRACE_CONFIG) {
   1909  1.1   scottr 		printf("iwm: Drive %d says 0x0%x (%d)\n",
   1910  1.1   scottr 		    unit, driveFlags, driveFlags);
   1911  1.1   scottr 	}
   1912  1.1   scottr 	if (driveFlags < 0)
   1913  1.1   scottr 		thisType = NULL;/* no such drive	 */
   1914  1.1   scottr 	else
   1915  1.1   scottr 		if (driveFlags & 0x01)
   1916  1.1   scottr 			thisType = &fdTypes[1];	/* double sided		 */
   1917  1.1   scottr 		else
   1918  1.1   scottr 			thisType = &fdTypes[0];	/* single sided		 */
   1919  1.1   scottr 
   1920  1.1   scottr 	return thisType;
   1921  1.1   scottr }
   1922  1.1   scottr 
   1923  1.1   scottr 
   1924  1.1   scottr /*
   1925  1.1   scottr  * fdDeviceToType
   1926  1.1   scottr  *
   1927  1.1   scottr  * maps the minor device number (elsewhere: partition type) to
   1928  1.1   scottr  * a corresponding disk format.
   1929  1.1   scottr  * This is currently:
   1930  1.1   scottr  * 	fdXa	default (800K GCR)
   1931  1.1   scottr  *	fdXb	400K GCR
   1932  1.1   scottr  *	fdXc	800K GCR
   1933  1.1   scottr  */
   1934  1.1   scottr static fdInfo_t *
   1935  1.1   scottr fdDeviceToType(fd, dev)
   1936  1.1   scottr 	fd_softc_t *fd;
   1937  1.1   scottr 	dev_t dev;
   1938  1.1   scottr {
   1939  1.1   scottr 	int type;
   1940  1.1   scottr 	fdInfo_t *thisInfo;
   1941  1.1   scottr 	/* XXX This broke with egcs 1.0.2 */
   1942  1.1   scottr 	/* extern fdInfo_t	fdTypes[]; */
   1943  1.1   scottr 
   1944  1.1   scottr 	type = minor(dev) % MAXPARTITIONS;	/* 1,2,... */
   1945  1.1   scottr 	if (type > sizeof(fdTypes) / sizeof(fdTypes[0]))
   1946  1.1   scottr 		thisInfo = NULL;
   1947  1.1   scottr 	else
   1948  1.1   scottr 		thisInfo = (type == 0) ? fd->defaultType : &fdTypes[type - 1];
   1949  1.1   scottr 	return thisInfo;
   1950  1.1   scottr }
   1951  1.1   scottr 
   1952  1.1   scottr 
   1953  1.1   scottr /*
   1954  1.1   scottr  * seek
   1955  1.1   scottr  *
   1956  1.1   scottr  * Step to given track; optionally restore to track zero before
   1957  1.1   scottr  * and/or verify correct track.
   1958  1.1   scottr  * Note that any necessary retries are done here.
   1959  1.1   scottr  * We keep the current position on disk in a 'struct diskPosition'.
   1960  1.1   scottr  */
   1961  1.1   scottr static int
   1962  1.2   scottr seek(fd, style)
   1963  1.2   scottr 	fd_softc_t *fd;
   1964  1.1   scottr 	int style;
   1965  1.1   scottr {
   1966  1.1   scottr 	int state, done;
   1967  1.1   scottr 	int err, ierr;
   1968  1.1   scottr 	int steps;
   1969  1.2   scottr 
   1970  1.2   scottr 	diskPosition_t *loc;
   1971  1.1   scottr 	sectorHdr_t hdr;
   1972  1.1   scottr 	char action[32];
   1973  1.1   scottr #ifndef _LKM
   1974  1.1   scottr 	iwm_softc_t *iwm = iwm_cd.cd_devs[0];
   1975  1.1   scottr #endif
   1976  1.1   scottr 
   1977  1.1   scottr 	char *stateDesc[] = {
   1978  1.1   scottr 		"Init",
   1979  1.1   scottr 		"Seek",
   1980  1.1   scottr 		"Recalibrate",
   1981  1.1   scottr 		"Verify",
   1982  1.1   scottr 		"Exit"
   1983  1.1   scottr 	};
   1984  1.1   scottr 	enum {
   1985  1.1   scottr 		state_Init = 0,
   1986  1.1   scottr 		state_Seek,
   1987  1.1   scottr 		state_Recalibrate,
   1988  1.1   scottr 		state_Verify,
   1989  1.1   scottr 		state_Exit
   1990  1.1   scottr 	};
   1991  1.2   scottr 	/* XXX egcs */
   1992  1.2   scottr 	done = err = ierr = 0;
   1993  1.2   scottr 	fd->seekRetries = 0;
   1994  1.2   scottr 	fd->verifyRetries = 0;
   1995  1.2   scottr 
   1996  1.2   scottr 	loc = &fd->pos;
   1997  1.2   scottr 
   1998  1.1   scottr 	state = state_Init;
   1999  1.1   scottr 	do {
   2000  1.1   scottr 		if (TRACE_STEP)
   2001  1.1   scottr 			printf(" seek state %d [%s].\n",
   2002  1.1   scottr 			    state, stateDesc[state]);
   2003  1.1   scottr 		switch (state) {
   2004  1.1   scottr 
   2005  1.1   scottr 		case state_Init:
   2006  1.1   scottr 			if (TRACE_STEP)
   2007  1.1   scottr 				printf("Current track is %d, new track %d.\n",
   2008  1.1   scottr 				    loc->oldTrack, loc->track);
   2009  1.2   scottr 			memset(&hdr, 0, sizeof(hdr));
   2010  1.1   scottr 			err = ierr = 0;
   2011  1.2   scottr 			fd->seekRetries = 0;
   2012  1.2   scottr 			fd->verifyRetries = 0;
   2013  1.1   scottr 			state = (style == IWM_SEEK_RECAL)
   2014  1.1   scottr 			    ? state_Recalibrate : state_Seek;
   2015  1.1   scottr 			done = 0;
   2016  1.1   scottr 			break;
   2017  1.1   scottr 
   2018  1.1   scottr 		case state_Recalibrate:
   2019  1.1   scottr 			ierr = iwmTrack00();
   2020  1.1   scottr 			if (ierr == 0) {
   2021  1.1   scottr 				loc->oldTrack = 0;
   2022  1.1   scottr 				state = state_Seek;
   2023  1.1   scottr 			} else {
   2024  1.1   scottr 				strncpy(action, "Recalibrate (track 0)",
   2025  1.1   scottr 				    sizeof(action));
   2026  1.1   scottr 				state = state_Exit;
   2027  1.1   scottr 			}
   2028  1.1   scottr 			break;
   2029  1.1   scottr 
   2030  1.1   scottr 		case state_Seek:
   2031  1.1   scottr 			ierr = 0;
   2032  1.1   scottr 			steps = loc->track - loc->oldTrack;
   2033  1.1   scottr 
   2034  1.1   scottr 			if (steps != 0)
   2035  1.1   scottr 				ierr = iwmSeek(steps);
   2036  1.1   scottr 			if (ierr == 0) {
   2037  1.1   scottr 				/* No error or nothing to do */
   2038  1.1   scottr 				state = (style == IWM_SEEK_VERIFY)
   2039  1.1   scottr 				    ? state_Verify : state_Exit;
   2040  1.1   scottr 			} else {
   2041  1.2   scottr 				if (fd->seekRetries++ < iwm->maxRetries)
   2042  1.1   scottr 					state = state_Recalibrate;
   2043  1.1   scottr 				else {
   2044  1.1   scottr 					strncpy(action, "Seek retries",
   2045  1.1   scottr 					    sizeof(action));
   2046  1.1   scottr 					state = state_Exit;
   2047  1.1   scottr 				}
   2048  1.1   scottr 			}
   2049  1.1   scottr 			break;
   2050  1.1   scottr 
   2051  1.1   scottr 		case state_Verify:
   2052  1.2   scottr 			ierr = checkTrack(loc, TRACE_STEP);
   2053  1.1   scottr 			if (ierr == 0 && loc->track == hdr.track)
   2054  1.1   scottr 				state = state_Exit;
   2055  1.1   scottr 			else {
   2056  1.2   scottr 				if (fd->verifyRetries++ < iwm->maxRetries)
   2057  1.1   scottr 					state = state_Recalibrate;
   2058  1.1   scottr 				else {
   2059  1.1   scottr 					strncpy(action, "Verify retries",
   2060  1.1   scottr 					    sizeof(action));
   2061  1.1   scottr 					state = state_Exit;
   2062  1.1   scottr 				}
   2063  1.1   scottr 			}
   2064  1.1   scottr 			break;
   2065  1.1   scottr 
   2066  1.1   scottr 		case state_Exit:
   2067  1.1   scottr 			if (ierr == 0) {
   2068  1.1   scottr 				loc->oldTrack = loc->track;
   2069  1.1   scottr 				err = 0;
   2070  1.1   scottr 				/* Give the head some time to settle down */
   2071  1.1   scottr 				delay(3000);
   2072  1.1   scottr 			} else {
   2073  1.1   scottr #ifdef DIAGNOSTIC
   2074  1.1   scottr 				printf(" seek() action \"%s\", err = %d.\n",
   2075  1.1   scottr 				    action, ierr);
   2076  1.1   scottr #endif
   2077  1.1   scottr 				err = EIO;
   2078  1.1   scottr 			}
   2079  1.1   scottr 			done = 1;
   2080  1.1   scottr 			break;
   2081  1.1   scottr 		}
   2082  1.1   scottr 	} while (!done);
   2083  1.1   scottr 	return err;
   2084  1.1   scottr }
   2085  1.1   scottr 
   2086  1.1   scottr 
   2087  1.1   scottr /*
   2088  1.1   scottr  * checkTrack
   2089  1.1   scottr  *
   2090  1.1   scottr  * After positioning, get a sector header for validation
   2091  1.1   scottr  */
   2092  1.1   scottr static int
   2093  1.1   scottr checkTrack(loc, debugFlag)
   2094  1.2   scottr 	diskPosition_t *loc;
   2095  1.1   scottr 	int debugFlag;
   2096  1.1   scottr {
   2097  1.1   scottr 	int spl;
   2098  1.1   scottr 	int iwmErr;
   2099  1.1   scottr 	sectorHdr_t hdr;
   2100  1.1   scottr 
   2101  1.2   scottr 	spl = spl6();
   2102  1.2   scottr 	iwmSelectSide(loc->side);
   2103  1.1   scottr 	iwmErr = iwmReadSectHdr(&hdr);
   2104  1.1   scottr 	splx(spl);
   2105  1.1   scottr 	if (debugFlag) {
   2106  1.1   scottr 		printf("Seeked for %d, got at %d, Hdr read err %d.\n",
   2107  1.2   scottr 		    loc->track, hdr.track, iwmErr);
   2108  1.1   scottr 	}
   2109  1.1   scottr 	return iwmErr;
   2110  1.1   scottr }
   2111  1.1   scottr 
   2112  1.1   scottr 
   2113  1.1   scottr /* Debugging stuff */
   2114  1.1   scottr 
   2115  1.1   scottr static void
   2116  1.1   scottr hexDump(buf, len)
   2117  1.1   scottr 	u_char *buf;
   2118  1.1   scottr 	int len;
   2119  1.1   scottr {
   2120  1.1   scottr 	int i, j;
   2121  1.1   scottr 	u_char ch;
   2122  1.1   scottr 
   2123  1.1   scottr 	printf("\nDump %d from %p:\n", len, buf);
   2124  1.1   scottr 	i = j = 0;
   2125  1.1   scottr 	if (NULL != buf) do {
   2126  1.1   scottr 		printf("%04x: ", i);
   2127  1.1   scottr 		for (j = 0; j < 8; j++)
   2128  1.1   scottr 			printf("%02x ", buf[i + j]);
   2129  1.1   scottr 		printf(" ");
   2130  1.1   scottr 		for (j = 8; j < 16; j++)
   2131  1.1   scottr 			printf("%02x ", buf[i + j]);
   2132  1.1   scottr 		printf(" ");
   2133  1.1   scottr 		for (j = 0; j < 16; j++) {
   2134  1.1   scottr 			ch = buf[i + j];
   2135  1.1   scottr 			if (ch > 31 && ch < 127)
   2136  1.1   scottr 				printf("%c", ch);
   2137  1.1   scottr 			else
   2138  1.1   scottr 				printf(".");
   2139  1.1   scottr 		}
   2140  1.1   scottr 		printf("\n");
   2141  1.1   scottr 		i += 16;
   2142  1.1   scottr 	} while (len > i);
   2143  1.1   scottr }
   2144  1.1   scottr 
   2145  1.1   scottr 
   2146  1.1   scottr static void
   2147  1.1   scottr fdPrintDiskLabel(lp)
   2148  1.1   scottr 	struct disklabel *lp;
   2149  1.1   scottr {
   2150  1.1   scottr 	int i;
   2151  1.1   scottr 
   2152  1.1   scottr 	printf("iwm: Disklabel entries of current floppy.\n");
   2153  1.1   scottr 	printf("\t d_type:\t%d (%s)\n", lp->d_type,
   2154  1.2   scottr 	    dktypenames[lp->d_type]);
   2155  1.1   scottr 	printf("\t d_typename:\t%s\n", lp->d_typename);
   2156  1.1   scottr 	printf("\t d_packname:\t%s\n", lp->d_packname);
   2157  1.1   scottr 
   2158  1.1   scottr 	printf("\t d_secsize:\t%d\n", lp->d_secsize);
   2159  1.1   scottr 	printf("\t d_nsectors:\t%d\n", lp->d_nsectors);
   2160  1.1   scottr 	printf("\t d_ntracks:\t%d\n", lp->d_ntracks);
   2161  1.1   scottr 	printf("\t d_ncylinders:\t%d\n", lp->d_ncylinders);
   2162  1.1   scottr 	printf("\t d_secpercyl:\t%d\n", lp->d_secpercyl);
   2163  1.1   scottr 	printf("\t d_secperunit:\t%d\n", lp->d_secperunit);
   2164  1.1   scottr 
   2165  1.1   scottr 	printf("\t d_rpm: \t%d\n", lp->d_rpm);
   2166  1.1   scottr 	printf("\t d_interleave:\t%d\n", lp->d_interleave);
   2167  1.2   scottr 	printf("\t d_trkseek:\t%d [ms]\n", lp->d_trkseek);
   2168  1.1   scottr 
   2169  1.1   scottr 	printf(" d_npartitions:\t%d\n", lp->d_npartitions);
   2170  1.1   scottr 	for (i = 0; i < lp->d_npartitions; i++) {
   2171  1.1   scottr 		printf("\t d_partitions[%d].p_offset:\t%d\n", i,
   2172  1.1   scottr 		    lp->d_partitions[i].p_offset);
   2173  1.1   scottr 		printf("\t d_partitions[%d].p_size:\t%d\n", i,
   2174  1.1   scottr 		    lp->d_partitions[i].p_size);
   2175  1.1   scottr 		printf("\t d_partitions[%d].p_fstype:\t%d (%s)\n", i,
   2176  1.1   scottr 		    lp->d_partitions[i].p_fstype,
   2177  1.1   scottr 		    fstypenames[lp->d_partitions[i].p_fstype]);
   2178  1.1   scottr 		printf("\t d_partitions[%d].p_frag:\t%d\n", i,
   2179  1.1   scottr 		    lp->d_partitions[i].p_frag);
   2180  1.1   scottr 		printf("\n");
   2181  1.1   scottr 	}
   2182  1.1   scottr }
   2183