1/* $NetBSD: ace_ebus.c,v 1.3 2011/11/19 22:51:19 tls 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.3 2011/11/19 22:51:19 tls Exp $"); 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/kernel.h> 39#include <sys/conf.h> 40#include <sys/file.h> 41#include <sys/stat.h> 42#include <sys/ioctl.h> 43#include <sys/buf.h> 44#include <sys/bufq.h> 45#include <sys/uio.h> 46#include <sys/malloc.h> 47#include <sys/device.h> 48#include <sys/disklabel.h> 49#include <sys/disk.h> 50#include <sys/syslog.h> 51#include <sys/proc.h> 52#include <sys/vnode.h> 53#include <sys/kthread.h> 54#include <sys/lock.h> 55#include <sys/queue.h> 56 57#include <sys/rnd.h> 58 59#include <machine/intr.h> 60#include <machine/bus.h> 61 62#include "locators.h" 63#include <prop/proplib.h> 64 65#include <emips/ebus/ebusvar.h> 66#include <emips/emips/machdep.h> 67#include <machine/emipsreg.h> 68 69/* Structure returned by the Identify command (see CFlash specs) 70 * NB: We only care for the first sector so that is what we define here. 71 * NB: Beware of mis-alignment for all 32bit things 72 */ 73typedef struct _CFLASH_IDENTIFY { 74 uint16_t Signature; /* Word 0 */ 75#define CFLASH_SIGNATURE 0x848a 76 uint16_t DefaultNumberOfCylinders; /* Word 1 */ 77 uint16_t Reserved1; /* Word 2 */ 78 uint16_t DefaultNumberOfHeads; /* Word 3 */ 79 uint16_t Obsolete1[2]; /* Word 4 */ 80 uint16_t DefaultSectorsPerTrack; /* Word 6 */ 81 uint16_t SectorsPerCard[2]; /* Word 7 */ 82 uint16_t Obsolete2; /* Word 9 */ 83 uint8_t SerialNumber[20]; /* padded, right-justified Word 10 */ 84 uint16_t Obsolete3[2]; /* Word 20 */ 85 uint16_t EccBytesInRWLong; /* Word 22 */ 86 uint8_t FirmwareRevision[8]; /* Word 23 */ 87 uint8_t ModelNumber[40]; /* Word 27 */ 88 uint16_t SectorsInRWMultiple; /* Word 47 */ 89 uint16_t Reserved2; /* Word 48 */ 90 uint16_t Capabilities; /* Word 49 */ 91 uint16_t Reserved3; /* Word 50 */ 92 uint16_t PioMode; /* Word 51 */ 93 uint16_t Obsolete4; /* Word 52 */ 94 uint16_t FieldValidity; /* Word 53 */ 95 uint16_t CurrentNumberOfCylinders; /* Word 54 */ 96 uint16_t CurrentNumberOfHeads; /* Word 55 */ 97 uint16_t CurrentSectorsPerTrack; /* Word 56 */ 98 uint16_t CurrentCapacity[2]; /* Word 57 */ 99 uint16_t MultiSectorSettings; /* Word 59 */ 100 uint16_t NumberOfAddressableSectors[2]; /* Word 60 */ 101 uint16_t Reserved4; /* Word 62 */ 102 uint16_t MultiWordDmaTransfer; /* Word 63 */ 103 uint16_t AdvancedPioModes; /* Word 64 */ 104 uint16_t MinimumMultiWordDmaTiming; /* Word 65 */ 105 uint16_t RecommendedMultiWordDmaTiming; /* Word 66 */ 106 uint16_t PioTimingNoFlowControl; /* Word 67 */ 107 uint16_t PioTimingWithFlowControl; /* Word 68 */ 108 uint16_t Reserved5[13]; /* Word 69 */ 109 uint16_t FeaturesSupported[3]; /* Word 82 */ 110 uint16_t FeaturesEnabled[3]; /* Word 85 */ 111 uint16_t UdmaMode; /* Word 88 */ 112 uint16_t SecurityEraseTime; /* Word 89 */ 113 uint16_t EnhancedSecurityEraseTime; /* Word 90 */ 114 uint16_t CurrentPowerManagementValue; /* Word 91 */ 115 uint8_t Reserved6[72]; /* Word 92-127 */ 116 uint8_t SecondHalf[256]; /* Word 128-255 */ 117} CFLASH_IDENTIFY, *PCFLASH_IDENTIFY; 118 119#define SIZEOF_IDENTIFY CF_SECTOR_SIZE /* must be a sector multiple */ 120 121/* Instead of dragging in atavar.h.. */ 122/* 123 * Parameters/state needed by the controller to perform an ATA bio. 124 */ 125struct ace_bio { 126 volatile int flags;/* cmd flags */ 127#define ATA_POLL 0x0002 /* poll for completion */ 128#define ATA_SINGLE 0x0008 /* transfer must be done in singlesector mode */ 129#define ATA_READ 0x0020 /* transfer is a read (otherwise a write) */ 130#define ATA_CORR 0x0040 /* transfer had a corrected error */ 131 daddr_t blkno; /* block addr */ 132 daddr_t blkdone;/* number of blks transferred */ 133 size_t nblks; /* number of blocks currently transferring */ 134 size_t nbytes; /* number of bytes currently transferring */ 135 char *databuf;/* data buffer address */ 136 volatile int error; 137#define NOERROR 0 /* There was no error (r_error invalid), 138 else see acedone()*/ 139#define FAILED(er) (er != 0) 140#define EDOOFUS EIO 141 142 uint32_t r_error;/* copy of status register */ 143#ifdef HAS_BAD144_HANDLING 144 daddr_t badsect[127];/* 126 plus trailing -1 marker */ 145#endif 146}; 147/* End of atavar.h*/ 148 149struct ace_softc { 150 /* General disk infos */ 151 device_t sc_dev; 152 153 struct disk sc_dk; 154 struct bufq_state *sc_q; 155 struct callout sc_restart_ch; 156 157 /* IDE disk soft states */ 158 struct buf *sc_bp; /* buf being transfered */ 159 struct buf *active_xfer; /* buf handoff to thread */ 160 /* current transfer data */ 161 struct ace_bio sc_bio; /* current transfer */ 162 163 struct proc *ch_thread; 164 int ch_flags; 165#define ATACH_SHUTDOWN 0x02 /* thread is shutting down */ 166#define ATACH_IRQ_WAIT 0x10 /* thread is waiting for irq */ 167#define ATACH_DISABLED 0x80 /* channel is disabled */ 168#define ATACH_TH_RUN 0x100 /* the kernel thread is working */ 169#define ATACH_TH_RESET 0x200 /* someone ask the thread to reset */ 170 171 int openings; 172 int media_has_changed; 173#define ACECE_MC 0x20 /* media changed */ 174#define ACECE_MCR 0x08 /* media change requested */ 175 struct _CFLASH_IDENTIFY sc_params;/* drive characteristics found */ 176 177 int sc_flags; 178#define ACEF_WLABEL 0x004 /* label is writable */ 179#define ACEF_LABELLING 0x008 /* writing label */ 180#define ACEF_LOADED 0x010 /* parameters loaded */ 181#define ACEF_WAIT 0x020 /* waiting for resources */ 182#define ACEF_KLABEL 0x080 /* retain label after 'full' close */ 183 184 uint64_t sc_capacity; 185 uint32_t sc_multi; /* max sectors per xfer */ 186 187 struct _Sac *sc_dr; /* reg pointers */ 188 int hw_busy; 189 int retries; /* number of xfer retry */ 190 191 krndsource_t rnd_source; 192}; 193 194int ace_ebus_match(device_t, cfdata_t, void *); 195void ace_ebus_attach(device_t, device_t, void *); 196void aceattach(struct ace_softc *); 197int acedetach(device_t, int); 198int aceactivate(device_t, enum devact); 199 200void acedone(struct ace_softc *); 201static void ace_params_to_properties(struct ace_softc *ace); 202 203CFATTACH_DECL_NEW(ace_ebus, sizeof(struct ace_softc), 204 ace_ebus_match, ace_ebus_attach, acedetach, aceactivate); 205 206int ace_ebus_intr(void *cookie, void *f); 207 208static void sysace_thread(void *arg); 209 210int 211ace_ebus_match(device_t parent, cfdata_t cf, void *aux) 212{ 213 struct ebus_attach_args *d = aux; 214 struct _Sac *sac = (struct _Sac *)d->ia_vaddr; 215 216 if (strcmp("ace", d->ia_name) != 0) 217 return 0; 218 if ((sac == NULL) || 219 ((sac->Tag & SAC_TAG) != PMTTAG_SYSTEM_ACE)) 220 return 0; 221 return 1; 222} 223 224void 225ace_ebus_attach(device_t parent, device_t self, void *aux) 226{ 227 struct ace_softc *ace = device_private(self); 228 struct ebus_attach_args *ia = aux; 229 int error; 230 231 /* 232 * It's on the baseboard, with a dedicated interrupt line. 233 */ 234 ace->sc_dr = (struct _Sac *)ia->ia_vaddr; 235 ace->sc_dev = self; 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(); 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 259static int sysace_attach(struct ace_softc *sc); 260static int sysace_reset(struct ace_softc *sc); 261static int sysace_identify(struct ace_softc *sc); 262static int sysace_lock_registers(struct ace_softc *sc); 263static int sysace_unlock_registers(struct ace_softc *sc); 264static int sysace_start(struct ace_softc *sc, uint32_t Command, uint32_t Lba, 265 uint32_t nSectors); 266static int sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize); 267static int sysace_read_at (struct ace_softc *sc, daddr_t start_sector, 268 char *buffer, size_t nblocks, size_t * pSizeRead); 269static 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 */ 272static 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 285int 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 294static int 295sysace_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; 327Out: 328 return error; 329} 330 331static void 332sysace_wedges(void *arg); 333extern int dkwedge_autodiscover; 334 335/* 336 * Aux temp thread to avoid deadlock when doing 337 * the partitio.. ahem wedges thing. 338 */ 339static void 340sysace_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(); 351 352 DBGME(DEBUG_STATUS, printf("Sysace::thread done for %p\n", sc)); 353 kthread_exit(0); 354} 355 356static void 357sysace_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 443typedef char *NAME; 444typedef struct _REGDESC { 445 NAME RegisterName; 446 NAME BitNames[32]; 447} REGDESC, *PREGDESC; 448 449static void 450SysacePrintRegister(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 463static uint32_t 464SysaceDumpRegisters(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 */ 615static int 616sysace_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 */ 672static int 673sysace_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 */ 715static int 716sysace_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 */ 789static int 790sysace_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 */ 847static int 848sysace_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_params_to_properties(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 */ 1011static int 1012sysace_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 */ 1054uint32_t ace_maxatatime = 255; 1055#define MAXATATIME ace_maxatatime //255 /* BUGBUG test me on real hardware!! */ 1056 1057static int 1058sysace_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 */ 1190static int 1191sysace_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-existant 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 1336int 1337ace_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 1359static int 1360sysace_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/* $NetBSD: ace_ebus.c,v 1.3 2011/11/19 22:51:19 tls Exp $ */ 1465 1466/* 1467 * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. 1468 * 1469 * Redistribution and use in source and binary forms, with or without 1470 * modification, are permitted provided that the following conditions 1471 * are met: 1472 * 1. Redistributions of source code must retain the above copyright 1473 * notice, this list of conditions and the following disclaimer. 1474 * 2. Redistributions in binary form must reproduce the above copyright 1475 * notice, this list of conditions and the following disclaimer in the 1476 * documentation and/or other materials provided with the distribution. 1477 * 3. All advertising materials mentioning features or use of this software 1478 * must display the following acknowledgement: 1479 * This product includes software developed by Manuel Bouyer. 1480 * 4. The name of the author may not be used to endorse or promote products 1481 * derived from this software without specific prior written permission. 1482 * 1483 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1484 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1485 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1486 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1487 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1488 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1489 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1490 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1491 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1492 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1493 */ 1494 1495/*- 1496 * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. 1497 * All rights reserved. 1498 * 1499 * This code is derived from software contributed to The NetBSD Foundation 1500 * by Charles M. Hannum and by Onno van der Linden. 1501 * 1502 * Redistribution and use in source and binary forms, with or without 1503 * modification, are permitted provided that the following conditions 1504 * are met: 1505 * 1. Redistributions of source code must retain the above copyright 1506 * notice, this list of conditions and the following disclaimer. 1507 * 2. Redistributions in binary form must reproduce the above copyright 1508 * notice, this list of conditions and the following disclaimer in the 1509 * documentation and/or other materials provided with the distribution. 1510 * 3. All advertising materials mentioning features or use of this software 1511 * must display the following acknowledgement: 1512 * This product includes software developed by the NetBSD 1513 * Foundation, Inc. and its contributors. 1514 * 4. Neither the name of The NetBSD Foundation nor the names of its 1515 * contributors may be used to endorse or promote products derived 1516 * from this software without specific prior written permission. 1517 * 1518 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1519 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1520 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1521 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 1522 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1523 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1524 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1525 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1526 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1527 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1528 * POSSIBILITY OF SUCH DAMAGE. 1529 */ 1530 1531static const char ST506[] = "ST506"; 1532 1533#define ACEIORETRIES_SINGLE 4 /* number of retries before single-sector */ 1534#define ACEIORETRIES 5 /* number of retries before giving up */ 1535#define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */ 1536 1537#define ACEUNIT(dev) DISKUNIT(dev) 1538#define ACEPART(dev) DISKPART(dev) 1539#define ACEMINOR(unit, part) DISKMINOR(unit, part) 1540#define MAKEACEDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) 1541 1542#define ACELABELDEV(dev) (MAKEACEDEV(major(dev), ACEUNIT(dev), RAW_PART)) 1543 1544void aceperror(const struct ace_softc *); 1545 1546extern struct cfdriver ace_cd; 1547 1548dev_type_open(aceopen); 1549dev_type_close(aceclose); 1550dev_type_read(aceread); 1551dev_type_write(acewrite); 1552dev_type_ioctl(aceioctl); 1553dev_type_strategy(acestrategy); 1554dev_type_dump(acedump); 1555dev_type_size(acesize); 1556 1557const struct bdevsw ace_bdevsw = { 1558 aceopen, aceclose, acestrategy, aceioctl, acedump, acesize, D_DISK 1559}; 1560 1561const struct cdevsw ace_cdevsw = { 1562 aceopen, aceclose, aceread, acewrite, aceioctl, 1563 nostop, notty, nopoll, nommap, nokqfilter, D_DISK 1564}; 1565 1566void acegetdefaultlabel(struct ace_softc *, struct disklabel *); 1567void acegetdisklabel(struct ace_softc *); 1568void acestart(void *); 1569void __acestart(struct ace_softc*, struct buf *); 1570void acerestart(void *); 1571 1572struct dkdriver acedkdriver = { acestrategy, minphys }; 1573 1574#ifdef HAS_BAD144_HANDLING 1575static void bad144intern(struct ace_softc *); 1576#endif 1577 1578void 1579aceattach(struct ace_softc *ace) 1580{ 1581 struct device *self = ace->sc_dev; 1582 char tbuf[41], pbuf[9], c, *p, *q; 1583 int i, blank; 1584 DEBUG_PRINT(("aceattach\n"), DEBUG_FUNCS | DEBUG_PROBE); 1585 1586 callout_init(&ace->sc_restart_ch, 0); 1587 bufq_alloc(&ace->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK); 1588 1589 ace->openings = 1; /* wazziz?*/ 1590 ace->sc_multi = MAXATATIME; 1591 1592 aprint_naive("\n"); 1593 1594 /* setup all required fields so that if the attach fails we are ok */ 1595 ace->sc_dk.dk_driver = &acedkdriver; 1596 ace->sc_dk.dk_name = device_xname(ace->sc_dev); 1597 1598 /* read our drive info */ 1599 if (sysace_attach(ace) != 0) { 1600 aprint_error_dev(ace->sc_dev, "attach failed\n"); 1601 return; 1602 } 1603 1604 aprint_normal_dev(ace->sc_dev, "drive supports %d-sector PIO xfers\n", 1605 ace->sc_multi); 1606 1607 for (blank = 0, p = ace->sc_params.ModelNumber, q = tbuf, i = 0; 1608 i < sizeof(ace->sc_params.ModelNumber); i++) { 1609 c = *p++; 1610 if (c == '\0') 1611 break; 1612 if (c != ' ') { 1613 if (blank) { 1614 *q++ = ' '; 1615 blank = 0; 1616 } 1617 *q++ = c; 1618 } else 1619 blank = 1; 1620 } 1621 *q++ = '\0'; 1622 1623 aprint_normal_dev(ace->sc_dev, "card is <%s>\n", tbuf); 1624 1625 format_bytes(pbuf, sizeof(pbuf), ace->sc_capacity * DEV_BSIZE); 1626 aprint_normal("%s: %s, %d cyl, %d head, %d sec, " 1627 "%d bytes/sect x %llu sectors\n", 1628 self->dv_xname, pbuf, 1629 (int)(ace->sc_capacity / 1630 (ace->sc_params.CurrentNumberOfHeads * 1631 ace->sc_params.CurrentSectorsPerTrack)), 1632 ace->sc_params.CurrentNumberOfHeads, 1633 ace->sc_params.CurrentSectorsPerTrack, 1634 DEV_BSIZE, (unsigned long long)ace->sc_capacity); 1635 1636 /* 1637 * Attach the disk structure. We fill in dk_info later. 1638 */ 1639 disk_attach(&ace->sc_dk); 1640 1641 rnd_attach_source(&ace->rnd_source, device_xname(ace->sc_dev), 1642 RND_TYPE_DISK, 0); 1643 1644} 1645 1646int 1647aceactivate(struct device *self, enum devact act) 1648{ 1649 int rv = 0; 1650 1651 switch (act) { 1652 case DVACT_DEACTIVATE: 1653 /* 1654 * Nothing to do; we key off the device's DVF_ACTIVATE. 1655 */ 1656 break; 1657 default: 1658 rv = EOPNOTSUPP; 1659 } 1660 return rv; 1661} 1662 1663int 1664acedetach(struct device *self, int flags) 1665{ 1666 struct ace_softc *sc = device_private(self); 1667 int s, bmaj, cmaj, i, mn; 1668 1669 /* locate the major number */ 1670 bmaj = bdevsw_lookup_major(&ace_bdevsw); 1671 cmaj = cdevsw_lookup_major(&ace_cdevsw); 1672 1673 /* Nuke the vnodes for any open instances. */ 1674 for (i = 0; i < MAXPARTITIONS; i++) { 1675 mn = ACEMINOR(device_unit(self), i); 1676 vdevgone(bmaj, mn, mn, VBLK); 1677 vdevgone(cmaj, mn, mn, VCHR); 1678 } 1679 1680 /* Delete all of our wedges. */ 1681 dkwedge_delall(&sc->sc_dk); 1682 1683 s = splbio(); 1684 1685 /* Kill off any queued buffers. */ 1686 bufq_drain(sc->sc_q); 1687 1688 bufq_free(sc->sc_q); 1689#if 0 1690 sc->atabus->ata_killpending(sc->drvp); 1691#endif 1692 1693 splx(s); 1694 1695 /* Detach disk. */ 1696 disk_detach(&sc->sc_dk); 1697 1698 /* Unhook the entropy source. */ 1699 rnd_detach_source(&sc->rnd_source); 1700 1701#if 0 1702 sc->drvp->drive_flags = 0; /* no drive any more here */ 1703#endif 1704 1705 return 0; 1706} 1707 1708/* 1709 * Read/write routine for a buffer. Validates the arguments and schedules the 1710 * transfer. Does not wait for the transfer to complete. 1711 */ 1712void 1713acestrategy(struct buf *bp) 1714{ 1715 struct ace_softc *ace; 1716 struct disklabel *lp; 1717 daddr_t blkno; 1718 int s; 1719 1720 ace = device_lookup_private(&ace_cd, ACEUNIT(bp->b_dev)); 1721 1722 if (ace == NULL) { 1723 bp->b_error = ENXIO; 1724 biodone(bp); 1725 return; 1726 } 1727 lp = ace->sc_dk.dk_label; 1728 1729 DEBUG_PRINT(("acestrategy (%s) %lld\n", 1730 device_xname(ace->sc_dev), bp->b_blkno), DEBUG_XFERS); 1731 1732 /* Valid request? */ 1733 if (bp->b_blkno < 0 || 1734 (bp->b_bcount % lp->d_secsize) != 0 || 1735 (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) { 1736 bp->b_error = EINVAL; 1737 goto done; 1738 } 1739 1740 /* If device invalidated (e.g. media change, door open), error. */ 1741 if ((ace->sc_flags & ACEF_LOADED) == 0) { 1742 bp->b_error = EIO; 1743 goto done; 1744 } 1745 1746 /* If it's a null transfer, return immediately. */ 1747 if (bp->b_bcount == 0) 1748 goto done; 1749 1750 /* 1751 * Do bounds checking, adjust transfer. if error, process. 1752 * If end of partition, just return. 1753 */ 1754 if (ACEPART(bp->b_dev) == RAW_PART) { 1755 if (bounds_check_with_mediasize(bp, DEV_BSIZE, 1756 ace->sc_capacity) <= 0) 1757 goto done; 1758 } else { 1759 if (bounds_check_with_label(&ace->sc_dk, bp, 1760 (ace->sc_flags & (ACEF_WLABEL|ACEF_LABELLING)) != 0) <= 0) 1761 goto done; 1762 } 1763 1764 /* 1765 * Now convert the block number to absolute and put it in 1766 * terms of the device's logical block size. 1767 */ 1768 if (lp->d_secsize >= DEV_BSIZE) 1769 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); 1770 else 1771 blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize); 1772 1773 if (ACEPART(bp->b_dev) != RAW_PART) 1774 blkno += lp->d_partitions[ACEPART(bp->b_dev)].p_offset; 1775 1776 bp->b_rawblkno = blkno; 1777 1778 /* Queue transfer on drive, activate drive and controller if idle. */ 1779 s = splbio(); 1780 bufq_put(ace->sc_q, bp); 1781 acestart(ace); 1782 splx(s); 1783 return; 1784done: 1785 /* Toss transfer; we're done early. */ 1786 bp->b_resid = bp->b_bcount; 1787 biodone(bp); 1788} 1789 1790/* 1791 * Queue a drive for I/O. 1792 */ 1793void 1794acestart(void *arg) 1795{ 1796 struct ace_softc *ace = arg; 1797 struct buf *bp = NULL; 1798 1799 DEBUG_PRINT(("acestart %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS); 1800 while (ace->openings > 0) { 1801 1802 /* Is there a buf for us ? */ 1803 if ((bp = bufq_get(ace->sc_q)) == NULL) 1804 return; 1805 1806 /* 1807 * Make the command. First lock the device 1808 */ 1809 ace->openings--; 1810 1811 ace->retries = 0; 1812 __acestart(ace, bp); 1813 } 1814} 1815 1816void 1817__acestart(struct ace_softc *sc, struct buf *bp) 1818{ 1819 1820 sc->sc_bp = bp; 1821 /* 1822 * If we're retrying, retry in single-sector mode. This will give us 1823 * the sector number of the problem, and will eventually allow the 1824 * transfer to succeed. 1825 */ 1826 if (sc->retries >= ACEIORETRIES_SINGLE) 1827 sc->sc_bio.flags = ATA_SINGLE; 1828 else 1829 sc->sc_bio.flags = 0; 1830 if (bp->b_flags & B_READ) 1831 sc->sc_bio.flags |= ATA_READ; 1832 sc->sc_bio.blkno = bp->b_rawblkno; 1833 sc->sc_bio.blkdone = 0; 1834 sc->sc_bio.nbytes = bp->b_bcount; 1835 sc->sc_bio.nblks = bp->b_bcount >> CF_SECBITS; 1836 sc->sc_bio.databuf = bp->b_data; 1837 /* Instrumentation. */ 1838 disk_busy(&sc->sc_dk); 1839 sc->active_xfer = bp; 1840 wakeup(&sc->ch_thread); 1841} 1842 1843void 1844acedone(struct ace_softc *ace) 1845{ 1846 struct buf *bp = ace->sc_bp; 1847 const char *errmsg; 1848 int do_perror = 0; 1849 1850 DEBUG_PRINT(("acedone %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS); 1851 1852 if (bp == NULL) 1853 return; 1854 1855 bp->b_resid = ace->sc_bio.nbytes; 1856 switch (ace->sc_bio.error) { 1857 case ETIMEDOUT: 1858 errmsg = "device timeout"; 1859 do_perror = 1; 1860 goto retry; 1861 case EBUSY: 1862 case EDOOFUS: 1863 errmsg = "device stuck"; 1864retry: /* Just reset and retry. Can we do more ? */ 1865 sysace_reset(ace); 1866 diskerr(bp, "ace", errmsg, LOG_PRINTF, 1867 ace->sc_bio.blkdone, ace->sc_dk.dk_label); 1868 if (ace->retries < ACEIORETRIES) 1869 printf(", retrying"); 1870 printf("\n"); 1871 if (do_perror) 1872 aceperror(ace); 1873 if (ace->retries < ACEIORETRIES) { 1874 ace->retries++; 1875 callout_reset(&ace->sc_restart_ch, RECOVERYTIME, 1876 acerestart, ace); 1877 return; 1878 } 1879 1880 bp->b_error = EIO; 1881 break; 1882 case 0: 1883 if ((ace->sc_bio.flags & ATA_CORR) || ace->retries > 0) 1884 printf("%s: soft error (corrected)\n", 1885 device_xname(ace->sc_dev)); 1886 break; 1887 case ENODEV: 1888 case E2BIG: 1889 bp->b_error = EIO; 1890 break; 1891 } 1892 disk_unbusy(&ace->sc_dk, (bp->b_bcount - bp->b_resid), 1893 (bp->b_flags & B_READ)); 1894 rnd_add_uint32(&ace->rnd_source, bp->b_blkno); 1895 biodone(bp); 1896 ace->openings++; 1897 acestart(ace); 1898} 1899 1900void 1901acerestart(void *v) 1902{ 1903 struct ace_softc *ace = v; 1904 struct buf *bp = ace->sc_bp; 1905 int s; 1906 DEBUG_PRINT(("acerestart %s\n", 1907 device_xname(ace->sc_dev)), DEBUG_XFERS); 1908 1909 s = splbio(); 1910 __acestart(v, bp); 1911 splx(s); 1912} 1913 1914int 1915aceread(dev_t dev, struct uio *uio, int flags) 1916{ 1917 int r; 1918 1919 DEBUG_PRINT(("aceread\n"), DEBUG_XFERS); 1920 r = physio(acestrategy, NULL, dev, B_READ, minphys, uio); 1921 DEBUG_PRINT(("aceread -> x%x resid=%x\n",r,uio->uio_resid),DEBUG_XFERS); 1922 1923 return r; 1924} 1925 1926int 1927acewrite(dev_t dev, struct uio *uio, int flags) 1928{ 1929 1930 DEBUG_PRINT(("acewrite\n"), DEBUG_XFERS); 1931 return physio(acestrategy, NULL, dev, B_WRITE, minphys, uio); 1932} 1933 1934int 1935aceopen(dev_t dev, int flag, int fmt, struct lwp *l) 1936{ 1937 struct ace_softc *ace; 1938 int part, error; 1939 1940 DEBUG_PRINT(("aceopen\n"), DEBUG_FUNCS); 1941 ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); 1942 if (ace == NULL) 1943 return ENXIO; 1944 1945 if (! device_is_active(ace->sc_dev)) 1946 return ENODEV; 1947 1948 part = ACEPART(dev); 1949 1950 mutex_enter(&ace->sc_dk.dk_openlock); 1951 1952 /* 1953 * If there are wedges, and this is not RAW_PART, then we 1954 * need to fail. 1955 */ 1956 if (ace->sc_dk.dk_nwedges != 0 && part != RAW_PART) { 1957 error = EBUSY; 1958 goto bad; 1959 } 1960 1961 if (ace->sc_dk.dk_openmask != 0) { 1962 /* 1963 * If any partition is open, but the disk has been invalidated, 1964 * disallow further opens. 1965 */ 1966 if ((ace->sc_flags & ACEF_LOADED) == 0) { 1967 error = EIO; 1968 goto bad; 1969 } 1970 } else { 1971 if ((ace->sc_flags & ACEF_LOADED) == 0) { 1972 ace->sc_flags |= ACEF_LOADED; 1973 1974 /* Load the physical device parameters. */ 1975 if (ace->sc_capacity == 0) { 1976 error = sysace_identify(ace); 1977 if (error) 1978 goto bad; 1979 } 1980 1981 /* Load the partition info if not already loaded. */ 1982 acegetdisklabel(ace); 1983 } 1984 } 1985 1986 /* Check that the partition exists. */ 1987 if (part != RAW_PART && 1988 (part >= ace->sc_dk.dk_label->d_npartitions || 1989 ace->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { 1990 error = ENXIO; 1991 goto bad; 1992 } 1993 1994 /* Insure only one open at a time. */ 1995 switch (fmt) { 1996 case S_IFCHR: 1997 ace->sc_dk.dk_copenmask |= (1 << part); 1998 break; 1999 case S_IFBLK: 2000 ace->sc_dk.dk_bopenmask |= (1 << part); 2001 break; 2002 } 2003 ace->sc_dk.dk_openmask = 2004 ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask; 2005 2006 mutex_exit(&ace->sc_dk.dk_openlock); 2007 return 0; 2008 2009 bad: 2010 mutex_exit(&ace->sc_dk.dk_openlock); 2011 return error; 2012} 2013 2014int 2015aceclose(dev_t dev, int flag, int fmt, struct lwp *l) 2016{ 2017 struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); 2018 int part = ACEPART(dev); 2019 2020 DEBUG_PRINT(("aceclose\n"), DEBUG_FUNCS); 2021 if (ace == NULL) 2022 return ENXIO; 2023 2024 mutex_enter(&ace->sc_dk.dk_openlock); 2025 2026 switch (fmt) { 2027 case S_IFCHR: 2028 ace->sc_dk.dk_copenmask &= ~(1 << part); 2029 break; 2030 case S_IFBLK: 2031 ace->sc_dk.dk_bopenmask &= ~(1 << part); 2032 break; 2033 } 2034 ace->sc_dk.dk_openmask = 2035 ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask; 2036 2037 if (ace->sc_dk.dk_openmask == 0) { 2038 2039 if (!(ace->sc_flags & ACEF_KLABEL)) 2040 ace->sc_flags &= ~ACEF_LOADED; 2041 2042 } 2043 2044 mutex_exit(&ace->sc_dk.dk_openlock); 2045 return 0; 2046} 2047 2048void 2049acegetdefaultlabel(struct ace_softc *ace, struct disklabel *lp) 2050{ 2051 2052 DEBUG_PRINT(("acegetdefaultlabel\n"), DEBUG_FUNCS); 2053 memset(lp, 0, sizeof(struct disklabel)); 2054 2055 lp->d_secsize = DEV_BSIZE; 2056 lp->d_ntracks = ace->sc_params.CurrentNumberOfHeads; 2057 lp->d_nsectors = ace->sc_params.CurrentSectorsPerTrack; 2058 lp->d_ncylinders = ace->sc_capacity / 2059 (ace->sc_params.CurrentNumberOfHeads * 2060 ace->sc_params.CurrentSectorsPerTrack); 2061 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 2062 2063 lp->d_type = DTYPE_ST506; /* ?!? */ 2064 2065 strncpy(lp->d_typename, ace->sc_params.ModelNumber, 16); 2066 strncpy(lp->d_packname, "fictitious", 16); 2067 if (ace->sc_capacity > UINT32_MAX) 2068 lp->d_secperunit = UINT32_MAX; 2069 else 2070 lp->d_secperunit = ace->sc_capacity; 2071 lp->d_rpm = 3600; 2072 lp->d_interleave = 1; 2073 lp->d_flags = 0; 2074 2075 lp->d_partitions[RAW_PART].p_offset = 0; 2076 lp->d_partitions[RAW_PART].p_size = 2077 lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); 2078 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 2079 lp->d_npartitions = RAW_PART + 1; 2080 2081 lp->d_magic = DISKMAGIC; 2082 lp->d_magic2 = DISKMAGIC; 2083 lp->d_checksum = dkcksum(lp); 2084} 2085 2086/* 2087 * Fabricate a default disk label, and try to read the correct one. 2088 */ 2089void 2090acegetdisklabel(struct ace_softc *ace) 2091{ 2092 struct disklabel *lp = ace->sc_dk.dk_label; 2093 const char *errstring; 2094 2095 DEBUG_PRINT(("acegetdisklabel\n"), DEBUG_FUNCS); 2096 2097 memset(ace->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); 2098 2099 acegetdefaultlabel(ace, lp); 2100 2101#ifdef HAS_BAD144_HANDLING 2102 ace->sc_bio.badsect[0] = -1; 2103#endif 2104 2105 errstring = readdisklabel(MAKEACEDEV(0, device_unit(ace->sc_dev), 2106 RAW_PART), acestrategy, lp, 2107 ace->sc_dk.dk_cpulabel); 2108 if (errstring) { 2109 printf("%s: %s\n", device_xname(ace->sc_dev), errstring); 2110 return; 2111 } 2112 2113#if DEBUG 2114 if (ACE_DEBUG(DEBUG_WRITES)) { 2115 int i, n = ace->sc_dk.dk_label->d_npartitions; 2116 printf("%s: %d parts\n", device_xname(ace->sc_dev), n); 2117 for (i = 0; i < n; i++) { 2118 printf("\t[%d]: t=%x s=%d o=%d\n", i, 2119 ace->sc_dk.dk_label->d_partitions[i].p_fstype, 2120 ace->sc_dk.dk_label->d_partitions[i].p_size, 2121 ace->sc_dk.dk_label->d_partitions[i].p_offset); 2122 } 2123 } 2124#endif 2125 2126#ifdef HAS_BAD144_HANDLING 2127 if ((lp->d_flags & D_BADSECT) != 0) 2128 bad144intern(ace); 2129#endif 2130} 2131 2132void 2133aceperror(const struct ace_softc *ace) 2134{ 2135 const char *devname = device_xname(ace->sc_dev); 2136 uint32_t Status = ace->sc_bio.r_error; 2137 2138 printf("%s: (", devname); 2139 2140 if (Status == 0) 2141 printf("error not notified"); 2142 else 2143 printf("status=x%x", Status); 2144 2145 printf(")\n"); 2146} 2147 2148int 2149aceioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l) 2150{ 2151 struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); 2152 int error = 0, s; 2153 2154 DEBUG_PRINT(("aceioctl\n"), DEBUG_FUNCS); 2155 2156 if ((ace->sc_flags & ACEF_LOADED) == 0) 2157 return EIO; 2158 2159 error = disk_ioctl(&ace->sc_dk, xfer, addr, flag, l); 2160 if (error != EPASSTHROUGH) 2161 return error; 2162 2163 switch (xfer) { 2164#ifdef HAS_BAD144_HANDLING 2165 case DIOCSBAD: 2166 if ((flag & FWRITE) == 0) 2167 return EBADF; 2168 ace->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr; 2169 ace->sc_dk.dk_label->d_flags |= D_BADSECT; 2170 bad144intern(ace); 2171 return 0; 2172#endif 2173 case DIOCGDINFO: 2174 *(struct disklabel *)addr = *(ace->sc_dk.dk_label); 2175 return 0; 2176 2177 case DIOCGPART: 2178 ((struct partinfo *)addr)->disklab = ace->sc_dk.dk_label; 2179 ((struct partinfo *)addr)->part = 2180 &ace->sc_dk.dk_label->d_partitions[ACEPART(dev)]; 2181 return 0; 2182 2183 case DIOCWDINFO: 2184 case DIOCSDINFO: 2185 { 2186 struct disklabel *lp; 2187 2188 if ((flag & FWRITE) == 0) 2189 return EBADF; 2190 2191 lp = (struct disklabel *)addr; 2192 2193 mutex_enter(&ace->sc_dk.dk_openlock); 2194 ace->sc_flags |= ACEF_LABELLING; 2195 2196 error = setdisklabel(ace->sc_dk.dk_label, 2197 lp, /*ace->sc_dk.dk_openmask : */0, 2198 ace->sc_dk.dk_cpulabel); 2199 if (error == 0) { 2200 if (xfer == DIOCWDINFO) 2201 error = writedisklabel(ACELABELDEV(dev), 2202 acestrategy, ace->sc_dk.dk_label, 2203 ace->sc_dk.dk_cpulabel); 2204 } 2205 2206 ace->sc_flags &= ~ACEF_LABELLING; 2207 mutex_exit(&ace->sc_dk.dk_openlock); 2208 return error; 2209 } 2210 2211 case DIOCKLABEL: 2212 if (*(int *)addr) 2213 ace->sc_flags |= ACEF_KLABEL; 2214 else 2215 ace->sc_flags &= ~ACEF_KLABEL; 2216 return 0; 2217 2218 case DIOCWLABEL: 2219 if ((flag & FWRITE) == 0) 2220 return EBADF; 2221 if (*(int *)addr) 2222 ace->sc_flags |= ACEF_WLABEL; 2223 else 2224 ace->sc_flags &= ~ACEF_WLABEL; 2225 return 0; 2226 2227 case DIOCGDEFLABEL: 2228 acegetdefaultlabel(ace, (struct disklabel *)addr); 2229 return 0; 2230 2231 case DIOCCACHESYNC: 2232 return 0; 2233 2234 case DIOCAWEDGE: 2235 { 2236 struct dkwedge_info *dkw = (void *) addr; 2237 2238 if ((flag & FWRITE) == 0) 2239 return EBADF; 2240 2241 /* If the ioctl happens here, the parent is us. */ 2242 strcpy(dkw->dkw_parent, device_xname(ace->sc_dev)); 2243 return dkwedge_add(dkw); 2244 } 2245 2246 case DIOCDWEDGE: 2247 { 2248 struct dkwedge_info *dkw = (void *) addr; 2249 2250 if ((flag & FWRITE) == 0) 2251 return EBADF; 2252 2253 /* If the ioctl happens here, the parent is us. */ 2254 strcpy(dkw->dkw_parent, device_xname(ace->sc_dev)); 2255 return dkwedge_del(dkw); 2256 } 2257 2258 case DIOCLWEDGES: 2259 { 2260 struct dkwedge_list *dkwl = (void *) addr; 2261 2262 return dkwedge_list(&ace->sc_dk, dkwl, l); 2263 } 2264 2265 case DIOCGSTRATEGY: 2266 { 2267 struct disk_strategy *dks = (void *)addr; 2268 2269 s = splbio(); 2270 strlcpy(dks->dks_name, bufq_getstrategyname(ace->sc_q), 2271 sizeof(dks->dks_name)); 2272 splx(s); 2273 dks->dks_paramlen = 0; 2274 2275 return 0; 2276 } 2277 2278 case DIOCSSTRATEGY: 2279 { 2280 struct disk_strategy *dks = (void *)addr; 2281 struct bufq_state *new; 2282 struct bufq_state *old; 2283 2284 if ((flag & FWRITE) == 0) { 2285 return EBADF; 2286 } 2287 if (dks->dks_param != NULL) { 2288 return EINVAL; 2289 } 2290 dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */ 2291 error = bufq_alloc(&new, dks->dks_name, 2292 BUFQ_EXACT|BUFQ_SORT_RAWBLOCK); 2293 if (error) { 2294 return error; 2295 } 2296 s = splbio(); 2297 old = ace->sc_q; 2298 bufq_move(new, old); 2299 ace->sc_q = new; 2300 splx(s); 2301 bufq_free(old); 2302 2303 return 0; 2304 } 2305 2306#ifdef USE_ACE_FOR_RECONFIG 2307 /* 2308 * Ok, how do I get this standardized 2309 * [nothing to do with disks either] 2310 */ 2311#define DIOC_FPGA_RECONFIGURE _IOW('d',166, struct ioctl_pt) 2312 case DIOC_FPGA_RECONFIGURE: 2313 { 2314 /* 2315 * BUGBUG This is totally wrong, we need to fault in 2316 * all data in advance. 2317 * Otherwise we get back here with the sysace in a bad state 2318 * (its NOT reentrant!) 2319 */ 2320 struct ioctl_pt *pt = (struct ioctl_pt *)addr; 2321 return sysace_send_config(ace,(uint32_t*)pt->data,pt->com); 2322 } 2323#endif /* USE_ACE_FOR_RECONFIG */ 2324 2325 default: 2326 /* 2327 * NB: we get a DIOCGWEDGEINFO, but nobody else handles it 2328 * either 2329 */ 2330 DEBUG_PRINT(("aceioctl: unsup x%lx\n", xfer), DEBUG_FUNCS); 2331 return ENOTTY; 2332 } 2333} 2334 2335int 2336acesize(dev_t dev) 2337{ 2338 struct ace_softc *ace; 2339 int part, omask; 2340 int size; 2341 2342 DEBUG_PRINT(("acesize\n"), DEBUG_FUNCS); 2343 2344 ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); 2345 if (ace == NULL) 2346 return -1; 2347 2348 part = ACEPART(dev); 2349 omask = ace->sc_dk.dk_openmask & (1 << part); 2350 2351 if (omask == 0 && aceopen(dev, 0, S_IFBLK, NULL) != 0) 2352 return -1; 2353 if (ace->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) 2354 size = -1; 2355 else 2356 size = ace->sc_dk.dk_label->d_partitions[part].p_size * 2357 (ace->sc_dk.dk_label->d_secsize / DEV_BSIZE); 2358 if (omask == 0 && aceclose(dev, 0, S_IFBLK, NULL) != 0) 2359 return -1; 2360 return size; 2361} 2362 2363/* #define ACE_DUMP_NOT_TRUSTED if you just want to watch */ 2364#define ACE_DUMP_NOT_TRUSTED 2365static int acedoingadump = 0; 2366 2367/* 2368 * Dump core after a system crash. 2369 */ 2370int 2371acedump(dev_t dev, daddr_t blkno, void *va, size_t size) 2372{ 2373 struct ace_softc *ace; /* disk unit to do the I/O */ 2374 struct disklabel *lp; /* disk's disklabel */ 2375 int part, err; 2376 int nblks; /* total number of sectors left to write */ 2377 2378 /* Check if recursive dump; if so, punt. */ 2379 if (acedoingadump) 2380 return EFAULT; 2381 acedoingadump = 1; 2382 2383 ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); 2384 if (ace == NULL) 2385 return ENXIO; 2386 2387 part = ACEPART(dev); 2388 2389 /* Convert to disk sectors. Request must be a multiple of size. */ 2390 lp = ace->sc_dk.dk_label; 2391 if ((size % lp->d_secsize) != 0) 2392 return EFAULT; 2393 nblks = size / lp->d_secsize; 2394 blkno = blkno / (lp->d_secsize / DEV_BSIZE); 2395 2396 /* Check transfer bounds against partition size. */ 2397 if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size)) 2398 return EINVAL; 2399 2400 /* Offset block number to start of partition. */ 2401 blkno += lp->d_partitions[part].p_offset; 2402 2403 ace->sc_bp = NULL; 2404 ace->sc_bio.blkno = blkno; 2405 ace->sc_bio.flags = ATA_POLL; 2406 ace->sc_bio.nbytes = nblks * lp->d_secsize; 2407 ace->sc_bio.databuf = va; 2408#ifndef ACE_DUMP_NOT_TRUSTED 2409 ace->active_xfer = bp; 2410 wakeup(&ace->ch_thread); 2411 2412 switch(ace->sc_bio.error) { 2413 case ETIMEDOUT: 2414 printf("acedump: device timed out"); 2415 err = EIO; 2416 break; 2417 case 0: 2418 err = 0; 2419 break; 2420 default: 2421 panic("acedump: unknown error type"); 2422 } 2423 if (err != 0) { 2424 printf("\n"); 2425 return err; 2426 } 2427#else /* ACE_DUMP_NOT_TRUSTED */ 2428 /* Let's just talk about this first... */ 2429 device_printf(ace->sc_dev, ": dump addr 0x%p, size %zu blkno %llx\n", 2430 va, size, blkno); 2431 DELAY(500 * 1000); /* half a second */ 2432 err = 0; 2433#endif 2434 2435 acedoingadump = 0; 2436 return 0; 2437} 2438 2439#ifdef HAS_BAD144_HANDLING 2440/* 2441 * Internalize the bad sector table. 2442 */ 2443void 2444bad144intern(struct ace_softc *ace) 2445{ 2446 struct dkbad *bt = &ace->sc_dk.dk_cpulabel->bad; 2447 struct disklabel *lp = ace->sc_dk.dk_label; 2448 int i = 0; 2449 2450 DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS); 2451 2452 for (; i < NBT_BAD; i++) { 2453 if (bt->bt_bad[i].bt_cyl == 0xffff) 2454 break; 2455 ace->sc_bio.badsect[i] = 2456 bt->bt_bad[i].bt_cyl * lp->d_secpercyl + 2457 (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors + 2458 (bt->bt_bad[i].bt_trksec & 0xff); 2459 } 2460 for (; i < NBT_BAD+1; i++) 2461 ace->sc_bio.badsect[i] = -1; 2462} 2463#endif 2464 2465static void 2466ace_params_to_properties(struct ace_softc *ace) 2467{ 2468 prop_dictionary_t disk_info, odisk_info, geom; 2469 const char *cp; 2470 2471 disk_info = prop_dictionary_create(); 2472 2473 cp = ST506; 2474 2475 prop_dictionary_set_cstring_nocopy(disk_info, "type", cp); 2476 2477 geom = prop_dictionary_create(); 2478 2479 prop_dictionary_set_uint64(geom, "sectors-per-unit", ace->sc_capacity); 2480 2481 prop_dictionary_set_uint32(geom, "sector-size", 2482 DEV_BSIZE /* XXX 512? */); 2483 2484 prop_dictionary_set_uint16(geom, "sectors-per-track", 2485 ace->sc_params.CurrentSectorsPerTrack); 2486 2487 prop_dictionary_set_uint16(geom, "tracks-per-cylinder", 2488 ace->sc_params.CurrentNumberOfHeads); 2489 2490 prop_dictionary_set_uint64(geom, "cylinders-per-unit", 2491 ace->sc_capacity / 2492 (ace->sc_params.CurrentNumberOfHeads * 2493 ace->sc_params.CurrentSectorsPerTrack)); 2494 2495 prop_dictionary_set(disk_info, "geometry", geom); 2496 prop_object_release(geom); 2497 2498 prop_dictionary_set(device_properties(ace->sc_dev), 2499 "disk-info", disk_info); 2500 2501 /* 2502 * Don't release disk_info here; we keep a reference to it. 2503 * disk_detach() will release it when we go away. 2504 */ 2505 2506 odisk_info = ace->sc_dk.dk_info; 2507 ace->sc_dk.dk_info = disk_info; 2508 if (odisk_info) 2509 prop_object_release(odisk_info); 2510} 2511