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