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