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