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