1 /* $NetBSD: ace.c,v 1.4 2018/03/07 14:59:14 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * Copyright (c) 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code was written by Alessandro Forin and Neil Pittman 9 * at Microsoft Research and contributed to The NetBSD Foundation 10 * by Microsoft Corporation. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* -------------------------------------------------------------------------- 35 * 36 * Module: 37 * 38 * ace.c 39 * 40 * Purpose: 41 * 42 * Driver for the Xilinx System ACE CompactFlash Solution 43 * 44 * Author: 45 * A. Forin (sandrof) 46 * 47 * References: 48 * "System ACE CompactFlash Solution", Advance Product Specification 49 * Document DS080 Version 1.5 April 5, 2002. Xilinx Corp. 50 * Available at http://www.xilinx.com 51 * 52 * "CF+ and CompactFlash Specification", Revision 4.1, 02/16/2007. 53 * CompactFlash Association. 54 * Available at http://www.compactflash.org 55 * -------------------------------------------------------------------------- 56 */ 57 58 #include <lib/libsa/stand.h> 59 #include <lib/libkern/libkern.h> 60 #include <machine/emipsreg.h> 61 62 #include <sys/param.h> 63 #include <sys/disklabel.h> 64 #include <sys/endian.h> 65 66 #include "common.h" 67 #include "ace.h" 68 #include "start.h" 69 70 #define NSAC 2 71 #define SAC0 ((struct _Sac *)IDE_DEFAULT_ADDRESS) 72 #define SAC1 ((struct _Sac *)(IDE_DEFAULT_ADDRESS+256)) 73 74 #define CF_SECBITS 9 75 #define CF_SECTOR_SIZE (1 << CF_SECBITS) 76 77 78 /* Error codes 79 */ 80 #define FAILED(x) (x < 0) 81 #define S_OK (0) 82 #define E_INVALID_PARAMETER (-1) 83 #define E_DISK_RESET_FAILED (-2) 84 #define E_NO_MEDIA_IN_DRIVE (-3) 85 #define E_TIMED_OUT (-4) 86 87 /* Utilities 88 */ 89 #if defined(DEBUG) 90 int acedebug = 2; 91 #define DBGME(lev,x) \ 92 do \ 93 if (lev >= acedebug) { \ 94 x; \ 95 } \ 96 while (/*CONSTCOND*/0) 97 #else 98 #define DBGME(lev,x) 99 #endif 100 101 #if defined(DEBUG) 102 typedef char *NAME; 103 typedef struct _REGDESC { 104 NAME RegisterName; 105 NAME BitNames[32]; 106 } REGDESC, *PREGDESC; 107 108 static void SysacePrintRegister(const REGDESC *Desc, uint32_t Value); 109 110 static void SysacePrintRegister(const REGDESC *Desc, uint32_t Value) 111 { 112 int i; 113 printf("\t%s %x =", Desc->RegisterName, Value); 114 for (i = 31; i >= 0; i--) { 115 if (Value & (1 << i)) 116 printf(" %s", 117 (Desc->BitNames[i]) ? Desc->BitNames[i] : "?"); 118 } 119 printf("\n"); 120 } 121 122 static void SysaceDumpRegisters(struct _Sac *Interface) 123 { 124 const REGDESC Control_Names = 125 { "Control", 126 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 127 "RST", // 0x00010000 128 "BUS8", // 0x00020000 129 "BUS16", // 0x00040000 130 "BUS32", // 0x00080000 131 "IRQ", // 0x00100000 132 "BRDY", // 0x00200000 133 "IMSK0", // 0x00400000 134 "IMSK1", // 0x00800000 135 "TD0", // 0x0f000000 136 "TD1", // 0x0f000000 137 "TD2", // 0x0f000000 138 "TD3", // 0x0f000000 139 "BUFW8", // 0x10000000 140 "BUFW16", // 0x20000000 141 "BUFW32", // 0x40000000 142 "DEBUG"} // 0x80000000 143 }; 144 145 const REGDESC STATUS_Names = 146 { "STATUS", 147 {"CFGLOCK", // 0x00000001 148 "MPULOCK", // 0x00000002 149 "CFGERROR", // 0x00000004 150 "CFCERROR", // 0x00000008 151 "CFDETECT", // 0x00000010 152 "DATABUFRDY", // 0x00000020 153 "DATABUFWRITE", //0x00000040 154 "CFGDONE", // 0x00000080 155 "RDYFORCFCMD", // 0x00000100 156 "CFGMODEPIN", // 0x00000200 157 0,0,0, 158 "CFGADDRPIN0", // 0x0000e000 159 "CFGADDRPIN1", // 0x0000e000 160 "CFGADDRPIN2", // 0x0000e000 161 0, 162 "CFBSY", // 0x00020000 163 "CFRDY", // 0x00040000 164 "CFDWF", // 0x00080000 165 "CFDSC", // 0x00100000 166 "CFDRQ", // 0x00200000 167 "CFCORR", // 0x00400000 168 "CFERR", // 0x00800000 169 0,} 170 }; 171 172 const REGDESC ERRORREG_Names = 173 { "ERRORREG", 174 {"CARDRESETERR", // 0x00000001 175 "CARDRDYERR", // 0x00000002 176 "CARDREADERR", // 0x00000004 177 "CARDWRITEERR", // 0x00000008 178 "SECTORRDYERR", // 0x00000010 179 "CFGADDRERR", // 0x00000020 180 "CFGFAILED", // 0x00000040 181 "CFGREADERR", // 0x00000080 182 "CFGINSTRERR", // 0x00000100 183 "CFGINITERR", // 0x00000200 184 0, 185 "CFBBK", // 0x00000800 186 "CFUNC", // 0x00001000 187 "CFIDNF", // 0x00002000 188 "CFABORT", // 0x00004000 189 "CFAMNF", // 0x00008000 190 0,} 191 }; 192 193 const NAME CommandNames[8] = 194 { "0", // 0x0000 195 "RESETMEMCARD", // 0x0100 196 "IDENTIFYMEMCARD", // 0x0200 197 "READMEMCARDDATA", // 0x0300 198 "WRITEMEMCARDDATA", // 0x0400 199 "5", // 0x0500 200 "ABORT", // 0x0600 201 "7" // 0x0700 202 }; 203 204 const REGDESC CONTROLREG_Names = 205 { "CONTROLREG", 206 {"FORCELOCKREQ", // 0x00000001 207 "LOCKREQ", // 0x00000002 208 "FORCECFGADDR", // 0x00000004 209 "FORCECFGMODE", // 0x00000008 210 "CFGMODE", // 0x00000010 211 "CFGSTART", // 0x00000020 212 "CFGSEL_MPU", // 0x00000040 213 "CFGRESET", // 0x00000080 214 "DATABUFRDYIRQ", // 0x00000100 215 "ERRORIRQ", // 0x00000200 216 "CFGDONEIRQ", // 0x00000400 217 "RESETIRQ", // 0x00000800 218 "CFGPROG", // 0x00001000 219 "CFGADDR_B0", // 0x00002000 220 "CFGADDR_B1", // 0x00004000 221 "CFGADDR_B2", // 0x00008000 222 0,} 223 }; 224 225 const REGDESC FATSTATREG_Names = 226 { "FATSTATREG", 227 {"MBRVALID", // 0x00000001 228 "PBRVALID", // 0x00000002 229 "MBRFAT12", // 0x00000004 230 "PBRFAT12", // 0x00000008 231 "MBRFAT16", // 0x00000010 232 "PBRFAT16", // 0x00000020 233 "CALCFAT12", // 0x00000040 234 "CALCFAT16", // 0x00000080 235 0, } 236 }; 237 238 printf("Sysace@%p:\n", Interface); 239 printf("\tTag %x\n", Interface->Tag); 240 SysacePrintRegister(&Control_Names, Interface->Control); 241 printf("\tBUSMODEREG %x\n", Interface->BUSMODEREG); 242 SysacePrintRegister(&STATUS_Names, Interface->STATUS); 243 SysacePrintRegister(&ERRORREG_Names, Interface->ERRORREG); 244 printf("\tCFGLBAREG %x\n", Interface->CFGLBAREG); 245 printf("\tMPULBAREG %x\n", Interface->MPULBAREG); 246 printf("\tVERSIONREG %x\n", Interface->VERSIONREG); 247 printf("\tSECCNTCMDREG %x = %s cnt=%d\n", Interface->SECCNTCMDREG, 248 CommandNames[(Interface->SECCNTCMDREG >> 8)&7], 249 Interface->SECCNTCMDREG & SAC_SECCCNT); 250 SysacePrintRegister(&CONTROLREG_Names, Interface->CONTROLREG); 251 SysacePrintRegister(&FATSTATREG_Names, Interface->FATSTATREG); 252 } 253 254 #else 255 #define SysaceDumpRegisters(_c_) 256 #endif 257 258 /* Reset the device and the interface 259 */ 260 static int SysaceInitialize(struct _Sac *Interface) 261 { 262 /* 16bit mode etc etc */ 263 uint32_t BusMode, Control; 264 265 /* reset our interface */ 266 Interface->Control = SAC_RST; 267 Delay(200); 268 269 /* repeat on both byte lanes */ 270 Interface->BUSMODEREG = SAC_MODE16 | (SAC_MODE16 << 8); 271 Delay(1); 272 273 /* check what our interface does and what the SysACE expects */ 274 Control = Interface->Control; 275 BusMode = Interface->BUSMODEREG; 276 277 /* get them to agree */ 278 if (BusMode & SAC_MODE16) 279 { 280 Interface->Control = Control | SAC_BUS16; 281 Interface->Control = Interface->Control & ~SAC_BUS8; 282 } 283 else 284 { 285 Interface->Control = Control | SAC_BUS8; 286 Interface->Control = Interface->Control & ~SAC_BUS16; 287 } 288 289 /* check that it worked */ 290 BusMode = Interface->BUSMODEREG; 291 Control = Interface->Control; 292 293 if (((BusMode & SAC_MODE16) == 0) && ((Control & SAC_BUS8) == 0)) return E_DISK_RESET_FAILED; 294 if (((BusMode & SAC_MODE16) > 0) && ((Control & SAC_BUS16) == 0)) return E_DISK_RESET_FAILED; 295 296 /* interrupts off for now */ 297 Interface->Control &= ~SAC_INTMASK; 298 #define SAC_INTERRUPTS (SAC_DATABUFRDYIRQ | SAC_ERRORIRQ )// | SAC_CFGDONEIRQ) 299 Control = Interface->CONTROLREG; 300 Control = (Control & ~SAC_INTERRUPTS) | SAC_RESETIRQ | SAC_FORCECFGMODE; 301 Interface->CONTROLREG = Control; 302 Interface->CONTROLREG = Control & ~SAC_RESETIRQ; 303 304 /* no command */ 305 Interface->MPULBAREG = 0; 306 307 return S_OK; 308 } 309 310 /* Take control of the ACE datapath 311 */ 312 static int SysaceLock(struct _Sac *Interface) 313 { 314 uint32_t Status; 315 int i; 316 317 /* Locked already? 318 */ 319 Status = Interface->STATUS; 320 if (Status & SAC_MPULOCK) 321 return TRUE; 322 323 /* Request lock 324 */ 325 Interface->CONTROLREG |= SAC_LOCKREQ; 326 327 /* Spin a bit until we get it 328 */ 329 for (i = 0; i < 200; i++) { 330 Status = Interface->STATUS; 331 if (Status & SAC_MPULOCK) 332 return TRUE; 333 Delay(100); 334 DBGME(0,printf("Sysace::Lock loops.. (st=%x)\n",Status)); 335 } 336 337 /* oopsie! 338 */ 339 DBGME(3,printf("Sysace::Lock timeout (st=%x)\n",Status)); 340 SysaceDumpRegisters(Interface); 341 return FALSE; 342 } 343 344 /* Release control of the ACE datapath 345 */ 346 static int SysaceUnlock(struct _Sac *Interface) 347 { 348 uint32_t Status; 349 int i; 350 351 /* Clear reset 352 */ 353 Interface->CONTROLREG &= ~SAC_CFGRESET; 354 355 /* Unlocked already? 356 */ 357 Status = Interface->STATUS; 358 if (0 == (Status & SAC_MPULOCK)) 359 return TRUE; 360 361 /* Request unlock 362 */ 363 Interface->CONTROLREG &= ~SAC_LOCKREQ; 364 365 /* Spin a bit until we get it 366 */ 367 for (i = 0; i < 200; i++) { 368 Status = Interface->STATUS; 369 if (0 == (Status & SAC_MPULOCK)) 370 return TRUE; 371 Delay(100); 372 DBGME(0,printf("Sysace::Unlock loops.. (st=%x)\n",Status)); 373 } 374 375 /* oopsie! 376 */ 377 DBGME(3,printf("Sysace::Unlock timeout (st=%x)\n",Status)); 378 SysaceDumpRegisters(Interface); 379 return FALSE; 380 } 381 382 /* Check if the ACE is waiting for a comamnd 383 */ 384 #define SysaceReadyForCommand(_i_) ((_i_)->STATUS & SAC_RDYFORCFCMD) 385 386 /* Check if the ACE is executing a comamnd 387 */ 388 #define SysaceBusyWithCommand(_i_) ((_i_)->STATUS & SAC_CFBSY) 389 390 /* Turn on interrupts from the ACE 391 */ 392 #define SysaceInton(_i_) { \ 393 (_i_)->CONTROLREG |= SAC_INTERRUPTS; \ 394 (_i_)->Control |= SAC_INTMASK; \ 395 } 396 397 /* Turn off interrupts from the ACE 398 */ 399 #define SysaceIntoff(_i_) { \ 400 (_i_)->CONTROLREG &= ~SAC_INTERRUPTS; \ 401 (_i_)->Control &= ~SAC_INTMASK; \ 402 } 403 404 /* Start a command on the ACE, such as read or identify. 405 */ 406 static int SysaceStartCommand(struct _Sac *Interface, 407 uint32_t Command, 408 uint32_t Lba, 409 uint32_t nSectors) 410 { 411 int sc = E_DISK_RESET_FAILED; 412 413 /* Lock it if not already 414 */ 415 if (!SysaceLock(Interface)) { 416 /* printed already */ 417 return sc; 418 } 419 420 /* Is there a CF inserted 421 */ 422 if (! (Interface->STATUS & SAC_CFDETECT)) { 423 /* NB: Not a failure state */ 424 DBGME(2,printf("Sysace:: no media (st=%x)\n",Interface->STATUS)); 425 return E_NO_MEDIA_IN_DRIVE; 426 } 427 428 /* Is it ready for a command 429 */ 430 if (!SysaceReadyForCommand(Interface)) { 431 DBGME(3,printf("Sysace:: not ready (st=%x)\n",Interface->STATUS)); 432 SysaceDumpRegisters(Interface); 433 return sc; 434 } 435 436 /* sector number and command 437 */ 438 Interface->MPULBAREG = Lba; 439 Interface->SECCNTCMDREG = (uint16_t)(Command | (nSectors & SAC_SECCCNT)); 440 441 /* re-route the chip 442 * NB: The word "RESET" is actually not much of a misnomer. 443 * The chip was designed for a one-shot execution only, at reset time, 444 * namely loading the configuration data into the FPGA. So.. 445 */ 446 Interface->CONTROLREG |= SAC_CFGRESET; 447 return S_OK; 448 } 449 450 451 /* "Interrupt service routine" 452 */ 453 static void SysAce_isr ( struct _Sac *Interface ) 454 { 455 uint32_t Control; 456 457 /* Turn off interrupts and ACK them 458 */ 459 SysaceIntoff(Interface); 460 461 Control = Interface->CONTROLREG & (~(SAC_RESETIRQ|SAC_INTERRUPTS)); 462 Interface->CONTROLREG = Control | SAC_RESETIRQ; 463 Interface->CONTROLREG = Control; 464 } 465 466 static int SysAce_wait(struct _Sac *Interface) 467 { 468 int i; 469 for (i = 0; i < 30000; i++) { 470 if (Interface->STATUS & SAC_DATABUFRDY) { 471 SysAce_isr(Interface); 472 return S_OK; 473 } 474 Delay(100); 475 } 476 return E_TIMED_OUT; 477 } 478 479 480 /* Read NBLOCKS blocks of 512 bytes each, 481 * starting at block number STARTSECTOR, 482 * into the buffer BUFFER. 483 * Return 0 if ok, -1 otherwise. 484 */ 485 static int SysAce_read(struct _Sac * Interface, char *Buffer, uint32_t StartSector, uint32_t nBlocks) 486 { 487 int sc = S_OK; 488 uint32_t Size, SizeThisTime; 489 uint32_t Status = 0, SizeRead = 0; 490 unsigned int i, j; 491 492 Size = nBlocks << CF_SECBITS; 493 494 DBGME(1,printf("Sysace Read(%p %x %x)\n", 495 Buffer, StartSector, nBlocks)); 496 497 /* Repeat until we are done or error 498 */ 499 while (sc == S_OK) { 500 501 /* .. one sector at a time 502 * BUGBUG Supposedly we can do up to 256 sectors? 503 */ 504 SizeThisTime = Size; 505 if (SizeThisTime > CF_SECTOR_SIZE) 506 SizeThisTime = CF_SECTOR_SIZE; 507 508 /* Start a new sector read 509 */ 510 SysaceInton(Interface); 511 sc = SysaceStartCommand(Interface, 512 SAC_CMD_READMEMCARDDATA, 513 StartSector, 514 1); 515 /* And wait until done, if ok 516 */ 517 if (!FAILED(sc)) { 518 sc = SysAce_wait(Interface); 519 } 520 521 /* Are we doing ok 522 */ 523 if (!FAILED(sc)) { 524 525 /* Get the data out of the ACE 526 */ 527 for (i = 0; i < SizeThisTime; i += 4) { 528 529 /* Make sure the FIFO is ready 530 */ 531 for (j = 0; j < 100; j++) { 532 Status = Interface->STATUS; 533 if (Status & SAC_DATABUFRDY) 534 break; 535 Delay(10); 536 } 537 538 /* Got it? 539 */ 540 if (Status & SAC_DATABUFRDY) { 541 uint32_t Data32; 542 543 Data32 = Interface->DATABUFREG[0]; 544 Data32 = le32toh(Data32); 545 DBGME(0,printf(" %x", Data32)); 546 if (0 == (0xf & (i+4))) DBGME(0,printf("\n")); 547 memcpy(Buffer+i, &Data32, 4); 548 } 549 else 550 { 551 /* Ooops, get out of here 552 */ 553 DBGME(3,printf("Sysace::READ timeout\n")); 554 SysaceDumpRegisters(Interface); 555 sc = E_TIMED_OUT; 556 break; 557 } 558 } 559 560 /* Still doing ok? 561 */ 562 if (!FAILED(sc)) { 563 StartSector += 1; 564 Buffer += SizeThisTime; 565 SizeRead += SizeThisTime; 566 Size -= SizeThisTime; 567 } 568 } 569 570 /* Free the ACE for the JTAG, just in case */ 571 SysaceUnlock(Interface); 572 573 /* Are we done yet? 574 */ 575 if (Size == 0) 576 break; 577 } 578 579 return sc; 580 } 581 582 /* Exported interface 583 */ 584 struct ace_softc { 585 struct _Sac *sc_dp; /* I/O regs */ 586 int sc_part; /* disk partition number */ 587 struct disklabel sc_label; /* disk label for this disk */ 588 }; 589 590 #define RF_PROTECTED_SECTORS 64 /* XXX refer to <.../rf_optnames.h> */ 591 592 int aceprobe(int unit) 593 { 594 struct _Sac *Sac; 595 596 if (unit == 0) 597 Sac = SAC0; 598 else if (unit == 1) 599 Sac = SAC1; 600 else 601 return E_INVALID_PARAMETER; 602 603 /* Check the tag to see if its there 604 */ 605 if ((Sac->Tag & SAC_TAG) != PMTTAG_SYSTEM_ACE) { 606 DBGME(3,printf("init_ace: bad tag (%x != %x) @x%p\n", 607 Sac->Tag, PMTTAG_SYSTEM_ACE, Sac)); 608 return E_INVALID_PARAMETER; 609 } 610 611 return S_OK; 612 } 613 614 /* aceopen("", ctlr, unit, part); 615 */ 616 int 617 aceopen(struct open_file *f, ...) 618 { 619 int ctlr, unit, part; 620 struct _Sac *Sac; 621 622 struct ace_softc *sc; 623 struct disklabel *lp; 624 int i; 625 char *msg; 626 char buf[DEV_BSIZE]; 627 size_t cnt; 628 va_list ap; 629 630 va_start(ap, f); 631 632 ctlr = va_arg(ap, int); 633 unit = va_arg(ap, int); 634 part = va_arg(ap, int); 635 va_end(ap); 636 637 if (ctlr != 0 || unit >= NSAC || part >= 8) 638 return (ENXIO); 639 640 /* Is it there, does it work. 641 */ 642 Sac = (unit == 0) ? SAC0 : SAC1; 643 i = aceprobe(unit); 644 if (i < 0) 645 goto Bad; 646 647 if (SysaceInitialize(Sac) < 0) { 648 DBGME(3,printf("ace%d: no reset @x%p\n", unit, Sac)); 649 Bad: 650 printf("open failed\n"); 651 return (ENXIO); 652 } 653 654 /* Yep, go ahead. 655 */ 656 sc = alloc(sizeof(struct ace_softc)); 657 memset(sc, 0, sizeof(struct ace_softc)); 658 f->f_devdata = (void *)sc; 659 660 sc->sc_dp = Sac; 661 sc->sc_part = part; 662 663 /* try to read disk label and partition table information */ 664 lp = &sc->sc_label; 665 lp->d_secsize = DEV_BSIZE; 666 lp->d_secpercyl = 1; 667 lp->d_npartitions = MAXPARTITIONS; 668 lp->d_partitions[part].p_offset = 0; 669 lp->d_partitions[part].p_size = 0x7fffffff; 670 671 i = acestrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt); 672 if (i || cnt != DEV_BSIZE) { 673 DBGME(3,printf("ace%d: error reading disk label\n", unit)); 674 goto bad; 675 } 676 msg = getdisklabel(buf, lp); 677 if (msg) { 678 /* If no label, just assume 0 and return */ 679 return (0); 680 } 681 682 if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) { 683 bad: 684 dealloc(sc, sizeof(struct ace_softc)); 685 DBGME(3,printf("ace%d: bad part %d\n", unit, part)); 686 return (ENXIO); 687 } 688 return (0); 689 } 690 691 #ifndef LIBSA_NO_DEV_CLOSE 692 int 693 aceclose(struct open_file *f) 694 { 695 dealloc(f->f_devdata, sizeof(struct ace_softc)); 696 f->f_devdata = (void *)0; 697 return (0); 698 } 699 #endif 700 701 int 702 acestrategy( 703 void *devdata, 704 int rw, 705 daddr_t bn, 706 size_t reqcnt, 707 void *addr, 708 size_t *cnt) /* out: number of bytes transfered */ 709 { 710 struct ace_softc *sc = (struct ace_softc *)devdata; 711 int part = sc->sc_part; 712 struct partition *pp = &sc->sc_label.d_partitions[part]; 713 int s; 714 uint32_t sector; 715 716 #if 0 //useless? 717 if (rw != F_READ) 718 return (EINVAL); 719 #endif 720 721 /* 722 * Partial-block transfers not handled. 723 */ 724 if (reqcnt & (DEV_BSIZE - 1)) { 725 *cnt = 0; 726 return (EINVAL); 727 } 728 729 /* 730 * Compute starting sector 731 */ 732 sector = bn; 733 sector += pp->p_offset; 734 if (pp->p_fstype == FS_RAID) 735 sector += RF_PROTECTED_SECTORS; 736 737 /* read */ 738 s = SysAce_read(sc->sc_dp,addr,sector,reqcnt >> CF_SECBITS); 739 740 if (s < 0) 741 return (EIO); 742 743 /* BUGBUG there's no validation we don't fall off the deep end */ 744 *cnt = reqcnt; 745 return (0); 746 } 747 748