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