Home | History | Annotate | Line # | Download | only in ebus
ace_ebus.c revision 1.1
      1 /*	$NetBSD: ace_ebus.c,v 1.1 2011/01/26 01:18:50 pooka Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code was written by Alessandro Forin and Neil Pittman
      8  * at Microsoft Research and contributed to The NetBSD Foundation
      9  * by Microsoft Corporation.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: ace_ebus.c,v 1.1 2011/01/26 01:18:50 pooka Exp $");
     35 
     36 #include "rnd.h"
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/kernel.h>
     41 #include <sys/conf.h>
     42 #include <sys/file.h>
     43 #include <sys/stat.h>
     44 #include <sys/ioctl.h>
     45 #include <sys/buf.h>
     46 #include <sys/bufq.h>
     47 #include <sys/uio.h>
     48 #include <sys/malloc.h>
     49 #include <sys/device.h>
     50 #include <sys/disklabel.h>
     51 #include <sys/disk.h>
     52 #include <sys/syslog.h>
     53 #include <sys/proc.h>
     54 #include <sys/vnode.h>
     55 #include <sys/kthread.h>
     56 #include <sys/lock.h>
     57 #include <sys/queue.h>
     58 
     59 #if NRND > 0
     60 #include <sys/rnd.h>
     61 #endif
     62 
     63 #include <machine/intr.h>
     64 #include <machine/bus.h>
     65 
     66 #include "locators.h"
     67 #include <prop/proplib.h>
     68 
     69 #include <emips/ebus/ebusvar.h>
     70 #include <emips/emips/machdep.h>
     71 #include <machine/emipsreg.h>
     72 
     73 /* Structure returned by the Identify command (see CFlash specs)
     74  * NB: We only care for the first sector so that is what we define here.
     75  * NB: Beware of mis-alignment for all 32bit things
     76  */
     77 typedef struct _CFLASH_IDENTIFY {
     78     uint16_t Signature;                              /* Word 0 */
     79 #define CFLASH_SIGNATURE 0x848a
     80     uint16_t DefaultNumberOfCylinders;               /* Word 1 */
     81     uint16_t Reserved1;                              /* Word 2 */
     82     uint16_t DefaultNumberOfHeads;                   /* Word 3 */
     83     uint16_t Obsolete1[2];                           /* Word 4 */
     84     uint16_t DefaultSectorsPerTrack;                 /* Word 6 */
     85     uint16_t SectorsPerCard[2];                      /* Word 7 */
     86     uint16_t Obsolete2;                              /* Word 9 */
     87     uint8_t  SerialNumber[20]; /* padded, right-justified Word 10 */
     88     uint16_t Obsolete3[2];                           /* Word 20 */
     89     uint16_t EccBytesInRWLong;                       /* Word 22 */
     90     uint8_t  FirmwareRevision[8];                    /* Word 23 */
     91     uint8_t  ModelNumber[40];                        /* Word 27 */
     92     uint16_t SectorsInRWMultiple;                    /* Word 47 */
     93     uint16_t Reserved2;                              /* Word 48 */
     94     uint16_t Capabilities;                           /* Word 49 */
     95     uint16_t Reserved3;                              /* Word 50 */
     96     uint16_t PioMode;                                /* Word 51 */
     97     uint16_t Obsolete4;                              /* Word 52 */
     98     uint16_t FieldValidity;                          /* Word 53 */
     99     uint16_t CurrentNumberOfCylinders;               /* Word 54 */
    100     uint16_t CurrentNumberOfHeads;                   /* Word 55 */
    101     uint16_t CurrentSectorsPerTrack;                 /* Word 56 */
    102     uint16_t CurrentCapacity[2];                     /* Word 57 */
    103     uint16_t MultiSectorSettings;                    /* Word 59 */
    104     uint16_t NumberOfAddressableSectors[2];          /* Word 60 */
    105     uint16_t Reserved4;                              /* Word 62 */
    106     uint16_t MultiWordDmaTransfer;                   /* Word 63 */
    107     uint16_t AdvancedPioModes;                       /* Word 64 */
    108     uint16_t MinimumMultiWordDmaTiming;              /* Word 65 */
    109     uint16_t RecommendedMultiWordDmaTiming;          /* Word 66 */
    110     uint16_t PioTimingNoFlowControl;                 /* Word 67 */
    111     uint16_t PioTimingWithFlowControl;               /* Word 68 */
    112     uint16_t Reserved5[13];                          /* Word 69 */
    113     uint16_t FeaturesSupported[3];                   /* Word 82 */
    114     uint16_t FeaturesEnabled[3];                     /* Word 85 */
    115     uint16_t UdmaMode;                               /* Word 88 */
    116     uint16_t SecurityEraseTime;                      /* Word 89 */
    117     uint16_t EnhancedSecurityEraseTime;              /* Word 90 */
    118     uint16_t CurrentPowerManagementValue;            /* Word 91 */
    119     uint8_t  Reserved6[72];                          /* Word 92-127 */
    120     uint8_t  SecondHalf[256];                        /* Word 128-255 */
    121 } CFLASH_IDENTIFY, *PCFLASH_IDENTIFY;
    122 
    123 #define SIZEOF_IDENTIFY CF_SECTOR_SIZE /* must be a sector multiple */
    124 
    125 /* Instead of dragging in atavar.h.. */
    126 /*
    127  * Parameters/state needed by the controller to perform an ATA bio.
    128  */
    129 struct ace_bio {
    130 	volatile int flags;/* cmd flags */
    131 #define	ATA_POLL	0x0002	/* poll for completion */
    132 #define	ATA_SINGLE	0x0008	/* transfer must be done in singlesector mode */
    133 #define	ATA_READ	0x0020	/* transfer is a read (otherwise a write) */
    134 #define	ATA_CORR	0x0040	/* transfer had a corrected error */
    135 	daddr_t		blkno;	/* block addr */
    136 	daddr_t		blkdone;/* number of blks transferred */
    137 	size_t		nblks;	/* number of blocks currently transferring */
    138 	size_t	    nbytes;	/* number of bytes currently transferring */
    139 	char		*databuf;/* data buffer address */
    140 	volatile int	error;
    141 #define	NOERROR 	0	/* There was no error (r_error invalid), else see acedone()*/
    142 #define FAILED(er) (er != 0)
    143 #define EDOOFUS EIO
    144 
    145 	u_int32_t	r_error;/* copy of status register */
    146 #ifdef HAS_BAD144_HANDLING
    147 	daddr_t		badsect[127];/* 126 plus trailing -1 marker */
    148 #endif
    149 };
    150 /* End of atavar.h*/
    151 
    152 struct ace_softc {
    153 	/* General disk infos */
    154 	device_t sc_dev;
    155 
    156 	struct disk sc_dk;
    157 	struct bufq_state *sc_q;
    158 	struct callout sc_restart_ch;
    159 
    160 	/* IDE disk soft states */
    161 	struct buf *sc_bp; /* buf being transfered */
    162 	struct buf *active_xfer; /* buf handoff to thread  */
    163     /* current transfer data */
    164 	struct ace_bio sc_bio; /* current transfer */
    165 
    166     struct proc *ch_thread;
    167     int ch_flags;
    168 #define ATACH_SHUTDOWN 0x02        /* thread is shutting down */
    169 #define ATACH_IRQ_WAIT 0x10        /* thread is waiting for irq */
    170 #define ATACH_DISABLED 0x80        /* channel is disabled */
    171 #define ATACH_TH_RUN   0x100       /* the kernel thread is working */
    172 #define ATACH_TH_RESET 0x200       /* someone ask the thread to reset */
    173 
    174 	int openings;
    175     int media_has_changed;
    176 #define    ACECE_MC    0x20    /* media changed */
    177 #define    ACECE_MCR   0x08    /* media change requested */
    178 	struct _CFLASH_IDENTIFY sc_params;/* drive characteristics found */
    179 
    180 	int sc_flags;
    181 #define	ACEF_WLABEL	0x004 /* label is writable */
    182 #define	ACEF_LABELLING	0x008 /* writing label */
    183 #define ACEF_LOADED	0x010 /* parameters loaded */
    184 #define ACEF_WAIT	0x020 /* waiting for resources */
    185 #define ACEF_KLABEL	0x080 /* retain label after 'full' close */
    186 
    187 	u_int64_t sc_capacity;
    188 	uint32_t sc_multi; /* max sectors per xfer */
    189 
    190 	struct	_Sac   *sc_dr;		/* reg pointers */
    191     int hw_busy;
    192 	int retries; /* number of xfer retry */
    193 
    194 #if NRND > 0
    195 	rndsource_element_t	rnd_source;
    196 #endif
    197 };
    198 
    199 int  ace_ebus_match(struct device *, struct cfdata *, void *);
    200 void ace_ebus_attach(struct device *, struct device *, void *);
    201 void aceattach(struct ace_softc *);
    202 int	 acedetach(struct device *, int);
    203 int	 aceactivate(struct device *, enum devact);
    204 
    205 void  acedone(struct ace_softc *);
    206 static void ace_params_to_properties(struct ace_softc *ace);
    207 
    208 CFATTACH_DECL_NEW(ace_ebus, sizeof(struct ace_softc),
    209     ace_ebus_match, ace_ebus_attach, acedetach, aceactivate);
    210 
    211 int  ace_ebus_intr(void *cookie, void *f);
    212 
    213 static void sysace_thread(void *arg);
    214 
    215 int
    216 ace_ebus_match(struct device *parent, struct cfdata *match, void *aux)
    217 {
    218 	struct ebus_attach_args *d = aux;
    219     struct _Sac *sac = (struct _Sac *)d->ia_vaddr;
    220 
    221     if (strcmp("ace", d->ia_name) != 0)
    222 		return (0);
    223     if ((sac == NULL) ||
    224         ((sac->Tag & SAC_TAG) != PMTTAG_SYSTEM_ACE))
    225         return 0;
    226 	return (1);
    227 }
    228 
    229 void
    230 ace_ebus_attach(struct device *parent, struct device *self, void *aux)
    231 {
    232 	struct ace_softc *ace = device_private(self);
    233 	struct ebus_attach_args *ia = aux;
    234 	int error;
    235 
    236 	/*
    237 	 * It's on the baseboard, with a dedicated interrupt line.
    238 	 */
    239 	ace->sc_dr = (struct _Sac *)ia->ia_vaddr;
    240 	ace->sc_dev = self;
    241 #if DEBUG
    242 	printf(" virt=%p", (void*)ace->sc_dr);
    243 #endif
    244 	printf(" : System ACE\n");
    245 
    246 	ebus_intr_establish(parent, (void*)ia->ia_cookie, IPL_BIO,
    247 	    ace_ebus_intr, ace);
    248 
    249 	config_pending_incr();
    250 
    251 	error = kthread_create(PRI_NONE, 0, NULL, sysace_thread,
    252 	    ace, NULL, "%s", device_xname(ace->sc_dev));
    253 	if (error)
    254 		aprint_error_dev(ace->sc_dev, "unable to create kernel "
    255 		    "thread: error %d\n", error);
    256 }
    257 
    258 /* Sysace driver I(af) wrote for FreeBsd.
    259  */
    260 #define CF_SECBITS     9
    261 #define CF_SECTOR_SIZE (1 << CF_SECBITS)
    262 
    263 static int sysace_attach(struct ace_softc *sc);
    264 static int sysace_reset(struct ace_softc *sc);
    265 static int sysace_identify(struct ace_softc *sc);
    266 static int sysace_lock_registers(struct ace_softc *sc);
    267 static int sysace_unlock_registers(struct ace_softc *sc);
    268 static int sysace_start(struct ace_softc *sc, uint32_t Command, uint32_t Lba, uint32_t nSectors);
    269 static int sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize);
    270 static int sysace_read_at (struct ace_softc *sc, daddr_t start_sector, char *buffer,
    271                            size_t nblocks, size_t * pSizeRead);
    272 static int sysace_write_at(struct ace_softc *sc, daddr_t start_sector, char *buffer,
    273                            size_t nblocks, size_t * pSizeWritten);
    274 #ifdef USE_ACE_FOR_RECONFIG /* Old code, despised and replaced by ICAP */
    275 static int sysace_send_config(struct ace_softc *sc,
    276                               uint32_t *Data, unsigned int nBytes);
    277 #endif
    278 
    279 #define DEBUG_INTR   0x01
    280 #define DEBUG_XFERS  0x02
    281 #define DEBUG_STATUS 0x04
    282 #define DEBUG_FUNCS  0x08
    283 #define DEBUG_PROBE  0x10
    284 #define DEBUG_WRITES 0x20
    285 #define DEBUG_READS  0x40
    286 #define DEBUG_ERRORS 0x80
    287 #ifdef DEBUG
    288 int ace_debug = DEBUG_ERRORS;//|DEBUG_WRITES;
    289 #define ACE_DEBUG(x) (ace_debug & (x))
    290 #define DBGME(_lev_,_x_) if ((_lev_) & ace_debug) _x_
    291 #else
    292 #define ACE_DEBUG(x) (0)
    293 #define DBGME(_lev_,_x_)
    294 #endif
    295 #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_)
    296 
    297 static int
    298 sysace_attach(struct ace_softc *sc)
    299 {
    300     int error;
    301 
    302     DBGME(DEBUG_FUNCS,printf("Sysace::delayed_attach %p\n", sc));
    303 
    304     sc->media_has_changed = TRUE;
    305     sc->sc_capacity = 0;
    306 
    307     error = sysace_reset(sc);
    308     if (error) {
    309         device_printf(sc->sc_dev,"failed to reset, errno=%d\n", error);
    310         goto Out;
    311     }
    312 
    313     error = sysace_identify(sc);
    314     if (error) {
    315         device_printf(sc->sc_dev,"failed to identify card, errno=%d.\n", error);
    316         goto Out;
    317     }
    318 
    319     DBGME(DEBUG_PROBE,device_printf(sc->sc_dev,"Card has %qx sectors.\n", sc->sc_capacity));
    320 	if (sc->sc_capacity == 0) {
    321         device_printf(sc->sc_dev,"size 0, no card? Wont work.\n");
    322         error = EDOOFUS;
    323 	goto Out;
    324     }
    325 
    326     sc->media_has_changed = FALSE;
    327 Out:
    328     return error;
    329 }
    330 
    331 static void
    332 sysace_wedges(void *arg);
    333 extern int	dkwedge_autodiscover;
    334 
    335 /* Aux temp thread to avoid deadlock when doing the partitio.. ahem wedges thing.
    336  */
    337 static void
    338 sysace_wedges(void *arg)
    339 {
    340 	struct ace_softc *sc = (struct ace_softc*)arg;
    341 
    342 	DBGME(DEBUG_STATUS,printf("Sysace::wedges started for %p\n", sc));
    343 
    344 	/* Discover wedges on this disk. */
    345 	dkwedge_autodiscover = 1;
    346 	dkwedge_discover(&sc->sc_dk);
    347 
    348 	config_pending_decr();
    349 
    350 	DBGME(DEBUG_STATUS,printf("Sysace::thread done for %p\n", sc));
    351 	    kthread_exit(0);
    352 }
    353 
    354 static void
    355 sysace_thread(void *arg)
    356 {
    357 	struct ace_softc *sc = (struct ace_softc*)arg;
    358 	struct buf *bp;
    359 	int s, error;
    360 
    361 	DBGME(DEBUG_STATUS,printf("Sysace::thread started for %p\n", sc));
    362 
    363 	s = splbio();
    364 	aceattach(sc);
    365 	splx(s);
    366 
    367 	error = kthread_create(PRI_NONE, 0 /* MPSAFE??? */, NULL,
    368 	    sysace_wedges, sc, NULL, "%s.wedges", device_xname(sc->sc_dev));
    369 	if (error)
    370 		aprint_error_dev(sc->sc_dev, "wedges: unable to create "
    371 		    "kernel thread: error %d\n", error);
    372 
    373     DBGME(DEBUG_STATUS,printf("Sysace::thread service active for %p\n", sc));
    374 
    375     s = splbio();
    376 	for (;;) {
    377         /* Get next I/O request, wait if necessary
    378          */
    379 		if ((sc->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 &&
    380 		    (sc->active_xfer == NULL)) {
    381 			sc->ch_flags &= ~ATACH_TH_RUN;
    382 			(void) tsleep(&sc->ch_thread, PRIBIO, "aceth", 0);
    383 			sc->ch_flags |= ATACH_TH_RUN;
    384 		}
    385 		if (sc->ch_flags & ATACH_SHUTDOWN) {
    386 			break;
    387         }
    388         bp = sc->active_xfer;
    389         sc->active_xfer = NULL;
    390 		if (bp != NULL) {
    391 
    392             size_t sz, bnow;
    393 
    394             DBGME(DEBUG_XFERS,printf("Sysace::task %p %p %x %p %qx %d (%zd)\n", sc, bp,
    395                                      sc->sc_bio.flags, sc->sc_bio.databuf, sc->sc_bio.blkno,
    396                                      sc->sc_bio.nbytes, sc->sc_bio.nblks));
    397 
    398             sc->sc_bio.error = 0;
    399             for (; sc->sc_bio.nblks > 0;) {
    400 
    401                 bnow = sc->sc_bio.nblks;
    402                 if (sc->sc_bio.flags & ATA_SINGLE) bnow = 1;
    403 
    404                 if (sc->sc_bio.flags & ATA_READ) {
    405                     sc->sc_bio.error =
    406                         sysace_read_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz);
    407                 } else {
    408                     sc->sc_bio.error =
    409                         sysace_write_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz);
    410                 }
    411 
    412                 if (FAILED(sc->sc_bio.error))
    413                     break;
    414 
    415                 sc->sc_bio.blkno += sz; /* in blocks */
    416                 sc->sc_bio.nblks -= sz;
    417                 sc->sc_bio.blkdone += sz;
    418                 sz = sz << CF_SECBITS; /* in bytes */
    419                 sc->sc_bio.databuf += sz;
    420                 sc->sc_bio.nbytes  -= sz;
    421             }
    422 
    423             acedone(sc);
    424         }
    425 	}
    426 
    427 	splx(s);
    428 	sc->ch_thread = NULL;
    429 	wakeup(&sc->ch_flags);
    430 	kthread_exit(0);
    431 }
    432 
    433 /* Worker routines
    434  */
    435 #if _DEBUG
    436 typedef char *NAME;
    437 typedef struct _REGDESC {
    438     NAME RegisterName;
    439     NAME BitNames[32];
    440 } REGDESC, *PREGDESC;
    441 
    442 static void SysacePrintRegister(const REGDESC *Desc, uint32_t Value)
    443 {
    444     int i;
    445     printf("\t%s %x =", Desc->RegisterName, Value);
    446     for (i = 31; i >= 0; i--) {
    447         if (Value & (1 << i))
    448             printf(" %s",
    449                      (Desc->BitNames[i]) ? Desc->BitNames[i] : "?");
    450     }
    451     printf("\n");
    452 }
    453 
    454 static uint32_t SysaceDumpRegisters(struct _Sac *regs)
    455 {
    456 	const REGDESC Control_Names =
    457         { "Control",
    458           {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    459           "RST", //			0x00010000
    460           "BUS8", //		0x00020000
    461           "BUS16", //		0x00040000
    462           "BUS32", //		0x00080000
    463           "IRQ", //			0x00100000
    464           "BRDY", //		0x00200000
    465           "IMSK0", //		0x00400000
    466           "IMSK1", //		0x00800000
    467           "TD0", //	    	0x0f000000
    468           "TD1", //		    0x0f000000
    469           "TD2", //	    	0x0f000000
    470           "TD3", //	    	0x0f000000
    471           "BUFW8", //		0x10000000
    472           "BUFW16", //		0x20000000
    473           "BUFW32", //		0x40000000
    474           "DEBUG"} //		0x80000000
    475         };
    476 
    477 	const REGDESC STATUS_Names =
    478         { "STATUS",
    479           {"CFGLOCK", //	0x00000001
    480           "MPULOCK", //		0x00000002
    481           "CFGERROR", //	0x00000004
    482           "CFCERROR", //	0x00000008
    483           "CFDETECT", //	0x00000010
    484           "DATABUFRDY", //	0x00000020
    485           "DATABUFWRITE", //0x00000040
    486           "CFGDONE", //		0x00000080
    487           "RDYFORCFCMD", //	0x00000100
    488           "CFGMODEPIN", //	0x00000200
    489           0,0,0,
    490           "CFGADDRPIN0", //	0x0000e000
    491           "CFGADDRPIN1", //	0x0000e000
    492           "CFGADDRPIN2", //	0x0000e000
    493           0,
    494           "CFBSY", //		0x00020000
    495           "CFRDY", //		0x00040000
    496           "CFDWF", //		0x00080000
    497           "CFDSC", //		0x00100000
    498           "CFDRQ", //		0x00200000
    499           "CFCORR", //		0x00400000
    500           "CFERR", //		0x00800000
    501           0,}
    502         };
    503 
    504 	const REGDESC ERRORREG_Names =
    505         { "ERRORREG",
    506           {"CARDRESETERR", //			0x00000001
    507           "CARDRDYERR", //				0x00000002
    508           "CARDREADERR", //				0x00000004
    509           "CARDWRITEERR", //			0x00000008
    510           "SECTORRDYERR", //			0x00000010
    511           "CFGADDRERR", //				0x00000020
    512           "CFGFAILED", //				0x00000040
    513           "CFGREADERR", //				0x00000080
    514           "CFGINSTRERR", //				0x00000100
    515           "CFGINITERR", //				0x00000200
    516           0,
    517           "CFBBK", //					0x00000800
    518           "CFUNC", //					0x00001000
    519           "CFIDNF", //					0x00002000
    520           "CFABORT", //					0x00004000
    521           "CFAMNF", //					0x00008000
    522            0,}
    523         };
    524 
    525     const NAME CommandNames[8] =
    526         { "0", //     				0x0000
    527           "RESETMEMCARD", //   		0x0100
    528           "IDENTIFYMEMCARD", //		0x0200
    529           "READMEMCARDDATA", //		0x0300
    530           "WRITEMEMCARDDATA", //  	0x0400
    531           "5", //     				0x0500
    532           "ABORT", //			    0x0600
    533           "7" //     			    0x0700
    534         };
    535 
    536 	const REGDESC CONTROLREG_Names =
    537         { "CONTROLREG",
    538           {"FORCELOCKREQ", //			0x00000001
    539           "LOCKREQ", //					0x00000002
    540           "FORCECFGADDR", //			0x00000004
    541           "FORCECFGMODE", //			0x00000008
    542           "CFGMODE", //					0x00000010
    543           "CFGSTART", //				0x00000020
    544           "CFGSEL_MPU", //  			0x00000040
    545           "CFGRESET", //				0x00000080
    546           "DATABUFRDYIRQ", //			0x00000100
    547           "ERRORIRQ", //				0x00000200
    548           "CFGDONEIRQ", //				0x00000400
    549           "RESETIRQ", //				0x00000800
    550           "CFGPROG", //					0x00001000
    551           "CFGADDR_B0", //				0x00002000
    552           "CFGADDR_B1", //				0x00004000
    553           "CFGADDR_B2", //				0x00008000
    554           0,}
    555         };
    556 
    557 	const REGDESC FATSTATREG_Names =
    558         { "FATSTATREG",
    559           {"MBRVALID", //				0x00000001
    560           "PBRVALID", //				0x00000002
    561           "MBRFAT12", //				0x00000004
    562           "PBRFAT12", //				0x00000008
    563           "MBRFAT16", //				0x00000010
    564           "PBRFAT16", //				0x00000020
    565           "CALCFAT12", //				0x00000040
    566           "CALCFAT16", //				0x00000080
    567           0, }
    568         };
    569 
    570     printf("Sysace@%p:\n", regs);
    571     printf("\tTag %x\n", regs->Tag);
    572     SysacePrintRegister(&Control_Names, regs->Control);
    573     printf("\tBUSMODEREG %x\n", regs->BUSMODEREG);
    574     SysacePrintRegister(&STATUS_Names, regs->STATUS);
    575     SysacePrintRegister(&ERRORREG_Names, regs->ERRORREG);
    576     printf("\tCFGLBAREG %x\n", regs->CFGLBAREG);
    577     printf("\tMPULBAREG %x\n", regs->MPULBAREG);
    578     printf("\tVERSIONREG %x\n", regs->VERSIONREG);
    579     printf("\tSECCNTCMDREG %x = %s cnt=%d\n", regs->SECCNTCMDREG,
    580              CommandNames[(regs->SECCNTCMDREG >> 8)&7],
    581              regs->SECCNTCMDREG & SAC_SECCCNT);
    582     SysacePrintRegister(&CONTROLREG_Names, regs->CONTROLREG);
    583     SysacePrintRegister(&FATSTATREG_Names, regs->FATSTATREG);
    584 
    585     return 1;
    586 }
    587 
    588 #else
    589 #define SysaceDumpRegisters(_c_)
    590 #endif
    591 
    592 /* Reset the device and the interface
    593  */
    594 static int sysace_reset(struct ace_softc *sc)
    595 {
    596     struct _Sac *regs = sc->sc_dr;
    597 
    598     DBGME(DEBUG_FUNCS,printf("Sysace::Reset %p\n", sc));
    599 
    600     /* 16bit etc etc */
    601 	uint32_t BusMode, Control;
    602 
    603     /* reset our interface */
    604     regs->Control = SAC_RST;
    605     DELAY(200);
    606 
    607     /* repeat on both byte lanes */
    608 	regs->BUSMODEREG = SAC_MODE16 | (SAC_MODE16 << 8);
    609     DELAY(1);
    610 
    611     /* check what our interface does and what the SysACE expects */
    612 	Control = regs->Control;
    613 	BusMode = regs->BUSMODEREG;
    614 
    615     /* get them to agree */
    616 	if (BusMode & SAC_MODE16)
    617 	{
    618 		regs->Control = Control | SAC_BUS16;
    619 		regs->Control = regs->Control & ~SAC_BUS8;
    620 	}
    621 	else
    622 	{
    623 		regs->Control = Control | SAC_BUS8;
    624 		regs->Control = regs->Control & ~SAC_BUS16;
    625 	}
    626 
    627     /* check that it worked */
    628 	BusMode = regs->BUSMODEREG;
    629 	Control = regs->Control;
    630 
    631 	if (((BusMode & SAC_MODE16) == 0) && ((Control & SAC_BUS8) == 0)) return EDOOFUS;
    632 	if (((BusMode & SAC_MODE16) > 0) && ((Control & SAC_BUS16) == 0)) return EDOOFUS;
    633 
    634     /* interrupts off for now */
    635     regs->Control &= ~SAC_INTMASK;
    636 #define SAC_INTERRUPTS (SAC_DATABUFRDYIRQ |	SAC_ERRORIRQ )// | SAC_CFGDONEIRQ)
    637     Control = regs->CONTROLREG;
    638     Control = (Control & ~SAC_INTERRUPTS) | SAC_RESETIRQ | SAC_FORCECFGMODE;
    639     regs->CONTROLREG = Control;
    640     regs->CONTROLREG = Control & ~SAC_RESETIRQ;
    641 
    642     /* no command */
    643     regs->MPULBAREG = 0;
    644 
    645     return 0;
    646 }
    647 
    648 /* Take control of the ACE datapath
    649  */
    650 static int sysace_lock_registers(struct ace_softc *sc)
    651 {
    652     uint32_t Status;
    653     int i;
    654 
    655     DBGME(DEBUG_FUNCS,printf("Sysace::Lock %p\n", sc));
    656 
    657     /* Locked already?
    658      */
    659     Status = sc->sc_dr->STATUS;
    660     if (Status & SAC_MPULOCK)
    661         return TRUE;
    662 
    663     /* Request lock
    664      */
    665     sc->sc_dr->CONTROLREG |= SAC_LOCKREQ;
    666 
    667     /* Spin a bit until we get it
    668      */
    669     for (i = 0; i < 200; i++) {
    670         Status = sc->sc_dr->STATUS;
    671         if (Status & SAC_MPULOCK)
    672             return TRUE;
    673         DELAY(100);
    674         DBGME(DEBUG_FUNCS,printf("Sysace::Lock loops.. (st=%x)\n",Status));
    675     }
    676 
    677     /* oopsie!
    678      */
    679     DBGME(DEBUG_ERRORS,printf("Sysace::Lock timeout (st=%x)\n",Status));
    680     SysaceDumpRegisters(sc->sc_dr);
    681     return FALSE;
    682 }
    683 
    684 /* Release control of the ACE datapath
    685  */
    686 static int sysace_unlock_registers(struct ace_softc *sc)
    687 {
    688     uint32_t Status;
    689     int i;
    690 
    691     DBGME(DEBUG_FUNCS,printf("Sysace::Unlock %p\n", sc));
    692 
    693     /* Clear reset
    694      */
    695     sc->sc_dr->CONTROLREG &= ~SAC_CFGRESET;
    696 
    697     /* Unlocked already?
    698      */
    699     Status = sc->sc_dr->STATUS;
    700     if (0 == (Status & SAC_MPULOCK))
    701         return TRUE;
    702 
    703     /* Request unlock
    704      */
    705     sc->sc_dr->CONTROLREG &= ~SAC_LOCKREQ;
    706 
    707     /* Spin a bit until we get it
    708      */
    709     for (i = 0; i < 200; i++) {
    710         Status = sc->sc_dr->STATUS;
    711         if (0 == (Status & SAC_MPULOCK))
    712             return TRUE;
    713         DELAY(100);
    714         DBGME(DEBUG_FUNCS,printf("Sysace::Unlock loops.. (st=%x)\n",Status));
    715     }
    716 
    717     /* oopsie!
    718      */
    719     DBGME(DEBUG_ERRORS,printf("Sysace::Unlock timeout (st=%x)\n",Status));
    720     SysaceDumpRegisters(sc->sc_dr);
    721     return FALSE;
    722 }
    723 
    724 /* Check if the ACE is waiting for a comamnd
    725  */
    726 #define sysace_ready(_s_) ((_s_)->sc_dr->STATUS & SAC_RDYFORCFCMD)
    727 
    728 /* Check if the ACE is executing a comamnd
    729  */
    730 #define sysace_busy(_s_) ((_s_)->sc_dr->STATUS & SAC_CFBSY)
    731 
    732 /* Turn on interrupts from the ACE
    733  */
    734 #define sysace_inton(_s_) { \
    735           (_s_)->sc_dr->CONTROLREG |= SAC_INTERRUPTS; \
    736           (_s_)->sc_dr->Control |= SAC_INTMASK; \
    737 }
    738 
    739 /* Turn off interrupts from the ACE
    740  */
    741 #define sysace_intoff(_s_) { \
    742           (_s_)->sc_dr->CONTROLREG &= ~SAC_INTERRUPTS; \
    743           (_s_)->sc_dr->Control &= ~SAC_INTMASK; \
    744 }
    745 
    746 /* Start a command on the ACE, such as read or identify.
    747  */
    748 static int sysace_start(struct ace_softc *sc,
    749                         uint32_t Command,
    750                         uint32_t Lba,
    751                         uint32_t nSectors)
    752 {
    753     /* Lock it if not already
    754      */
    755     if (!sysace_lock_registers(sc)) {
    756         /* printed already */
    757         return ETIMEDOUT;
    758     }
    759 
    760     /* Is there a CF inserted
    761      */
    762     if (! (sc->sc_dr->STATUS & SAC_CFDETECT)) {
    763         /* NB: Not a failure state */
    764         DBGME(DEBUG_ERRORS,printf("Sysace:: no media (st=%x)\n",sc->sc_dr->STATUS));
    765         if (sc->sc_capacity) {
    766             sc->media_has_changed = TRUE;
    767             sc->sc_capacity = 0;
    768         }
    769         return ENODEV;
    770     }
    771 
    772     /* Is it ready for a command
    773      */
    774     if (!sysace_ready(sc)) {
    775         DBGME(DEBUG_ERRORS,printf("Sysace:: not ready (st=%x)\n",sc->sc_dr->STATUS));
    776         SysaceDumpRegisters(sc->sc_dr);
    777         return EBUSY;
    778     }
    779 
    780     /* sector number and command
    781      */
    782     sc->sc_dr->MPULBAREG = Lba;
    783     sc->sc_dr->SECCNTCMDREG = (uint16_t)(Command | (nSectors & SAC_SECCCNT));
    784 
    785     /* re-route the chip
    786      * NB: The "RESET" is actually not much of a misnomer.
    787      * The chip was designed for a one-shot execution at reset time,
    788      * namely loading the configuration data into the FPGA. So.
    789      */
    790     sc->hw_busy = TRUE;
    791     sc->sc_dr->CONTROLREG |= SAC_CFGRESET;
    792     return 0;
    793 }
    794 
    795 /* Identify the (size of the) CompactFlash card inserted in the slot.
    796  */
    797 static int sysace_identify(struct ace_softc *sc)
    798 {
    799     PCFLASH_IDENTIFY Identify = &sc->sc_params;
    800     uint32_t Status = 0;
    801     int i, j, error;
    802 
    803     DBGME(DEBUG_FUNCS,printf("Sysace::Identify %p\n", sc));
    804 
    805     /* Turn on interrupts before we start the command
    806      */
    807     sysace_inton(sc); /* BUGBUG we should add polling mode (for dump too) */
    808 
    809     /* This will invalidate the ACE's current sector data
    810      */
    811     sc->sc_capacity = 0;
    812 
    813     /* Get it going
    814      */
    815     error = sysace_start(sc,
    816                          SAC_CMD_IDENTIFYMEMCARD,
    817                          0,
    818                          1);
    819 
    820     /* Wait until its done
    821      */
    822     if (!FAILED(error)) {
    823 
    824         /* Might be called during autoconf, no interrupts */
    825         if (cold) {
    826             do {
    827                 DELAY(10);
    828                 Status = sc->sc_dr->STATUS;
    829             } while (0 == (Status & (SAC_DATABUFRDY|SAC_CFCERROR|SAC_CFGERROR)));
    830         } else {
    831             while (sc->hw_busy) {
    832                 DBGME(DEBUG_FUNCS,printf("Sysace:: cwait.. (st=%x) sizeof=%d\n",sc->sc_dr->STATUS, sizeof(*Identify)));
    833                 error = tsleep(&sc->media_has_changed, PRIBIO, "aceidfy", 0);
    834             }
    835         }
    836 
    837         /* Did it work?
    838          */
    839         Status = sc->sc_dr->STATUS;
    840 
    841         if (Status & SAC_DATABUFRDY) {
    842 
    843             /* Yes, pull out all the data.
    844              * NB: Until we do so the chip will not be ready for another command
    845              */
    846             for (i = 0; i < sizeof(*Identify); i += 4) {
    847 
    848                 /* Verify the (32-bytes) FIFO has reloaded
    849                  */
    850                 for (j = 0; j < 10; j++) {
    851                     Status = sc->sc_dr->STATUS;
    852                     if (Status & SAC_DATABUFRDY)
    853                         break;
    854                     DELAY(10);
    855                 }
    856                 if (Status & SAC_DATABUFRDY)
    857                 {
    858                     uint32_t Data32;
    859 
    860                     /* This pulls two 16-bit words out of the FIFO.
    861                      * They are ordered in LE.
    862                      * NB: Yes this is different from regular data accesses
    863                      */
    864                     Data32 = sc->sc_dr->DATABUFREG[0];
    865 #if _BYTE_ORDER == _LITTLE_ENDIAN
    866                     /* all is fine */
    867 #else
    868                     Data32 = (Data32 >> 16) | (Data32 << 16);
    869 #endif
    870                     memcpy(((char*)Identify)+i,&Data32,4);
    871                 }
    872                 else
    873                 /* Ooops, what's going on here?
    874                  */
    875                 {
    876                     DBGME(DEBUG_ERRORS,printf("Sysace::!DATABUFRDY %x\n",Status));
    877                     error = EIO;
    878                     break;
    879                 }
    880             }
    881 
    882             /* Make sure we did ok and pick up the relevant info
    883              */
    884             if (Status & SAC_DATABUFRDY)
    885             {
    886                 DBGME(DEBUG_XFERS,device_printf(sc->sc_dev,"model: %.40s/%.20s\n",
    887                               Identify->ModelNumber, Identify->SerialNumber));
    888                 if (Identify->Signature == CFLASH_SIGNATURE)
    889                 {
    890                     DBGME(DEBUG_PROBE,printf("Sysace::Card is %.40s::%.20s\n",
    891                                Identify->ModelNumber, Identify->SerialNumber));
    892 
    893                     sc->sc_capacity =
    894                         (Identify->SectorsPerCard[0] << 16) | Identify->SectorsPerCard[1];
    895                     DBGME(DEBUG_PROBE,printf("Sysace::sc_capacity x%qx\n", sc->sc_capacity));
    896                     ace_params_to_properties(sc);
    897                 } else {
    898                     DBGME(DEBUG_ERRORS,printf("Sysace::Bad card signature? %x != %x\n",
    899                                  Identify->Signature, CFLASH_SIGNATURE));
    900                     sc->sc_capacity = 0;
    901                     error = ENXIO;
    902                 }
    903             }
    904             else
    905             {
    906                 error = ETIMEDOUT;
    907             }
    908         }
    909         else
    910         /* No, it did not work. Maybe there is no card inserted
    911          */
    912         {
    913             DBGME(DEBUG_ERRORS,printf("Sysace::Identify failed, missing CFLASH card?\n"));
    914             SysaceDumpRegisters(sc->sc_dr);
    915             /* BUGBUG Fix the error code accordingly */
    916             error = ETIMEDOUT;
    917         }
    918     }
    919 
    920     /* remember this jic */
    921     sc->sc_bio.r_error = Status;
    922 
    923     /* Free the ACE for the JTAG, just in case */
    924     sysace_unlock_registers(sc);
    925 
    926     /* Done
    927      */
    928     return error;
    929 }
    930 
    931 /* Common code for read&write argument validation
    932  */
    933 static int sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize)
    934 {
    935     daddr_t Size;
    936 
    937     /* Verify that we know the media size
    938      */
    939     if (sc->sc_capacity == 0) {
    940         int error = sysace_identify(sc);
    941         if (FAILED(error))
    942             return error;
    943     }
    944 
    945     /* Validate args
    946      */
    947     if (start >= sc->sc_capacity) {
    948         *pSize = 0;
    949         DBGME(DEBUG_ERRORS,printf("Sysace::ValidateArg(%qx) EOF\n", start));
    950         return E2BIG;
    951     }
    952 
    953     /* Adjust size if necessary
    954      */
    955     Size = start + *pSize;
    956     if (Size > sc->sc_capacity) {
    957         /* At most this many sectors
    958          */
    959         Size = sc->sc_capacity - start;
    960         *pSize = (size_t)Size;
    961     }
    962 
    963     DBGME(DEBUG_FUNCS,printf("Sysace::Validate %qx %zd\n",  start,*pSize));
    964     return 0;
    965 }
    966 
    967 /* Read SIZE bytes from sysace device, at offset Position
    968  */
    969 uint32_t ace_maxatatime = 255;
    970 #define MAXATATIME ace_maxatatime //255 /* BUGBUG test me on real hardware!! */
    971 
    972 static int sysace_read_at (struct ace_softc *sc,
    973                            daddr_t start_sector, char *buffer, size_t nblocks,
    974                            size_t * pSizeRead)
    975 {
    976     int error;
    977     uint32_t BlocksThisTime;
    978     uint32_t Status = 0, SizeRead = 0;
    979     uint32_t i, j;
    980 
    981     DBGME(DEBUG_XFERS|DEBUG_READS,printf("SysaceReadAt(%p %qx %p %zd %p)\n",
    982                      sc, start_sector, buffer, nblocks, pSizeRead));
    983 
    984     /* Validate & trim arguments
    985      */
    986     error = sysace_validate(sc, start_sector, &nblocks);
    987 
    988     /* Repeat until we are done or error
    989      */
    990     while (error == 0) {
    991 
    992         /* .. one bunch of sectors at a time
    993          */
    994         BlocksThisTime = nblocks;
    995         if (BlocksThisTime > MAXATATIME)
    996             BlocksThisTime = MAXATATIME;
    997 
    998         /* Yes, start a sector read
    999          */
   1000         sysace_inton(sc);
   1001         error = sysace_start(sc,
   1002                              SAC_CMD_READMEMCARDDATA,
   1003                              (uint32_t)start_sector,  /* BUGBUG trims here, no warn. */
   1004                              BlocksThisTime);
   1005         /* And wait until done, if ok
   1006          */
   1007         if (!FAILED(error)) {
   1008             start_sector += BlocksThisTime;
   1009             /* Might be called during autoconf, no interrupts */
   1010             /* BUGBUG timeouts! */
   1011             if (cold) {
   1012                 do {
   1013                     DELAY(10);
   1014                     Status = sc->sc_dr->STATUS;
   1015                 } while (0 == (Status & (SAC_DATABUFRDY|SAC_CFCERROR|SAC_CFGERROR)));
   1016             } else {
   1017                 while (sc->hw_busy) {
   1018                     error = tsleep(&sc->media_has_changed, PRIBIO, "aceread", 0);
   1019                 }
   1020             }
   1021         }
   1022 
   1023         /* Are we doing ok
   1024          */
   1025         if (!FAILED(error)) {
   1026 
   1027             /* Get the data out of the ACE
   1028              */
   1029             for (i = 0; i < (BlocksThisTime << CF_SECBITS); i += 4) {
   1030 
   1031                 /* Make sure the FIFO is ready
   1032                  */
   1033                 for (j = 0; j < 10; j++) {
   1034                     Status = sc->sc_dr->STATUS;
   1035                     if (Status & SAC_DATABUFRDY)
   1036                         break;
   1037                     DELAY(1000);
   1038                 }
   1039 
   1040                 /* Got it?
   1041                  */
   1042                 if (Status & SAC_DATABUFRDY) {
   1043                     uint32_t Data32;
   1044 
   1045                     Data32 = sc->sc_dr->DATABUFREG[0];
   1046                     Data32 = le32toh(Data32);
   1047                     memcpy(buffer+i,&Data32,4);
   1048                 }
   1049                 else
   1050                 {
   1051                     /* Ooops, get out of here
   1052                      */
   1053                     DBGME(DEBUG_ERRORS,printf("Sysace::READ timeout\n"));
   1054                     SysaceDumpRegisters(sc->sc_dr);
   1055                     error = ETIMEDOUT;
   1056                     break;
   1057                 }
   1058             }
   1059 
   1060             /* Still doing ok?
   1061              */
   1062             if (!FAILED(error)) {
   1063                 nblocks   -= BlocksThisTime;
   1064                 SizeRead  += BlocksThisTime;
   1065                 buffer    += BlocksThisTime << CF_SECBITS;
   1066             }
   1067             else
   1068                 /* remember this jic */
   1069                 sc->sc_bio.r_error = Status;
   1070         }
   1071 
   1072         /* Free the ACE for the JTAG, just in case */
   1073         sysace_unlock_registers(sc);
   1074 
   1075         /* Are we done yet?
   1076          */
   1077         if (nblocks == 0)
   1078             break;
   1079     }
   1080 
   1081     if (pSizeRead)
   1082         *pSizeRead = SizeRead;
   1083     return error;
   1084 }
   1085 
   1086 /* Write SIZE bytes to device.
   1087  */
   1088 static int sysace_write_at (struct ace_softc *sc,
   1089                            daddr_t start_sector, char *buffer, size_t nblocks,
   1090                            size_t * pSizeWritten)
   1091 {
   1092     int error;
   1093     uint32_t BlocksThisTime;
   1094     uint32_t Status = 0, SizeWritten = 0;
   1095     uint32_t i, j;
   1096 
   1097     DBGME(DEBUG_XFERS|DEBUG_WRITES,printf("SysaceWriteAt(%p %qx %p %zd %p)\n",
   1098                      sc, start_sector, buffer, nblocks, pSizeWritten));
   1099 
   1100     /* Validate & trim arguments
   1101      */
   1102     error = sysace_validate(sc, start_sector, &nblocks);
   1103 
   1104     /* Repeat until we are done or error
   1105      */
   1106     while (error == 0) {
   1107 
   1108         /* .. one sector at a time
   1109          * BUGBUG Supposedly we can do up to 256 sectors?
   1110          */
   1111         BlocksThisTime = nblocks;
   1112         if (BlocksThisTime > MAXATATIME)
   1113             BlocksThisTime = MAXATATIME;
   1114 
   1115         /* Yes, start a sector write
   1116          */
   1117         sysace_inton(sc);
   1118         error = sysace_start(sc,
   1119                              SAC_CMD_WRITEMEMCARDDATA,
   1120                              (uint32_t)start_sector,  /* BUGBUG trims here, no warn. */
   1121                              BlocksThisTime);
   1122         /* And wait until done, if ok
   1123          */
   1124         if (!FAILED(error)) {
   1125             start_sector += BlocksThisTime;
   1126             /* BUGBUG timeouts! */
   1127             while (sc->hw_busy) {
   1128                 error = tsleep(&sc->media_has_changed, PRIBIO, "acewrite", 0);
   1129             }
   1130         }
   1131 
   1132         /* Are we doing ok
   1133          */
   1134         if (!FAILED(error)) {
   1135 
   1136             /* Get the data out to the ACE
   1137              */
   1138             for (i = 0; i < (BlocksThisTime << CF_SECBITS); i += 4) {
   1139 
   1140                 /* Make sure the FIFO is ready
   1141                  */
   1142                 for (j = 0; j < 10; j++) {
   1143                     Status = sc->sc_dr->STATUS;
   1144                     if (Status & SAC_DATABUFRDY)
   1145                         break;
   1146                     DELAY(1000);
   1147                 }
   1148 
   1149                 /* Got it?
   1150                  */
   1151                 if (Status & SAC_DATABUFRDY) {
   1152                     uint32_t Data32;
   1153 
   1154                     memcpy(&Data32,buffer+i,4);
   1155                     Data32 = htole32(Data32);
   1156                     sc->sc_dr->DATABUFREG[0] = Data32;
   1157                 }
   1158                 else
   1159                 {
   1160                     /* Ooops, get out of here
   1161                      */
   1162                     DBGME(DEBUG_ERRORS,printf("Sysace::WRITE timeout\n"));
   1163                     SysaceDumpRegisters(sc->sc_dr);
   1164                     error = ETIMEDOUT;
   1165                     /* remember this jic */
   1166                     sc->sc_bio.r_error = Status;
   1167                     break;
   1168                 }
   1169             }
   1170 
   1171             /* Still doing ok?
   1172              */
   1173             if (!FAILED(error)) {
   1174                 nblocks     -= BlocksThisTime;
   1175                 SizeWritten += BlocksThisTime;
   1176                 buffer      += BlocksThisTime << CF_SECBITS;
   1177             }
   1178         }
   1179 
   1180         /* We need to wait until the device is ready for the next command
   1181          * Experimentation shows that it can take longer than 10msec.
   1182          */
   1183         if (!FAILED(error)) {
   1184             for (j = 0; j < 300; j++) {
   1185                 Status = sc->sc_dr->STATUS;
   1186                 if (Status & SAC_RDYFORCFCMD)
   1187                     break;
   1188                 (void) tsleep(&sc->media_has_changed, PRIBIO, "acewrite", 2);
   1189             }
   1190             if (! (Status & SAC_RDYFORCFCMD)) {
   1191                 DBGME(DEBUG_ERRORS,printf("Sysace::WRITE-COMPLETE timeout St=%x\n", Status));
   1192                 SysaceDumpRegisters(sc->sc_dr);
   1193                 /* Ignore,  we'll handle it the next time around
   1194                  * BUGBUG To be revised along with non-existant error handling
   1195                  */
   1196             }
   1197         }
   1198 
   1199         /* Free the ACE for the JTAG, just in case */
   1200         sysace_unlock_registers(sc);
   1201 
   1202         /* Are we done yet?
   1203          */
   1204         if (nblocks == 0)
   1205             break;
   1206     }
   1207 
   1208     if (pSizeWritten)
   1209         *pSizeWritten = SizeWritten;
   1210     return error;
   1211 }
   1212 
   1213 int
   1214 ace_ebus_intr(void *cookie, void *f)
   1215 {
   1216 	struct ace_softc *sc = cookie;
   1217     uint32_t Control;
   1218 
   1219     /* Turn off interrupts and ACK them
   1220      */
   1221     sysace_intoff(sc);
   1222 
   1223     Control = sc->sc_dr->CONTROLREG & (~(SAC_RESETIRQ|SAC_INTERRUPTS));
   1224     sc->sc_dr->CONTROLREG = Control | SAC_RESETIRQ;
   1225     sc->sc_dr->CONTROLREG = Control;
   1226 
   1227     /* ... read status and do whatever ... */
   1228 
   1229     sc->hw_busy = FALSE;
   1230     wakeup(&sc->media_has_changed);
   1231     return 1;
   1232 }
   1233 
   1234 #ifdef USE_ACE_FOR_RECONFIG
   1235 static int sysace_send_config(struct ace_softc *sc,
   1236                               uint32_t *Data, unsigned int nBytes)
   1237 {
   1238     struct _Sac *Interface = sc->sc_dr;
   1239     unsigned int i, j, nWords;
   1240     uint32_t CtlWas;
   1241     uint32_t Status;
   1242 
   1243     CtlWas = Interface->CONTROLREG;
   1244 
   1245     /* Set the bits but in RESET (pag 49-50 of specs)*/
   1246 #define CFGCMD (SAC_FORCELOCKREQ | SAC_LOCKREQ | SAC_CFGSEL | \
   1247                 SAC_FORCECFGMODE |/* SAC_CFGMODE |*/ SAC_CFGSTART)
   1248 
   1249     Interface->CONTROLREG = CFGCMD | SAC_CFGRESET;
   1250 
   1251     /* Take it out of RESET */
   1252     Interface->CONTROLREG = CFGCMD;
   1253 
   1254     /* Must wait till it says READY
   1255      * It can take a looong time
   1256      */
   1257     for (j = 0; j < 1000; j++) {
   1258         Status = Interface->STATUS;
   1259         if (Status & SAC_RDYFORCFCMD)
   1260             break;
   1261         DELAY(1000);
   1262     }
   1263 
   1264     if (0 == (Status & SAC_RDYFORCFCMD)) {
   1265         DBGME(DEBUG_ERRORS,printf("Sysace::CMD error %x (j=%d)\n", Status, j));
   1266         goto Error;
   1267     }
   1268 
   1269     /* Get the data out to the ACE
   1270      */
   1271 #define ACEROUNDUP 32
   1272     nBytes = (nBytes + ACEROUNDUP - 1) & ~(ACEROUNDUP-1);
   1273     nWords = (nBytes + 3) / 4;
   1274     DBGME(DEBUG_FUNCS,printf("Sending %d bytes (as %d words) to %p ",
   1275                      nBytes, nWords, Interface));
   1276     for (i = 0; i < nWords; i += 1/*word*/) {
   1277 
   1278         /* Stop on errors */
   1279         Status = Interface->ERRORREG;
   1280         if (Status) {
   1281             /* Ooops, get out of here
   1282              */
   1283             DBGME(DEBUG_ERRORS,printf("Sysace::CFG error %x (i=%d)\n", Status, i));
   1284             goto Error;
   1285         }
   1286 
   1287         /* Make sure the FIFO is ready
   1288          */
   1289         for (j = 0; j < 100; j++) {
   1290             Status = Interface->STATUS;
   1291             if (Status & SAC_DATABUFRDY)
   1292                 break;
   1293             DELAY(1000);
   1294         }
   1295 
   1296         /* Got it?
   1297          */
   1298         if (Status & SAC_DATABUFRDY) {
   1299             uint32_t Data32;
   1300 
   1301             Data32 = Data[i];
   1302             Data32 = htole32(Data32);
   1303             Interface->DATABUFREG[0] = Data32;
   1304         }
   1305         else
   1306         {
   1307             /* Ooops, get out of here
   1308              */
   1309             DBGME(DEBUG_ERRORS,printf("Sysace::WRITE timeout %x (i=%d)\n", Status, i));
   1310             goto Error;
   1311         }
   1312     }
   1313     DBGME(DEBUG_FUNCS,printf("done ok.\n"));
   1314 
   1315     /* Put it back the way it was (try to.. :-( )*/
   1316     Interface->CONTROLREG = CtlWas;
   1317     return 0;
   1318 
   1319  Error:
   1320     SysaceDumpRegisters(Interface);
   1321     Interface->CONTROLREG = CtlWas;
   1322     return (EIO);
   1323 }
   1324 #endif /* USE_ACE_FOR_RECONFIG */
   1325 
   1326 
   1327 /* Rest of code lifted with mods from the dev\ata\wd.c driver
   1328  */
   1329 
   1330 /*	$NetBSD: ace_ebus.c,v 1.1 2011/01/26 01:18:50 pooka Exp $ */
   1331 
   1332 /*
   1333  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
   1334  *
   1335  * Redistribution and use in source and binary forms, with or without
   1336  * modification, are permitted provided that the following conditions
   1337  * are met:
   1338  * 1. Redistributions of source code must retain the above copyright
   1339  *	notice, this list of conditions and the following disclaimer.
   1340  * 2. Redistributions in binary form must reproduce the above copyright
   1341  *	notice, this list of conditions and the following disclaimer in the
   1342  *	documentation and/or other materials provided with the distribution.
   1343  * 3. All advertising materials mentioning features or use of this software
   1344  *	must display the following acknowledgement:
   1345  *  This product includes software developed by Manuel Bouyer.
   1346  * 4. The name of the author may not be used to endorse or promote products
   1347  *	derived from this software without specific prior written permission.
   1348  *
   1349  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   1350  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   1351  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   1352  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   1353  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   1354  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   1355  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   1356  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   1357  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   1358  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1359  */
   1360 
   1361 /*-
   1362  * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
   1363  * All rights reserved.
   1364  *
   1365  * This code is derived from software contributed to The NetBSD Foundation
   1366  * by Charles M. Hannum and by Onno van der Linden.
   1367  *
   1368  * Redistribution and use in source and binary forms, with or without
   1369  * modification, are permitted provided that the following conditions
   1370  * are met:
   1371  * 1. Redistributions of source code must retain the above copyright
   1372  *    notice, this list of conditions and the following disclaimer.
   1373  * 2. Redistributions in binary form must reproduce the above copyright
   1374  *    notice, this list of conditions and the following disclaimer in the
   1375  *    documentation and/or other materials provided with the distribution.
   1376  * 3. All advertising materials mentioning features or use of this software
   1377  *    must display the following acknowledgement:
   1378  *        This product includes software developed by the NetBSD
   1379  *        Foundation, Inc. and its contributors.
   1380  * 4. Neither the name of The NetBSD Foundation nor the names of its
   1381  *    contributors may be used to endorse or promote products derived
   1382  *    from this software without specific prior written permission.
   1383  *
   1384  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   1385  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   1386  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   1387  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   1388  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   1389  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   1390  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   1391  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   1392  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   1393  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   1394  * POSSIBILITY OF SUCH DAMAGE.
   1395  */
   1396 
   1397 static const char ST506[] = "ST506";
   1398 
   1399 #define	ACEIORETRIES_SINGLE 4	/* number of retries before single-sector */
   1400 #define	ACEIORETRIES	5	/* number of retries before giving up */
   1401 #define	RECOVERYTIME hz/2	/* time to wait before retrying a cmd */
   1402 
   1403 #define	ACEUNIT(dev)		DISKUNIT(dev)
   1404 #define	ACEPART(dev)		DISKPART(dev)
   1405 #define	ACEMINOR(unit, part)	DISKMINOR(unit, part)
   1406 #define	MAKEACEDEV(maj, unit, part)	MAKEDISKDEV(maj, unit, part)
   1407 
   1408 #define	ACELABELDEV(dev)	(MAKEACEDEV(major(dev), ACEUNIT(dev), RAW_PART))
   1409 
   1410 void	aceperror(const struct ace_softc *);
   1411 
   1412 extern struct cfdriver ace_cd;
   1413 
   1414 dev_type_open(aceopen);
   1415 dev_type_close(aceclose);
   1416 dev_type_read(aceread);
   1417 dev_type_write(acewrite);
   1418 dev_type_ioctl(aceioctl);
   1419 dev_type_strategy(acestrategy);
   1420 dev_type_dump(acedump);
   1421 dev_type_size(acesize);
   1422 
   1423 const struct bdevsw ace_bdevsw = {
   1424 	aceopen, aceclose, acestrategy, aceioctl, acedump, acesize, D_DISK
   1425 };
   1426 
   1427 const struct cdevsw ace_cdevsw = {
   1428 	aceopen, aceclose, aceread, acewrite, aceioctl,
   1429 	nostop, notty, nopoll, nommap, nokqfilter, D_DISK
   1430 };
   1431 
   1432 void  acegetdefaultlabel(struct ace_softc *, struct disklabel *);
   1433 void  acegetdisklabel(struct ace_softc *);
   1434 void  acestart(void *);
   1435 void  __acestart(struct ace_softc*, struct buf *);
   1436 void  acerestart(void *);
   1437 
   1438 struct dkdriver acedkdriver = { acestrategy, minphys };
   1439 
   1440 #ifdef HAS_BAD144_HANDLING
   1441 static void bad144intern(struct ace_softc *);
   1442 #endif
   1443 
   1444 void
   1445 aceattach(struct ace_softc *ace)
   1446 {
   1447 	struct device *self = ace->sc_dev;
   1448 	char tbuf[41], pbuf[9], c, *p, *q;
   1449 	int i, blank;
   1450 	DEBUG_PRINT(("aceattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
   1451 
   1452 	callout_init(&ace->sc_restart_ch, 0);
   1453 	bufq_alloc(&ace->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
   1454 
   1455     ace->openings = 1; /* wazziz?*/
   1456     ace->sc_multi = MAXATATIME;
   1457 
   1458 	aprint_naive("\n");
   1459 
   1460 	/* setup all required fields so that if the attach fails we are ok */
   1461 	ace->sc_dk.dk_driver = &acedkdriver;
   1462 	ace->sc_dk.dk_name = device_xname(ace->sc_dev);
   1463 
   1464 	/* read our drive info */
   1465 	if (sysace_attach(ace) != 0) {
   1466 		aprint_error_dev(ace->sc_dev, "attach failed\n");
   1467 		return;
   1468 	}
   1469 
   1470 	aprint_normal_dev(ace->sc_dev, "drive supports %d-sector PIO xfers\n",
   1471 	    ace->sc_multi);
   1472 
   1473 	for (blank = 0, p = ace->sc_params.ModelNumber, q = tbuf, i = 0;
   1474 	    i < sizeof(ace->sc_params.ModelNumber); i++) {
   1475 		c = *p++;
   1476 		if (c == '\0')
   1477 			break;
   1478 		if (c != ' ') {
   1479 			if (blank) {
   1480 				*q++ = ' ';
   1481 				blank = 0;
   1482 			}
   1483 			*q++ = c;
   1484 		} else
   1485 			blank = 1;
   1486 	}
   1487 	*q++ = '\0';
   1488 
   1489 	aprint_normal_dev(ace->sc_dev, "card is <%s>\n", tbuf);
   1490 
   1491 	format_bytes(pbuf, sizeof(pbuf), ace->sc_capacity * DEV_BSIZE);
   1492 	aprint_normal("%s: %s, %d cyl, %d head, %d sec, "
   1493 	    "%d bytes/sect x %llu sectors\n",
   1494 	    self->dv_xname, pbuf,
   1495 	    (int)(ace->sc_capacity /
   1496               (ace->sc_params.CurrentNumberOfHeads * ace->sc_params.CurrentSectorsPerTrack)),
   1497 	    ace->sc_params.CurrentNumberOfHeads, ace->sc_params.CurrentSectorsPerTrack,
   1498 	    DEV_BSIZE, (unsigned long long)ace->sc_capacity);
   1499 
   1500 	/*
   1501 	 * Attach the disk structure. We fill in dk_info later.
   1502 	 */
   1503 	disk_attach(&ace->sc_dk);
   1504 
   1505 #if NRND > 0
   1506 	rnd_attach_source(&ace->rnd_source, device_xname(ace->sc_dev),
   1507 			  RND_TYPE_DISK, 0);
   1508 #endif
   1509 
   1510 }
   1511 
   1512 int
   1513 aceactivate(struct device *self, enum devact act)
   1514 {
   1515 	int rv = 0;
   1516 
   1517 	switch (act) {
   1518 	case DVACT_DEACTIVATE:
   1519 		/*
   1520 		 * Nothing to do; we key off the device's DVF_ACTIVATE.
   1521 		 */
   1522 		break;
   1523 	default:
   1524 		rv = EOPNOTSUPP;
   1525 	}
   1526 	return (rv);
   1527 }
   1528 
   1529 int
   1530 acedetach(struct device *self, int flags)
   1531 {
   1532 	struct ace_softc *sc = device_private(self);
   1533 	int s, bmaj, cmaj, i, mn;
   1534 
   1535 	/* locate the major number */
   1536 	bmaj = bdevsw_lookup_major(&ace_bdevsw);
   1537 	cmaj = cdevsw_lookup_major(&ace_cdevsw);
   1538 
   1539 	/* Nuke the vnodes for any open instances. */
   1540 	for (i = 0; i < MAXPARTITIONS; i++) {
   1541 		mn = ACEMINOR(device_unit(self), i);
   1542 		vdevgone(bmaj, mn, mn, VBLK);
   1543 		vdevgone(cmaj, mn, mn, VCHR);
   1544 	}
   1545 
   1546 	/* Delete all of our wedges. */
   1547 	dkwedge_delall(&sc->sc_dk);
   1548 
   1549 	s = splbio();
   1550 
   1551 	/* Kill off any queued buffers. */
   1552 	bufq_drain(sc->sc_q);
   1553 
   1554 	bufq_free(sc->sc_q);
   1555 	//sc->atabus->ata_killpending(sc->drvp);
   1556 
   1557 	splx(s);
   1558 
   1559 	/* Detach disk. */
   1560 	disk_detach(&sc->sc_dk);
   1561 
   1562 #if NRND > 0
   1563 	/* Unhook the entropy source. */
   1564 	rnd_detach_source(&sc->rnd_source);
   1565 #endif
   1566 
   1567 	//sc->drvp->drive_flags = 0; /* no drive any more here */
   1568 
   1569 	return (0);
   1570 }
   1571 
   1572 /*
   1573  * Read/write routine for a buffer.  Validates the arguments and schedules the
   1574  * transfer.  Does not wait for the transfer to complete.
   1575  */
   1576 void
   1577 acestrategy(struct buf *bp)
   1578 {
   1579 	struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(bp->b_dev));
   1580 	struct disklabel *lp;
   1581 	daddr_t blkno;
   1582 	int s;
   1583 
   1584 	if (ace == NULL) {
   1585 	    bp->b_error = ENXIO;
   1586 	    biodone(bp);
   1587 	    return;
   1588 	}
   1589 	lp = ace->sc_dk.dk_label;
   1590 
   1591 	DEBUG_PRINT(("acestrategy (%s) %lld\n", device_xname(ace->sc_dev), bp->b_blkno), DEBUG_XFERS);
   1592 
   1593 	/* Valid request?  */
   1594 	if (bp->b_blkno < 0 ||
   1595 	    (bp->b_bcount % lp->d_secsize) != 0 ||
   1596 	    (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
   1597 		bp->b_error = EINVAL;
   1598 		goto done;
   1599 	}
   1600 
   1601 	/* If device invalidated (e.g. media change, door open), error. */
   1602 	if ((ace->sc_flags & ACEF_LOADED) == 0) {
   1603 		bp->b_error = EIO;
   1604 		goto done;
   1605 	}
   1606 
   1607 	/* If it's a null transfer, return immediately. */
   1608 	if (bp->b_bcount == 0)
   1609 		goto done;
   1610 
   1611 	/*
   1612 	 * Do bounds checking, adjust transfer. if error, process.
   1613 	 * If end of partition, just return.
   1614 	 */
   1615 	if (ACEPART(bp->b_dev) == RAW_PART) {
   1616 		if (bounds_check_with_mediasize(bp, DEV_BSIZE,
   1617 		    ace->sc_capacity) <= 0)
   1618 			goto done;
   1619 	} else {
   1620 		if (bounds_check_with_label(&ace->sc_dk, bp,
   1621 		    (ace->sc_flags & (ACEF_WLABEL|ACEF_LABELLING)) != 0) <= 0)
   1622 			goto done;
   1623 	}
   1624 
   1625 	/*
   1626 	 * Now convert the block number to absolute and put it in
   1627 	 * terms of the device's logical block size.
   1628 	 */
   1629 	if (lp->d_secsize >= DEV_BSIZE)
   1630 		blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
   1631 	else
   1632 		blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
   1633 
   1634 	if (ACEPART(bp->b_dev) != RAW_PART)
   1635 		blkno += lp->d_partitions[ACEPART(bp->b_dev)].p_offset;
   1636 
   1637 	bp->b_rawblkno = blkno;
   1638 
   1639 	/* Queue transfer on drive, activate drive and controller if idle. */
   1640 	s = splbio();
   1641 	bufq_put(ace->sc_q, bp);
   1642 	acestart(ace);
   1643 	splx(s);
   1644 	return;
   1645 done:
   1646 	/* Toss transfer; we're done early. */
   1647 	bp->b_resid = bp->b_bcount;
   1648 	biodone(bp);
   1649 }
   1650 
   1651 /*
   1652  * Queue a drive for I/O.
   1653  */
   1654 void
   1655 acestart(void *arg)
   1656 {
   1657 	struct ace_softc *ace = arg;
   1658 	struct buf *bp = NULL;
   1659 
   1660 	DEBUG_PRINT(("acestart %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS);
   1661 	while (ace->openings > 0) {
   1662 
   1663 		/* Is there a buf for us ? */
   1664 		if ((bp = bufq_get(ace->sc_q)) == NULL)
   1665 			return;
   1666 
   1667 		/*
   1668 		 * Make the command. First lock the device
   1669 		 */
   1670 		ace->openings--;
   1671 
   1672 		ace->retries = 0;
   1673 		__acestart(ace, bp);
   1674 	}
   1675 }
   1676 
   1677 void
   1678 __acestart(struct ace_softc *sc, struct buf *bp)
   1679 {
   1680 	sc->sc_bp = bp;
   1681 	/*
   1682 	 * If we're retrying, retry in single-sector mode. This will give us
   1683 	 * the sector number of the problem, and will eventually allow the
   1684 	 * transfer to succeed.
   1685 	 */
   1686 	if (sc->retries >= ACEIORETRIES_SINGLE)
   1687 		sc->sc_bio.flags = ATA_SINGLE;
   1688 	else
   1689 		sc->sc_bio.flags = 0;
   1690 	if (bp->b_flags & B_READ)
   1691 		sc->sc_bio.flags |= ATA_READ;
   1692 	sc->sc_bio.blkno = bp->b_rawblkno;
   1693 	sc->sc_bio.blkdone = 0;
   1694 	sc->sc_bio.nbytes = bp->b_bcount;
   1695 	sc->sc_bio.nblks  = bp->b_bcount >> CF_SECBITS;
   1696 	sc->sc_bio.databuf = bp->b_data;
   1697 	/* Instrumentation. */
   1698 	disk_busy(&sc->sc_dk);
   1699     sc->active_xfer = bp;
   1700     wakeup(&sc->ch_thread);
   1701 }
   1702 
   1703 void
   1704 acedone(struct ace_softc *ace)
   1705 {
   1706 	struct buf *bp = ace->sc_bp;
   1707 	const char *errmsg;
   1708 	int do_perror = 0;
   1709 
   1710 	DEBUG_PRINT(("acedone %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS);
   1711 
   1712 	if (bp == NULL)
   1713 		return;
   1714 
   1715 	bp->b_resid = ace->sc_bio.nbytes;
   1716 	switch (ace->sc_bio.error) {
   1717 	case ETIMEDOUT:
   1718 		errmsg = "device timeout";
   1719         do_perror = 1;
   1720 		goto retry;
   1721 	case EBUSY:
   1722 	case EDOOFUS:
   1723 		errmsg = "device stuck";
   1724 retry:		/* Just reset and retry. Can we do more ? */
   1725 		sysace_reset(ace);
   1726 		diskerr(bp, "ace", errmsg, LOG_PRINTF,
   1727 		    ace->sc_bio.blkdone, ace->sc_dk.dk_label);
   1728 		if (ace->retries < ACEIORETRIES)
   1729 			printf(", retrying");
   1730 		printf("\n");
   1731 		if (do_perror)
   1732 			aceperror(ace);
   1733 		if (ace->retries < ACEIORETRIES) {
   1734 			ace->retries++;
   1735 			callout_reset(&ace->sc_restart_ch, RECOVERYTIME,
   1736 			    acerestart, ace);
   1737 			return;
   1738 		}
   1739 
   1740 		bp->b_error = EIO;
   1741 		break;
   1742 	case 0:
   1743         if ((ace->sc_bio.flags & ATA_CORR) || ace->retries > 0)
   1744 			printf("%s: soft error (corrected)\n",
   1745 			    device_xname(ace->sc_dev));
   1746 		break;
   1747 	case ENODEV:
   1748 	case E2BIG:
   1749 		bp->b_error = EIO;
   1750 		break;
   1751 	}
   1752 	disk_unbusy(&ace->sc_dk, (bp->b_bcount - bp->b_resid),
   1753 	    (bp->b_flags & B_READ));
   1754 #if NRND > 0
   1755 	rnd_add_uint32(&ace->rnd_source, bp->b_blkno);
   1756 #endif
   1757     biodone(bp);
   1758     ace->openings++;
   1759 	acestart(ace);
   1760 }
   1761 
   1762 void
   1763 acerestart(void *v)
   1764 {
   1765 	struct ace_softc *ace = v;
   1766 	struct buf *bp = ace->sc_bp;
   1767 	int s;
   1768 	DEBUG_PRINT(("acerestart %s\n", device_xname(ace->sc_dev)),DEBUG_XFERS);
   1769 
   1770 	s = splbio();
   1771 	__acestart(v, bp);
   1772 	splx(s);
   1773 }
   1774 
   1775 int
   1776 aceread(dev_t dev, struct uio *uio, int flags)
   1777 {
   1778 	int r;
   1779 
   1780 	DEBUG_PRINT(("aceread\n"), DEBUG_XFERS);
   1781 	r = physio(acestrategy, NULL, dev, B_READ, minphys, uio);
   1782 	DEBUG_PRINT(("aceread -> x%x resid=%x\n",r,uio->uio_resid),DEBUG_XFERS);
   1783 
   1784 	return r;
   1785 }
   1786 
   1787 int
   1788 acewrite(dev_t dev, struct uio *uio, int flags)
   1789 {
   1790 
   1791 	DEBUG_PRINT(("acewrite\n"), DEBUG_XFERS);
   1792 	return (physio(acestrategy, NULL, dev, B_WRITE, minphys, uio));
   1793 }
   1794 
   1795 int
   1796 aceopen(dev_t dev, int flag, int fmt, struct lwp *l)
   1797 {
   1798 	struct ace_softc *ace;
   1799 	int part, error;
   1800 
   1801 	DEBUG_PRINT(("aceopen\n"), DEBUG_FUNCS);
   1802 	ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
   1803 	if (ace == NULL)
   1804 		return (ENXIO);
   1805 
   1806 	if (! device_is_active(ace->sc_dev))
   1807 		return (ENODEV);
   1808 
   1809 	part = ACEPART(dev);
   1810 
   1811 	mutex_enter(&ace->sc_dk.dk_openlock);
   1812 
   1813 	/*
   1814 	 * If there are wedges, and this is not RAW_PART, then we
   1815 	 * need to fail.
   1816 	 */
   1817 	if (ace->sc_dk.dk_nwedges != 0 && part != RAW_PART) {
   1818 		error = EBUSY;
   1819 		goto bad;
   1820 	}
   1821 
   1822 	if (ace->sc_dk.dk_openmask != 0) {
   1823 		/*
   1824 		 * If any partition is open, but the disk has been invalidated,
   1825 		 * disallow further opens.
   1826 		 */
   1827 		if ((ace->sc_flags & ACEF_LOADED) == 0) {
   1828 			error = EIO;
   1829 			goto bad;
   1830 		}
   1831 	} else {
   1832 		if ((ace->sc_flags & ACEF_LOADED) == 0) {
   1833 			ace->sc_flags |= ACEF_LOADED;
   1834 
   1835 			/* Load the physical device parameters. */
   1836             if (ace->sc_capacity == 0) {
   1837                 error = sysace_identify(ace);
   1838                 if (error) goto bad;
   1839             }
   1840 
   1841 			/* Load the partition info if not already loaded. */
   1842 			acegetdisklabel(ace);
   1843 		}
   1844 	}
   1845 
   1846 	/* Check that the partition exists. */
   1847 	if (part != RAW_PART &&
   1848 	    (part >= ace->sc_dk.dk_label->d_npartitions ||
   1849 	     ace->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
   1850 		error = ENXIO;
   1851 		goto bad;
   1852 	}
   1853 
   1854 	/* Insure only one open at a time. */
   1855 	switch (fmt) {
   1856 	case S_IFCHR:
   1857 		ace->sc_dk.dk_copenmask |= (1 << part);
   1858 		break;
   1859 	case S_IFBLK:
   1860 		ace->sc_dk.dk_bopenmask |= (1 << part);
   1861 		break;
   1862 	}
   1863 	ace->sc_dk.dk_openmask =
   1864 	    ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask;
   1865 
   1866 	mutex_exit(&ace->sc_dk.dk_openlock);
   1867 	return 0;
   1868 
   1869  bad:
   1870 	mutex_exit(&ace->sc_dk.dk_openlock);
   1871 	return error;
   1872 }
   1873 
   1874 int
   1875 aceclose(dev_t dev, int flag, int fmt, struct lwp *l)
   1876 {
   1877 	struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
   1878 	int part = ACEPART(dev);
   1879 
   1880 	DEBUG_PRINT(("aceclose\n"), DEBUG_FUNCS);
   1881 	if (ace == NULL)
   1882 		return ENXIO;
   1883 
   1884 	mutex_enter(&ace->sc_dk.dk_openlock);
   1885 
   1886 	switch (fmt) {
   1887 	case S_IFCHR:
   1888 		ace->sc_dk.dk_copenmask &= ~(1 << part);
   1889 		break;
   1890 	case S_IFBLK:
   1891 		ace->sc_dk.dk_bopenmask &= ~(1 << part);
   1892 		break;
   1893 	}
   1894 	ace->sc_dk.dk_openmask =
   1895 	    ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask;
   1896 
   1897 	if (ace->sc_dk.dk_openmask == 0) {
   1898 
   1899 		if (! (ace->sc_flags & ACEF_KLABEL))
   1900 			ace->sc_flags &= ~ACEF_LOADED;
   1901 
   1902 	}
   1903 
   1904 	mutex_exit(&ace->sc_dk.dk_openlock);
   1905 	return 0;
   1906 }
   1907 
   1908 void
   1909 acegetdefaultlabel(struct ace_softc *ace, struct disklabel *lp)
   1910 {
   1911 
   1912 	DEBUG_PRINT(("acegetdefaultlabel\n"), DEBUG_FUNCS);
   1913 	memset(lp, 0, sizeof(struct disklabel));
   1914 
   1915 	lp->d_secsize = DEV_BSIZE;
   1916 	lp->d_ntracks = ace->sc_params.CurrentNumberOfHeads;
   1917 	lp->d_nsectors = ace->sc_params.CurrentSectorsPerTrack;
   1918 	lp->d_ncylinders = ace->sc_capacity /
   1919 		(ace->sc_params.CurrentNumberOfHeads * ace->sc_params.CurrentSectorsPerTrack);
   1920 	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
   1921 
   1922     lp->d_type = DTYPE_ST506; /* ?!? */
   1923 
   1924 	strncpy(lp->d_typename, ace->sc_params.ModelNumber, 16);
   1925 	strncpy(lp->d_packname, "fictitious", 16);
   1926 	if (ace->sc_capacity > UINT32_MAX)
   1927 		lp->d_secperunit = UINT32_MAX;
   1928 	else
   1929 		lp->d_secperunit = ace->sc_capacity;
   1930 	lp->d_rpm = 3600;
   1931 	lp->d_interleave = 1;
   1932 	lp->d_flags = 0;
   1933 
   1934 	lp->d_partitions[RAW_PART].p_offset = 0;
   1935 	lp->d_partitions[RAW_PART].p_size =
   1936 	    lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
   1937 	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
   1938 	lp->d_npartitions = RAW_PART + 1;
   1939 
   1940 	lp->d_magic = DISKMAGIC;
   1941 	lp->d_magic2 = DISKMAGIC;
   1942 	lp->d_checksum = dkcksum(lp);
   1943 }
   1944 
   1945 /*
   1946  * Fabricate a default disk label, and try to read the correct one.
   1947  */
   1948 void
   1949 acegetdisklabel(struct ace_softc *ace)
   1950 {
   1951 	struct disklabel *lp = ace->sc_dk.dk_label;
   1952 	const char *errstring;
   1953 
   1954 	DEBUG_PRINT(("acegetdisklabel\n"), DEBUG_FUNCS);
   1955 
   1956 	memset(ace->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
   1957 
   1958 	acegetdefaultlabel(ace, lp);
   1959 
   1960 #ifdef HAS_BAD144_HANDLING
   1961 	ace->sc_bio.badsect[0] = -1;
   1962 #endif
   1963 
   1964 	errstring = readdisklabel(MAKEACEDEV(0, device_unit(ace->sc_dev),
   1965 				  RAW_PART), acestrategy, lp,
   1966 				  ace->sc_dk.dk_cpulabel);
   1967 	if (errstring) {
   1968 		printf("%s: %s\n", device_xname(ace->sc_dev), errstring);
   1969 		return;
   1970 	}
   1971 
   1972 #if DEBUG
   1973     if (ACE_DEBUG(DEBUG_WRITES)) {
   1974         int i, n = ace->sc_dk.dk_label->d_npartitions;
   1975         printf("%s: %d parts\n", device_xname(ace->sc_dev), n);
   1976         for (i = 0; i < n; i++) {
   1977             printf("\t[%d]: t=%x s=%d o=%d\n", i,
   1978                    ace->sc_dk.dk_label->d_partitions[i].p_fstype,
   1979                    ace->sc_dk.dk_label->d_partitions[i].p_size,
   1980                    ace->sc_dk.dk_label->d_partitions[i].p_offset);
   1981         }
   1982     }
   1983 #endif
   1984 
   1985 #ifdef HAS_BAD144_HANDLING
   1986 	if ((lp->d_flags & D_BADSECT) != 0)
   1987 		bad144intern(ace);
   1988 #endif
   1989 }
   1990 
   1991 void
   1992 aceperror(const struct ace_softc *ace)
   1993 {
   1994 	const char *devname = device_xname(ace->sc_dev);
   1995 	u_int32_t Status = ace->sc_bio.r_error;
   1996 
   1997 	printf("%s: (", devname);
   1998 
   1999 	if (Status == 0)
   2000 		printf("error not notified");
   2001     else
   2002         printf("status=x%x", Status);
   2003 
   2004 	printf(")\n");
   2005 }
   2006 
   2007 int
   2008 aceioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
   2009 {
   2010 	struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
   2011 	int error = 0, s;
   2012 
   2013 	DEBUG_PRINT(("aceioctl\n"), DEBUG_FUNCS);
   2014 
   2015 	if ((ace->sc_flags & ACEF_LOADED) == 0)
   2016 		return EIO;
   2017 
   2018 	error = disk_ioctl(&ace->sc_dk, xfer, addr, flag, l);
   2019 	if (error != EPASSTHROUGH)
   2020 		return (error);
   2021 
   2022 	switch (xfer) {
   2023 #ifdef HAS_BAD144_HANDLING
   2024 	case DIOCSBAD:
   2025 		if ((flag & FWRITE) == 0)
   2026 			return EBADF;
   2027 		ace->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
   2028 		ace->sc_dk.dk_label->d_flags |= D_BADSECT;
   2029 		bad144intern(ace);
   2030 		return 0;
   2031 #endif
   2032 	case DIOCGDINFO:
   2033 		*(struct disklabel *)addr = *(ace->sc_dk.dk_label);
   2034 		return 0;
   2035 
   2036 	case DIOCGPART:
   2037 		((struct partinfo *)addr)->disklab = ace->sc_dk.dk_label;
   2038 		((struct partinfo *)addr)->part =
   2039 		    &ace->sc_dk.dk_label->d_partitions[ACEPART(dev)];
   2040 		return 0;
   2041 
   2042 	case DIOCWDINFO:
   2043 	case DIOCSDINFO:
   2044 	{
   2045 		struct disklabel *lp;
   2046 
   2047 		if ((flag & FWRITE) == 0)
   2048 			return EBADF;
   2049 
   2050 		lp = (struct disklabel *)addr;
   2051 
   2052 		mutex_enter(&ace->sc_dk.dk_openlock);
   2053 		ace->sc_flags |= ACEF_LABELLING;
   2054 
   2055 		error = setdisklabel(ace->sc_dk.dk_label,
   2056 		    lp, /*ace->sc_dk.dk_openmask : */0,
   2057 		    ace->sc_dk.dk_cpulabel);
   2058 		if (error == 0) {
   2059 			if (xfer == DIOCWDINFO)
   2060 				error = writedisklabel(ACELABELDEV(dev),
   2061 				    acestrategy, ace->sc_dk.dk_label,
   2062 				    ace->sc_dk.dk_cpulabel);
   2063 		}
   2064 
   2065 		ace->sc_flags &= ~ACEF_LABELLING;
   2066 		mutex_exit(&ace->sc_dk.dk_openlock);
   2067 		return error;
   2068 	}
   2069 
   2070 	case DIOCKLABEL:
   2071 		if (*(int *)addr)
   2072 			ace->sc_flags |= ACEF_KLABEL;
   2073 		else
   2074 			ace->sc_flags &= ~ACEF_KLABEL;
   2075 		return 0;
   2076 
   2077 	case DIOCWLABEL:
   2078 		if ((flag & FWRITE) == 0)
   2079 			return EBADF;
   2080 		if (*(int *)addr)
   2081 			ace->sc_flags |= ACEF_WLABEL;
   2082 		else
   2083 			ace->sc_flags &= ~ACEF_WLABEL;
   2084 		return 0;
   2085 
   2086 	case DIOCGDEFLABEL:
   2087 		acegetdefaultlabel(ace, (struct disklabel *)addr);
   2088 		return 0;
   2089 
   2090 	case DIOCCACHESYNC:
   2091 		return 0;
   2092 
   2093 	case DIOCAWEDGE:
   2094 	    {
   2095 	    	struct dkwedge_info *dkw = (void *) addr;
   2096 
   2097 		if ((flag & FWRITE) == 0)
   2098 			return (EBADF);
   2099 
   2100 		/* If the ioctl happens here, the parent is us. */
   2101 		strcpy(dkw->dkw_parent, device_xname(ace->sc_dev));
   2102 		return (dkwedge_add(dkw));
   2103 	    }
   2104 
   2105 	case DIOCDWEDGE:
   2106 	    {
   2107 	    	struct dkwedge_info *dkw = (void *) addr;
   2108 
   2109 		if ((flag & FWRITE) == 0)
   2110 			return (EBADF);
   2111 
   2112 		/* If the ioctl happens here, the parent is us. */
   2113 		strcpy(dkw->dkw_parent, device_xname(ace->sc_dev));
   2114 		return (dkwedge_del(dkw));
   2115 	    }
   2116 
   2117 	case DIOCLWEDGES:
   2118 	    {
   2119 	    	struct dkwedge_list *dkwl = (void *) addr;
   2120 
   2121 		return (dkwedge_list(&ace->sc_dk, dkwl, l));
   2122 	    }
   2123 
   2124 	case DIOCGSTRATEGY:
   2125 	    {
   2126 		struct disk_strategy *dks = (void *)addr;
   2127 
   2128 		s = splbio();
   2129 		strlcpy(dks->dks_name, bufq_getstrategyname(ace->sc_q),
   2130 		    sizeof(dks->dks_name));
   2131 		splx(s);
   2132 		dks->dks_paramlen = 0;
   2133 
   2134 		return 0;
   2135 	    }
   2136 
   2137 	case DIOCSSTRATEGY:
   2138 	    {
   2139 		struct disk_strategy *dks = (void *)addr;
   2140 		struct bufq_state *new;
   2141 		struct bufq_state *old;
   2142 
   2143 		if ((flag & FWRITE) == 0) {
   2144 			return EBADF;
   2145 		}
   2146 		if (dks->dks_param != NULL) {
   2147 			return EINVAL;
   2148 		}
   2149 		dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
   2150 		error = bufq_alloc(&new, dks->dks_name,
   2151 		    BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
   2152 		if (error) {
   2153 			return error;
   2154 		}
   2155 		s = splbio();
   2156 		old = ace->sc_q;
   2157 		bufq_move(new, old);
   2158 		ace->sc_q = new;
   2159 		splx(s);
   2160 		bufq_free(old);
   2161 
   2162 		return 0;
   2163 	    }
   2164 
   2165 #ifdef USE_ACE_FOR_RECONFIG
   2166         /* Ok, how do I get this standardized [nothing to do with disks either] */
   2167 #define DIOC_FPGA_RECONFIGURE _IOW('d',166, struct ioctl_pt)
   2168 	case DIOC_FPGA_RECONFIGURE:
   2169 	    {
   2170             /* BUGBUG This is totally wrong, we need to fault in all data in advance.
   2171              * Otherwise we get back here with the sysace in a bad state (its NOT reentrant!)
   2172              */
   2173             struct ioctl_pt *pt = (struct ioctl_pt *)addr;
   2174             return sysace_send_config(ace,(uint32_t*)pt->data,pt->com);
   2175 	    }
   2176 #endif /* USE_ACE_FOR_RECONFIG */
   2177 
   2178 	default:
   2179         /* NB: we get a DIOCGWEDGEINFO, but nobody else handles it either */
   2180         DEBUG_PRINT(("aceioctl: unsup x%lx\n", xfer), DEBUG_FUNCS);
   2181 		return ENOTTY;
   2182 	}
   2183 }
   2184 
   2185 int
   2186 acesize(dev_t dev)
   2187 {
   2188 	struct ace_softc *ace;
   2189 	int part, omask;
   2190 	int size;
   2191 
   2192 	DEBUG_PRINT(("acesize\n"), DEBUG_FUNCS);
   2193 
   2194 	ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
   2195 	if (ace == NULL)
   2196 		return (-1);
   2197 
   2198 	part = ACEPART(dev);
   2199 	omask = ace->sc_dk.dk_openmask & (1 << part);
   2200 
   2201 	if (omask == 0 && aceopen(dev, 0, S_IFBLK, NULL) != 0)
   2202 		return (-1);
   2203 	if (ace->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
   2204 		size = -1;
   2205 	else
   2206 		size = ace->sc_dk.dk_label->d_partitions[part].p_size *
   2207 		    (ace->sc_dk.dk_label->d_secsize / DEV_BSIZE);
   2208 	if (omask == 0 && aceclose(dev, 0, S_IFBLK, NULL) != 0)
   2209 		return (-1);
   2210 	return (size);
   2211 }
   2212 
   2213 /* #define ACE_DUMP_NOT_TRUSTED if you just want to watch */
   2214 #define ACE_DUMP_NOT_TRUSTED
   2215 static int acedoingadump = 0;
   2216 
   2217 /*
   2218  * Dump core after a system crash.
   2219  */
   2220 int
   2221 acedump(dev_t dev, daddr_t blkno, void *va, size_t size)
   2222 {
   2223 	struct ace_softc *ace;	/* disk unit to do the I/O */
   2224 	struct disklabel *lp;   /* disk's disklabel */
   2225 	int part, err;
   2226 	int nblks;	/* total number of sectors left to write */
   2227 
   2228 	/* Check if recursive dump; if so, punt. */
   2229 	if (acedoingadump)
   2230 		return EFAULT;
   2231 	acedoingadump = 1;
   2232 
   2233 	ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
   2234 	if (ace == NULL)
   2235 		return (ENXIO);
   2236 
   2237 	part = ACEPART(dev);
   2238 
   2239 	/* Convert to disk sectors.  Request must be a multiple of size. */
   2240 	lp = ace->sc_dk.dk_label;
   2241 	if ((size % lp->d_secsize) != 0)
   2242 		return EFAULT;
   2243 	nblks = size / lp->d_secsize;
   2244 	blkno = blkno / (lp->d_secsize / DEV_BSIZE);
   2245 
   2246 	/* Check transfer bounds against partition size. */
   2247 	if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
   2248 		return EINVAL;
   2249 
   2250 	/* Offset block number to start of partition. */
   2251 	blkno += lp->d_partitions[part].p_offset;
   2252 
   2253 	ace->sc_bp = NULL;
   2254 	ace->sc_bio.blkno = blkno;
   2255 	ace->sc_bio.flags = ATA_POLL;
   2256 	ace->sc_bio.nbytes = nblks * lp->d_secsize;
   2257 	ace->sc_bio.databuf = va;
   2258 #ifndef ACE_DUMP_NOT_TRUSTED
   2259     ace->active_xfer = bp;
   2260     wakeup(&ace->ch_thread);
   2261 
   2262 	switch(ace->sc_bio.error) {
   2263 	case ETIMEDOUT:
   2264 		printf("acedump: device timed out");
   2265 		err = EIO;
   2266 		break;
   2267 	case 0:
   2268 		err = 0;
   2269 		break;
   2270 	default:
   2271 		panic("acedump: unknown error type");
   2272 	}
   2273 	if (err != 0) {
   2274 		printf("\n");
   2275 		return err;
   2276 	}
   2277 #else	/* ACE_DUMP_NOT_TRUSTED */
   2278 	/* Let's just talk about this first... */
   2279 	device_printf(ace->sc_dev, ": dump addr 0x%p, size %zu blkno %llx\n",
   2280 	    va, size, blkno);
   2281 	DELAY(500 * 1000);	/* half a second */
   2282     err = 0;
   2283 #endif
   2284 
   2285 	acedoingadump = 0;
   2286 	return 0;
   2287 }
   2288 
   2289 #ifdef HAS_BAD144_HANDLING
   2290 /*
   2291  * Internalize the bad sector table.
   2292  */
   2293 void
   2294 bad144intern(struct ace_softc *ace)
   2295 {
   2296 	struct dkbad *bt = &ace->sc_dk.dk_cpulabel->bad;
   2297 	struct disklabel *lp = ace->sc_dk.dk_label;
   2298 	int i = 0;
   2299 
   2300 	DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);
   2301 
   2302 	for (; i < NBT_BAD; i++) {
   2303 		if (bt->bt_bad[i].bt_cyl == 0xffff)
   2304 			break;
   2305 		ace->sc_bio.badsect[i] =
   2306 		    bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
   2307 		    (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
   2308 		    (bt->bt_bad[i].bt_trksec & 0xff);
   2309 	}
   2310 	for (; i < NBT_BAD+1; i++)
   2311 		ace->sc_bio.badsect[i] = -1;
   2312 }
   2313 #endif
   2314 
   2315 static void
   2316 ace_params_to_properties(struct ace_softc *ace)
   2317 {
   2318 	prop_dictionary_t disk_info, odisk_info, geom;
   2319 	const char *cp;
   2320 
   2321 	disk_info = prop_dictionary_create();
   2322 
   2323     cp = ST506;
   2324 
   2325 	prop_dictionary_set_cstring_nocopy(disk_info, "type", cp);
   2326 
   2327 	geom = prop_dictionary_create();
   2328 
   2329 	prop_dictionary_set_uint64(geom, "sectors-per-unit", ace->sc_capacity);
   2330 
   2331 	prop_dictionary_set_uint32(geom, "sector-size",
   2332 				   DEV_BSIZE /* XXX 512? */);
   2333 
   2334 	prop_dictionary_set_uint16(geom, "sectors-per-track",
   2335 				   ace->sc_params.CurrentSectorsPerTrack);
   2336 
   2337 	prop_dictionary_set_uint16(geom, "tracks-per-cylinder",
   2338 				   ace->sc_params.CurrentNumberOfHeads);
   2339 
   2340     prop_dictionary_set_uint64(geom, "cylinders-per-unit",
   2341                                ace->sc_capacity /
   2342                                (ace->sc_params.CurrentNumberOfHeads *
   2343                                 ace->sc_params.CurrentSectorsPerTrack));
   2344 
   2345 	prop_dictionary_set(disk_info, "geometry", geom);
   2346 	prop_object_release(geom);
   2347 
   2348 	prop_dictionary_set(device_properties(ace->sc_dev),
   2349 			    "disk-info", disk_info);
   2350 
   2351 	/*
   2352 	 * Don't release disk_info here; we keep a reference to it.
   2353 	 * disk_detach() will release it when we go away.
   2354 	 */
   2355 
   2356 	odisk_info = ace->sc_dk.dk_info;
   2357 	ace->sc_dk.dk_info = disk_info;
   2358 	if (odisk_info)
   2359 		prop_object_release(odisk_info);
   2360 }
   2361 
   2362