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