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