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