1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Generic IDE disk driver File: dev_ide_common.c 5 * 6 * This is a simple driver for IDE hard disks. The mechanics 7 * of talking to the I/O ports are abstracted sufficiently to make 8 * this driver usable for various bus interfaces. 9 * 10 * Author: Mitch Lichtenberg 11 * 12 ********************************************************************* 13 * 14 * Copyright 2000,2001,2002,2003 15 * Broadcom Corporation. All rights reserved. 16 * 17 * This software is furnished under license and may be used and 18 * copied only in accordance with the following terms and 19 * conditions. Subject to these conditions, you may download, 20 * copy, install, use, modify and distribute modified or unmodified 21 * copies of this software in source and/or binary form. No title 22 * or ownership is transferred hereby. 23 * 24 * 1) Any source code used, modified or distributed must reproduce 25 * and retain this copyright notice and list of conditions 26 * as they appear in the source file. 27 * 28 * 2) No right is granted to use any trade name, trademark, or 29 * logo of Broadcom Corporation. The "Broadcom Corporation" 30 * name may not be used to endorse or promote products derived 31 * from this software without the prior written permission of 32 * Broadcom Corporation. 33 * 34 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 35 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 36 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 37 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 38 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 39 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 42 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 44 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 45 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 46 * THE POSSIBILITY OF SUCH DAMAGE. 47 ********************************************************************* */ 48 49 50#include "cfe.h" 51 52#include "dev_ide_common.h" 53 54#include "dev_ide.h" 55 56/* ********************************************************************* 57 * Macros 58 ********************************************************************* */ 59 60#define DISK_MASTER 0 61#define DISK_SLAVE 1 62 63#define IDE_WRITEREG8(ide,reg,val) IDEDISP_WRITEREG8(ide->idecommon_dispatch,reg,val) 64#define IDE_WRITEREG16(ide,reg,val) IDEDISP_WRITEREG16(ide->idecommon_dispatch,reg,val) 65#define IDE_WRITEBUF(ide,reg,buf,len) IDEDISP_WRITEBUF(ide->idecommon_dispatch,reg,buf,len) 66#define IDE_READREG8(ide,reg) IDEDISP_READREG8(ide->idecommon_dispatch,reg) 67#define IDE_READREG16(ide,reg) IDEDISP_READREG16(ide->idecommon_dispatch,reg) 68#define IDE_READBUF(ide,reg,buf,len) IDEDISP_READBUF(ide->idecommon_dispatch,reg,buf,len) 69 70#define GETWORD_LE(buf,wordidx) (((unsigned int) (buf)[wordidx]) + \ 71 (((unsigned int) (buf)[wordidx+1]) << 8)) 72 73#define _IDE_DEBUG_ 74 75 76static void idecommon_testdrq(idecommon_t *ide); 77static int idecommon_spinup(idecommon_t *ide ); 78 79/* ********************************************************************* 80 * idecommon_sectorshift(size) 81 * 82 * Given a sector size, return log2(size). We cheat; this is 83 * only needed for 2048 and 512-byte sectors. 84 * Explicitly using shifts and masks in sector number calculations 85 * helps on 32-bit-only platforms, since we probably won't need 86 * a helper library. 87 * 88 * Input parameters: 89 * size - sector size 90 * 91 * Return value: 92 * # of bits to shift 93 ********************************************************************* */ 94 95#define idecommon_sectorshift(size) (((size)==2048)?11:9) 96 97/* ********************************************************************* 98 * idecommon_waitnotbusy(ide) 99 * 100 * Wait for an IDE device to report "not busy" 101 * 102 * Input parameters: 103 * ide - IDE interface 104 * 105 * Return value: 106 * 0 if ok, else -1 if timeout 107 ********************************************************************* */ 108 109static int idecommon_waitnotbusy(idecommon_t *ide) 110{ 111 int32_t timer; 112 uint8_t status; 113 114 TIMER_SET(timer,10*CFE_HZ); 115 116 while (!TIMER_EXPIRED(timer)) { 117 status = IDE_READREG8(ide,IDE_REG_STATUS); 118 if (!(status & IDE_STS_BSY) && (status & IDE_STS_DRQ)) { 119 idecommon_testdrq(ide); 120 continue; 121 } 122 if ((status & (IDE_STS_BSY | IDE_STS_DRQ )) == 0) return 0; 123 POLL(); 124 } 125 126#ifdef _IDE_DEBUG_ 127 xprintf("Device did not become unbusy\n"); 128#endif 129 return -1; 130} 131 132#if 0 133/* ********************************************************************* 134 * idecommon_waitready(ide) 135 * 136 * Wait for the specified device to become ready. 137 * 138 * Input parameters: 139 * ide - IDE interface 140 * 141 * Return value: 142 * 0 if device became ready 143 * -1 if device did not become ready 144 ********************************************************************* */ 145 146static int idecommon_waitready(idecommon_t *ide) 147{ 148 int32_t timer; 149 uint8_t status; 150 151 TIMER_SET(timer,10*CFE_HZ); 152 153 while (!TIMER_EXPIRED(timer)) { 154 status = IDE_READREG8(ide,IDE_REG_STATUS); 155 if (status & IDE_STS_RDY) return 0; 156 POLL(); 157 } 158 159#ifdef _IDE_DEBUG_ 160 xprintf("Disk did not become ready\n"); 161#endif 162 163 return -1; 164} 165#endif 166 167/* ********************************************************************* 168 * idecommon_waitbusy(idx) 169 * 170 * Wait for an IDE disk to start processing a command, or at 171 * least long enough to indicate that it is doing so. 172 * The code below looks suspiciously like a timing loop. 173 * unfortunately, that's what it is, determined empirically 174 * for certain ATA flash cards. Without this many reads to the 175 * ALTSTAT register, the PCMCIA controller deasserts the 176 * card detect pins briefly. Anyone have any clues? 177 * 178 * Input parameters: 179 * ide - IDE interface 180 * 181 * Return value: 182 * void 183 ********************************************************************* */ 184 185static void idecommon_waitbusy(idecommon_t *ide) 186{ 187 int idx; 188 189 for (idx = 0; idx < 10; idx++) { 190 IDE_READREG8(ide,IDE_REG_ALTSTAT); 191 IDE_READREG8(ide,IDE_REG_ALTSTAT); 192 IDE_READREG8(ide,IDE_REG_ALTSTAT); 193 IDE_READREG8(ide,IDE_REG_ALTSTAT); 194 } 195} 196 197 198/* ********************************************************************* 199 * idecommon_wait_drq(ide) 200 * 201 * Wait for the BUSY bit to be clear and the DRQ bit to be set. 202 * This is usually the indication that it's time to transfer data. 203 * 204 * Input parameters: 205 * ide - IDE interface 206 * 0 if DRQ is set 207 * -1 if timeout occured 208 ********************************************************************* */ 209 210static int idecommon_wait_drq(idecommon_t *ide) 211{ 212 int32_t timer; 213 uint8_t status; 214 215 TIMER_SET(timer,10*CFE_HZ); 216 217 while (!TIMER_EXPIRED(timer)) { 218 POLL(); 219 status = IDE_READREG8(ide,IDE_REG_STATUS); 220 if (!(status & IDE_STS_BSY) && (status & IDE_STS_ERR)) { 221 xprintf("Drive status: %02X error %02X\n",status, 222 IDE_READREG8(ide,IDE_REG_ERROR)); 223 return -1; 224 } 225 if (!(status & IDE_STS_BSY) && (status & IDE_STS_DRQ)) return 0; 226 } 227 228#ifdef _IDE_DEBUG_ 229 xprintf("Timeout waiting for disk\n"); 230#endif 231 232 return -1; 233} 234 235/* ********************************************************************* 236 * idecommon_testdrq(ide) 237 * 238 * Debug routine. Check the DRQ bit. If it's set, it is not 239 * supposed to be, so transfer data until it clears and report 240 * how much we had to transfer. 241 * 242 * Input parameters: 243 * ide - IDE interface 244 * 245 * Return value: 246 * nothing 247 ********************************************************************* */ 248 249#ifdef _IDE_DEBUG_ 250static void idecommon_testdrq(idecommon_t *ide) 251{ 252 uint8_t status; 253 uint16_t data; 254 int idx; 255 256 status = IDE_READREG8(ide,IDE_REG_STATUS); 257 if (status & IDE_STS_DRQ) { 258 xprintf("Error: DRQ should be zero\n"); 259 idx = 0; 260 while (status & IDE_STS_DRQ) { 261 data = IDE_READREG16(ide,IDE_REG_DATA); 262 idx++; 263 status = IDE_READREG8(ide,IDE_REG_STATUS); 264 } 265 xprintf("Had to read data %d times to clear DRQ\n",idx); 266 } 267} 268#else 269#define idecommon_testdrq(ide) 270#endif 271 272 273/* ********************************************************************* 274 * idecommon_dumpregs(ide) 275 * 276 * Dump out the IDE registers. (debug routine) 277 * 278 * Input parameters: 279 * ide - ide disk 280 * 281 * Return value: 282 * nothing 283 ********************************************************************* */ 284 285static void idecommon_dumpregs(idecommon_t *ide) 286{ 287#if 0 288 uint8_t reg = 0; 289 290 reg = IDE_READREG8(ide,IDE_REG_STATUS); 291 xprintf("Status:%02X ",reg); 292 293 reg = IDE_READREG8(ide,IDE_REG_DRVHD); 294 xprintf("DrvHd:%02X ",reg); 295 296 reg = IDE_READREG8(ide,IDE_REG_CYLLSB); 297 xprintf("CylLSB:%02X ",reg); 298 299 reg = IDE_READREG8(ide,IDE_REG_CYLMSB); 300 xprintf("CylMSB:%02X ",reg); 301 302 reg = IDE_READREG8(ide,IDE_REG_SECNUM); 303 xprintf("SecNum:%02X ",reg); 304 305 reg = IDE_READREG8(ide,IDE_REG_SECCNT); 306 xprintf("SecCnt:%02X ",reg); 307 308 xprintf("\n"); 309#endif 310} 311 312 313/* ********************************************************************* 314 * idecommon_reset(ide) 315 * 316 * Reset the IDE interface. 317 * 318 * Input parameters: 319 * ide - IDE interface 320 * 321 * Return value: 322 * 0 if ok, else -1 if a timeout occured 323 ********************************************************************* */ 324 325static int idecommon_reset(idecommon_t *ide) 326{ 327 return 0; 328} 329 330/* ********************************************************************* 331 * idecommon_identify(ide,buffer) 332 * 333 * Execute an IDENTIFY command to get information about the disk. 334 * 335 * Input parameters: 336 * ide - IDE interface 337 * buffer - pointer to 512 byte buffer 338 * 339 * Return value: 340 * 0 if ok 341 * else error code 342 ********************************************************************* */ 343 344int idecommon_identify(idecommon_t *ide,uint8_t *buffer) 345{ 346 347 /* Device Select Protocol; see ATAPI-4 sect 9.6 */ 348 349 if (idecommon_waitnotbusy(ide) < 0) return -1; 350 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4)|0); 351 if (idecommon_waitnotbusy(ide) < 0) return -1; 352 353 /* Set device registers */ 354 355 IDE_WRITEREG8(ide,IDE_REG_CYLLSB,0); 356 IDE_WRITEREG8(ide,IDE_REG_CYLMSB,0); 357 IDE_WRITEREG8(ide,IDE_REG_SECNUM,1); 358 IDE_WRITEREG8(ide,IDE_REG_SECCNT,1); 359 360 idecommon_testdrq(ide); 361 362 /* Issue command, then read ALT STATUS (9.7) */ 363 364 if (ide->idecommon_atapi) { 365 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_ATAPI_IDENTIFY); 366 } 367 else { 368 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_DRIVE_INFO); 369 } 370 371 IDE_READREG8(ide,IDE_REG_ALTSTAT); 372 idecommon_waitbusy(ide); /* should not be necessary */ 373 374 /* Wait BSY=0 && DRQ=1, then read buffer, see sect 9.7 */ 375 376 if (idecommon_wait_drq(ide) < 0) return -1; 377 IDE_READBUF(ide,IDE_REG_DATA,PTR2HSADDR(buffer),DISK_SECTORSIZE); 378 379 idecommon_testdrq(ide); 380 381 xprintf("Identify Success\n "); 382 383 return 0; 384} 385 386 387/* ********************************************************************* 388 * idecommon_spinup(ide,buffer) 389 * 390 * Execute a spinup command to the disk. 391 * 392 * Input parameters: 393 * ide - IDE interface 394 * buffer - pointer to 512 byte buffer 395 * 396 * Return value: 397 * 0 if ok 398 * else error code 399 ********************************************************************* */ 400 401int idecommon_spinup(idecommon_t *ide ) 402{ 403 404 /* Device Select Protocol; see ATAPI-4 sect 9.6 */ 405 406 if (idecommon_waitnotbusy(ide) < 0) return -1; 407 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4)|0); 408 if (idecommon_waitnotbusy(ide) < 0) return -1; 409 410 /* Set device registers */ 411 412 IDE_WRITEREG8(ide,IDE_REG_CYLLSB,0); 413 IDE_WRITEREG8(ide,IDE_REG_CYLMSB,0); 414 IDE_WRITEREG8(ide,IDE_REG_SECNUM,1); 415 IDE_WRITEREG8(ide,IDE_REG_SECCNT,1); 416 417 idecommon_testdrq(ide); 418 419 /* Issue command, then read ALT STATUS (9.7) */ 420 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_SET_FEATURE); 421 IDE_WRITEREG8(ide,IDE_REG_FEATURE,IDE_SUB_FEAT_DEV_SPINUP); 422 423 IDE_READREG8(ide,IDE_REG_ALTSTAT); 424 idecommon_waitbusy(ide); /* should not be necessary */ 425 426 /* Wait BSY=0 && DRQ=1 see sect 9.7 */ 427 if (idecommon_wait_drq(ide) < 0) return -1; 428 429 idecommon_testdrq(ide); 430 431 return 0; 432} 433 434 435/* ********************************************************************* 436 * idecommon_packet(ide,packet,pktlen,databuf,datalen) 437 * 438 * Process an IDE "packet" command, for ATAPI devices 439 * 440 * Input parameters: 441 * ide - IDE interface 442 * packet,pktlen - command packet 443 * databuf,datalen - data buffer 444 * 445 * Return value: 446 * 0 if ok 447 * else error code 448 ********************************************************************* */ 449 450static int idecommon_packet(idecommon_t *ide, 451 uint8_t *packet,int pktlen, 452 hsaddr_t databuf,int datalen) 453{ 454 uint8_t status; 455 456 /* 457 * Not valid on non-ATAPI disks 458 */ 459 460 if (!ide->idecommon_atapi) return -1; 461 462 /* 463 * Set up the standard IDE registers for an ATAPI PACKET command 464 */ 465 466 /* Device Select Protocol */ 467 if (idecommon_waitnotbusy(ide) < 0) return -1; 468 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4)); 469 if (idecommon_waitnotbusy(ide) < 0) return -1; 470 471 /* Device Registers */ 472 IDE_WRITEREG8(ide,IDE_REG_BCLSB,(datalen & 0xFF)); 473 IDE_WRITEREG8(ide,IDE_REG_BCMSB,((datalen >> 8) & 0xFF)); 474 IDE_WRITEREG8(ide,IDE_REG_SECNUM,0); 475 IDE_WRITEREG8(ide,IDE_REG_SECCNT,0); 476 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_ATAPI_PACKET); 477 478 /* 479 * Wait for the DRQ bit to indicate that we should send 480 * the packet. 481 */ 482 483 if (idecommon_wait_drq(ide) < 0) return -1; 484 485 status = IDE_READREG8(ide,IDE_REG_IR); 486 487 /* 488 * Send the packet to the device 489 */ 490 491 IDE_WRITEBUF(ide,IDE_REG_DATA,PTR2HSADDR(packet),pktlen); 492 493 /* 494 * Wait for BSY to be cleared and DRQ to be set. 495 */ 496 497 if (idecommon_wait_drq(ide) < 0) return -1; 498 status = IDE_READREG8(ide,IDE_REG_ALTSTAT); 499 if (idecommon_wait_drq(ide) < 0) return -1; 500 status = IDE_READREG8(ide,IDE_REG_IR); 501 502 503 /* 504 * Transfer data, if necessary. The direction will depend 505 * on what the drive says. If this is a non-data command, 506 * passing databuf == NULL can avoid all this. 507 */ 508 509 if (databuf) { 510 status = IDE_READREG8(ide,IDE_REG_IR); 511 if (status & IDE_IR_CD) { 512 xprintf("Error: Command/data should be zero\n"); 513 } 514 515 if (status & IDE_IR_IO) { /* from device (READ) */ 516 IDE_READBUF(ide,IDE_REG_DATA,databuf,datalen); 517 } 518 else { /* to device (WRITE) */ 519 IDE_WRITEBUF(ide,IDE_REG_DATA,databuf,datalen); 520 } 521 522 } 523 524 525 idecommon_testdrq(ide); 526 527 return 0; 528 529} 530 531 532/* ********************************************************************* 533 * idecommon_request_sense(ide) 534 * 535 * Request sense data. This also clears a UNIT_ATTENTION condition 536 * 537 * Input parameters: 538 * ide - IDE interface 539 * 540 * Return value: 541 * 0 if ok 542 * else error code 543 ********************************************************************* */ 544static int idecommon_request_sense(idecommon_t *ide) 545{ 546 uint8_t cdb[12]; 547 uint8_t sensedata[32]; 548 int res; 549 int numbytes; 550 551 numbytes = sizeof(sensedata); 552 553 cdb[0] = CDB_CMD_REQSENSE; 554 cdb[1] = 0; 555 cdb[2] = 0; 556 cdb[3] = 0; 557 cdb[4] = sizeof(sensedata); 558 cdb[5] = 0; 559 cdb[6] = 0; 560 cdb[7] = 0; 561 cdb[8] = 0; 562 cdb[9] = 0; 563 cdb[10] = 0; 564 cdb[11] = 0; 565 566 memset(sensedata,0,sizeof(sensedata)); 567 568 res = idecommon_packet(ide,cdb,sizeof(cdb),PTR2HSADDR(sensedata),numbytes); 569 570#if 0 571 xprintf("Sense data: "); 572 xprintf("Err:%02X ",sensedata[0]); 573 xprintf("Key:%02X ",sensedata[1]); 574 xprintf("Information:%02X%02X ",sensedata[2],sensedata[3]); 575 xprintf("ASC:%02X ASCQ:%02X ",sensedata[12],sensedata[13]); 576 xprintf("\n"); 577#endif 578 579 idecommon_testdrq(ide); 580 581 return res; 582} 583 584 585/* ********************************************************************* 586 * idecommon_read_atapi(ide,lba,numsec,buffer) 587 * 588 * Read sector(s) from the device. This version is for ATAPI devs. 589 * 590 * Input parameters: 591 * ide - IDE interface 592 * lba - logical block address 593 * numsec - number of sectors 594 * buffer - buffer address 595 * 596 * Return value: 597 * 0 if ok 598 * else error code 599 ********************************************************************* */ 600 601static int idecommon_read_atapi(idecommon_t *ide,uint64_t lba, 602 int numsec,hsaddr_t buffer) 603{ 604 uint8_t cdb[12]; 605 int res = 0; 606 int numbytes; 607 int idx; 608 609 numbytes = numsec << idecommon_sectorshift(ide->idecommon_sectorsize); 610 611 cdb[0] = CDB_CMD_READ; 612 cdb[1] = 0; 613 cdb[2] = ((lba >> 24) & 0xFF); 614 cdb[3] = ((lba >> 16) & 0xFF); 615 cdb[4] = ((lba >> 8) & 0xFF); 616 cdb[5] = ((lba >> 0) & 0xFF); 617 cdb[6] = 0; 618 cdb[7] = ((numsec >> 8) & 0xFF); 619 cdb[8] = ((numsec >> 0) & 0xFF); 620 cdb[9] = 0; 621 cdb[10] = 0; 622 cdb[11] = 0; 623 624 for (idx = 0; idx < 4; idx++) { 625 res = idecommon_packet(ide,cdb,sizeof(cdb),buffer,numbytes); 626 if (res < 0) { 627 idecommon_request_sense(ide); 628 continue; 629 } 630 break; 631 } 632 633 return res; 634} 635 636 637/* ********************************************************************* 638 * idecommon_write_atapi(ide,lba,numsec,buffer) 639 * 640 * Write sector(s) to the device. This version is for ATAPI disks 641 * 642 * Input parameters: 643 * ide - IDE interface 644 * lba - logical block address 645 * numsec - number of sectors 646 * buffer - buffer address 647 * 648 * Return value: 649 * 0 if ok 650 * else error code 651 ********************************************************************* */ 652 653static int idecommon_write_atapi(idecommon_t *ide,uint64_t lba, 654 int numsec,hsaddr_t buffer) 655{ 656 uint8_t cdb[12]; 657 int res; 658 int numbytes; 659 660 numbytes = numsec << idecommon_sectorshift(ide->idecommon_sectorsize); 661 662 cdb[0] = CDB_CMD_WRITE; 663 cdb[1] = 0; 664 cdb[2] = ((lba >> 24) & 0xFF); 665 cdb[3] = ((lba >> 16) & 0xFF); 666 cdb[4] = ((lba >> 8) & 0xFF); 667 cdb[5] = ((lba >> 0) & 0xFF); 668 cdb[6] = 0; 669 cdb[7] = ((numsec >> 8) & 0xFF); 670 cdb[8] = ((numsec >> 0) & 0xFF); 671 cdb[9] = 0; 672 cdb[10] = 0; 673 cdb[11] = 0; 674 675 res = idecommon_packet(ide,cdb,sizeof(cdb),buffer,numbytes); 676 677 return res; 678} 679 680 681/* ********************************************************************* 682 * idecommon_read_lba(ide,lba,numsec,buffer) 683 * 684 * Read sector(s) from the device. 685 * 686 * Input parameters: 687 * ide - IDE interface 688 * lba - logical block address 689 * numsec - number of sectors 690 * buffer - buffer address 691 * 692 * Return value: 693 * 0 if ok 694 * else error code 695 ********************************************************************* */ 696 697static int idecommon_read_lba(idecommon_t *ide,uint64_t lba,int numsec,hsaddr_t buffer) 698{ 699 int secidx; 700 hsaddr_t ptr; 701 702 if (idecommon_waitnotbusy(ide) < 0) return -1; 703 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4) | ((lba >> 24) & 0x0F) | 0x40); 704 if (idecommon_waitnotbusy(ide) < 0) return -1; 705 706 IDE_WRITEREG8(ide,IDE_REG_CYLMSB,((lba >> 16) & 0xFF)); 707 IDE_WRITEREG8(ide,IDE_REG_CYLLSB,((lba >> 8) & 0xFF)); 708 IDE_WRITEREG8(ide,IDE_REG_SECNUM,(lba & 0xFF)); 709 IDE_WRITEREG8(ide,IDE_REG_SECCNT,numsec); 710 711 idecommon_testdrq(ide); 712 713 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_READ); 714 715 idecommon_waitbusy(ide); 716 if (idecommon_wait_drq(ide) < 0) return -1; 717 718 ptr = buffer; 719 720 for (secidx = 0; secidx < numsec; secidx++) { 721 IDE_READBUF(ide,IDE_REG_DATA,ptr,ide->idecommon_sectorsize); 722 ptr += ide->idecommon_sectorsize; 723 } 724 725 idecommon_testdrq(ide); 726 727 return 0; 728} 729 730 731/* ********************************************************************* 732 * idecommon_write_lba(ide,lba,numsec,buffer) 733 * 734 * Write sector(s) from the device. 735 * 736 * Input parameters: 737 * ide - IDE interface 738 * lba - logical block address 739 * numsec - number of sectors 740 * buffer - buffer address 741 * 742 * Return value: 743 * 0 if ok 744 * else error code 745 ********************************************************************* */ 746 747static int idecommon_write_lba(idecommon_t *ide,uint64_t lba,int numsec,hsaddr_t buffer) 748{ 749 int secidx; 750 hsaddr_t ptr; 751 752 if (idecommon_waitnotbusy(ide) < 0) return -1; 753 IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4) | ((lba >> 24) & 0x0F) | 0x40); 754 if (idecommon_waitnotbusy(ide) < 0) return -1; 755 756 IDE_WRITEREG8(ide,IDE_REG_CYLMSB,((lba >> 16) & 0xFF)); 757 IDE_WRITEREG8(ide,IDE_REG_CYLLSB,((lba >> 8) & 0xFF)); 758 IDE_WRITEREG8(ide,IDE_REG_SECNUM,(lba & 0xFF)); 759 IDE_WRITEREG8(ide,IDE_REG_SECCNT,numsec); 760 761 IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_WRITE); 762 763 if (idecommon_wait_drq(ide) < 0) return -1; 764 765 ptr = buffer; 766 767 for (secidx = 0; secidx < numsec; secidx++) { 768 IDE_WRITEBUF(ide,IDE_REG_DATA,ptr,ide->idecommon_sectorsize); 769 ptr += ide->idecommon_sectorsize; 770 } 771 772 idecommon_testdrq(ide); 773 774 return 0; 775} 776 777 778/* ********************************************************************* 779 * idecommon_diagnostic(ide) 780 * 781 * run the device diagnostics on the IDE device. This also 782 * helps us determine if it's an IDE or ATAPI disk, since the 783 * diagnostic will leave a signature in the registers. 784 * 785 * Input parameters: 786 * softc - IDE interface 787 * 788 * Return value: 789 * 0 if ok 790 * else error code 791 ********************************************************************* */ 792 793static int idecommon_diagnostic(idecommon_t *softc) 794{ 795 if (idecommon_waitnotbusy(softc) < 0) return -1; 796 IDE_WRITEREG8(softc,IDE_REG_DRVHD,(softc->idecommon_unit<<4)); 797 if (idecommon_waitnotbusy(softc) < 0) return -1; 798 799 IDE_WRITEREG8(softc,IDE_REG_COMMAND,IDE_CMD_DIAGNOSTIC); 800 if (idecommon_waitnotbusy(softc) < 0) return -1; 801 802 cfe_sleep(CFE_HZ/2); 803 idecommon_dumpregs(softc); 804 805 return 0; 806} 807 808 809/* ********************************************************************* 810 * idecommon_getmodel(buffer,model) 811 * 812 * Get the ASCII model name out of an IDE identify buffer. some 813 * byte swapping is involved here. The trailing blanks are trimmed. 814 * 815 * Input parameters: 816 * buffer - 512-byte buffer from IDENTIFY command 817 * model - 41-byte string (max) for model name 818 * 819 * Return value: 820 * nothing 821 ********************************************************************* */ 822 823static void idecommon_getmodel(uint8_t *buffer,char *model) 824{ 825 uint16_t w; 826 int idx; 827 828 for (idx = 0; idx < 20; idx++) { 829 w = GETWORD_LE(buffer,27+idx); 830 model[idx*2] = w >> 8; 831 model[idx*2+1] = w & 0xFF; 832 } 833 for (idx = 39; idx > 0; idx--) { 834 if (model[idx] != ' ') { 835 model[idx+1] = '\0'; 836 break; 837 } 838 } 839 840} 841 842/* ********************************************************************* 843 * idecommon_devprobe(softc) 844 * 845 * Probe the IDE device, to determine if it's actually present 846 * or not. If present, determine if it's IDE or ATAPI and 847 * get the device size. Init our internal structures so we know 848 * how to talk to the device. 849 * 850 * Input parameters: 851 * softc - IDE structure 852 * noisy - display stuff as we probe 853 * 854 * Return value: 855 * 0 if ok, else error code 856 ********************************************************************* */ 857 858int idecommon_devprobe(idecommon_t *softc,int noisy) 859{ 860 int res; 861 int atapi; 862 unsigned char buffer[DISK_SECTORSIZE]; 863 unsigned char model[41]; 864 uint64_t ttlsect; 865 int devtype; 866 uint16_t w; 867 char *typename; 868 869 /* 870 * Reset the drive 871 */ 872 873 res = idecommon_reset(softc); 874 if (res < 0) return -1; 875 876 877 /* 878 * Attempt spinup( required for SATA ) 879 */ 880 res = idecommon_spinup(softc); 881 882 883 /* 884 * Run diagnostic to get the signature. 885 */ 886 887 res = idecommon_diagnostic(softc); 888 if (res < 0) return res; 889 890 /* 891 * Test signature 892 */ 893 894 atapi = 0; 895 if ((IDE_READREG8(softc,IDE_REG_CYLLSB) == ATAPI_SIG_LSB) && 896 (IDE_READREG8(softc,IDE_REG_CYLMSB) == ATAPI_SIG_MSB)) { 897 atapi = 1; 898 } 899 900 if (noisy) { 901 if (atapi) xprintf("ATAPI: "); 902 else xprintf("IDE: "); 903 } 904 905 /* 906 * Do the appropriate IDENTIFY command to get device information 907 */ 908 softc->idecommon_atapi = atapi; 909 res = idecommon_identify(softc,&buffer[0]); 910 if (res < 0) return -1; 911 912 /* 913 * Using that information, determine our device type 914 */ 915 916 if (!atapi) { 917 devtype = IDE_DEVTYPE_DISK; 918 typename = "Disk"; 919 } 920 else { 921 w = GETWORD_LE(&buffer[0],0); 922 switch ((w >> 8) & 31) { 923 case 5: /* CD-ROM */ 924 devtype = IDE_DEVTYPE_CDROM; 925 typename = "CD-ROM"; 926 break; 927 default: 928 devtype = IDE_DEVTYPE_ATAPIDISK; 929 typename = "Disk"; 930 break; 931 } 932 } 933 934 /* 935 * Say nice things about the device. 936 */ 937 938 noisy = 1; 939 idecommon_getmodel(&buffer[0], (char *)model); 940 if (noisy) xprintf("%s, \"%s\"",typename,model); 941 942#ifdef _IDE_DEBUG_ 943 if (!softc->idecommon_atapi) { 944 ttlsect = (GETWORD_LE(buffer,57) + (GETWORD_LE(buffer,58) << 16)); 945 if (noisy) xprintf(", Sectors: %llu (%lld MB)",ttlsect, 946 (uint64_t) (ttlsect/2048)); 947 } 948 else { 949 ttlsect = 0; 950 } 951 952#endif 953 if (noisy) xprintf("\n"); 954 955 /* 956 * Initialize internal structure info, especially pointers to the 957 * read/write routines and the sector size. 958 */ 959 960 softc->idecommon_ttlsect = ttlsect; 961 idecommon_init(softc,devtype); 962 963 return res; 964} 965 966/* ********************************************************************* 967 * idecommon_open(ctx) 968 * 969 * Process the CFE OPEN call for this device. For IDE disks, 970 * the device is reset and identified, and the geometry is 971 * determined. 972 * 973 * Input parameters: 974 * ctx - device context 975 * 976 * Return value: 977 * 0 if ok, else error code 978 ********************************************************************* */ 979 980 981int idecommon_open(cfe_devctx_t *ctx) 982{ 983 idecommon_t *softc = ctx->dev_softc; 984 int res; 985 986 if (softc->idecommon_deferprobe) { 987 res = idecommon_devprobe(softc,0); 988 if (res < 0) return res; 989 } 990 991 return 0; 992} 993 994/* ********************************************************************* 995 * idecommon_read(ctx,buffer) 996 * 997 * Process a CFE READ command for the IDE device. This is 998 * more complex than it looks, since CFE offsets are byte offsets 999 * and we may need to read partial sectors. 1000 * 1001 * Input parameters: 1002 * ctx - device context 1003 * buffer - buffer descriptor 1004 * 1005 * Return value: 1006 * number of bytes read, or <0 if an error occured 1007 ********************************************************************* */ 1008 1009int idecommon_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 1010{ 1011 idecommon_t *softc = ctx->dev_softc; 1012 hsaddr_t bptr; 1013 int blen; 1014 int numsec; 1015 int res = 0; 1016 int amtcopy; 1017 uint64_t lba; 1018 uint64_t offset; 1019 unsigned char sector[MAX_SECTORSIZE]; 1020 int sectorshift; 1021 1022 sectorshift = idecommon_sectorshift(softc->idecommon_sectorsize); 1023 1024 bptr = buffer->buf_ptr; 1025 blen = buffer->buf_length; 1026 offset = buffer->buf_offset; 1027 numsec = (blen + softc->idecommon_sectorsize - 1) >> sectorshift; 1028 1029 if (offset & (softc->idecommon_sectorsize-1)) { 1030 lba = (offset >> sectorshift); 1031 res = (*softc->idecommon_readfunc)(softc,lba,1,PTR2HSADDR(sector)); 1032 if (res < 0) goto out; 1033 amtcopy = softc->idecommon_sectorsize - (offset & (softc->idecommon_sectorsize-1)); 1034 if (amtcopy > blen) amtcopy = blen; 1035 hs_memcpy_to_hs(bptr,§or[offset & (softc->idecommon_sectorsize-1)],amtcopy); 1036 bptr += amtcopy; 1037 offset += amtcopy; 1038 blen -= amtcopy; 1039 } 1040 1041 while (blen >= softc->idecommon_sectorsize) { 1042 lba = (offset >> sectorshift); 1043 amtcopy = softc->idecommon_sectorsize; 1044 res = (*softc->idecommon_readfunc)(softc,lba,1,bptr); 1045 if (res < 0) goto out; 1046 bptr += amtcopy; 1047 offset += amtcopy; 1048 blen -= amtcopy; 1049 } 1050 1051 if (blen) { 1052 lba = (offset >> sectorshift); 1053 res = (*softc->idecommon_readfunc)(softc,lba,1,PTR2HSADDR(sector)); 1054 if (res < 0) goto out; 1055 amtcopy = blen; 1056 hs_memcpy_to_hs(bptr,sector,amtcopy); 1057 bptr += amtcopy; 1058 offset += amtcopy; 1059 blen -= amtcopy; 1060 } 1061 1062out: 1063 buffer->buf_retlen = bptr - buffer->buf_ptr; 1064 1065 return res; 1066} 1067 1068/* ********************************************************************* 1069 * idecommon_inpstat(ctx,inpstat) 1070 * 1071 * Test input status for the IDE disk. Disks are always ready 1072 * to read. 1073 * 1074 * Input parameters: 1075 * ctx - device context 1076 * inpstat - input status structure 1077 * 1078 * Return value: 1079 * 0 1080 ********************************************************************* */ 1081 1082int idecommon_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) 1083{ 1084 /* idecommon_t *softc = ctx->dev_softc; */ 1085 1086 inpstat->inp_status = 1; 1087 return 0; 1088} 1089 1090/* ********************************************************************* 1091 * idecommon_write(ctx,buffer) 1092 * 1093 * Process a CFE WRITE command for the IDE device. If the write 1094 * involves partial sectors, the affected sectors are read first 1095 * and the changes are merged in. 1096 * 1097 * Input parameters: 1098 * ctx - device context 1099 * buffer - buffer descriptor 1100 * 1101 * Return value: 1102 * number of bytes write, or <0 if an error occured 1103 ********************************************************************* */ 1104 1105int idecommon_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 1106{ 1107 idecommon_t *softc = ctx->dev_softc; 1108 hsaddr_t bptr; 1109 int blen; 1110 int numsec; 1111 int res = 0; 1112 int amtcopy; 1113 uint64_t offset; 1114 uint64_t lba; 1115 unsigned char sector[MAX_SECTORSIZE]; 1116 int sectorshift; 1117 1118 sectorshift = (softc->idecommon_sectorsize == 2048) ? 11 : 9; 1119 1120 bptr = buffer->buf_ptr; 1121 blen = buffer->buf_length; 1122 offset = buffer->buf_offset; 1123 numsec = (blen + softc->idecommon_sectorsize - 1) >> sectorshift; 1124 1125 if (offset & (softc->idecommon_sectorsize-1)) { 1126 lba = (offset >> sectorshift); 1127 res = (*softc->idecommon_readfunc)(softc,lba,1,PTR2HSADDR(sector)); 1128 if (res < 0) goto out; 1129 amtcopy = softc->idecommon_sectorsize - (offset & (softc->idecommon_sectorsize-1)); 1130 if (amtcopy > blen) amtcopy = blen; 1131 hs_memcpy_from_hs(§or[offset & (softc->idecommon_sectorsize-1)],bptr,amtcopy); 1132 res = (*softc->idecommon_writefunc)(softc,lba,1,PTR2HSADDR(sector)); 1133 if (res < 0) goto out; 1134 bptr += amtcopy; 1135 offset += amtcopy; 1136 blen -= amtcopy; 1137 } 1138 1139 while (blen >= softc->idecommon_sectorsize) { 1140 amtcopy = softc->idecommon_sectorsize; 1141 lba = (offset >> sectorshift); 1142 res = (*softc->idecommon_writefunc)(softc,lba,1,bptr); 1143 if (res < 0) goto out; 1144 bptr += amtcopy; 1145 offset += amtcopy; 1146 blen -= amtcopy; 1147 } 1148 1149 if (blen) { 1150 lba = (offset >> sectorshift); 1151 res = (*softc->idecommon_readfunc)(softc,lba,1,PTR2HSADDR(sector)); 1152 if (res < 0) goto out; 1153 amtcopy = blen; 1154 hs_memcpy_from_hs(sector,bptr,amtcopy); 1155 res = (*softc->idecommon_writefunc)(softc,lba,1,PTR2HSADDR(sector)); 1156 if (res < 0) goto out; 1157 bptr += amtcopy; 1158 offset += amtcopy; 1159 blen -= amtcopy; 1160 } 1161 1162out: 1163 buffer->buf_retlen = bptr - buffer->buf_ptr; 1164 1165 return res; 1166} 1167 1168 1169/* ********************************************************************* 1170 * idecommon_ioctl(ctx,buffer) 1171 * 1172 * Process device I/O control requests for the IDE device. 1173 * 1174 * Input parameters: 1175 * ctx - device context 1176 * buffer - buffer descriptor 1177 * 1178 * Return value: 1179 * 0 if ok 1180 * else error code 1181 ********************************************************************* */ 1182 1183int idecommon_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 1184{ 1185 idecommon_t *softc = ctx->dev_softc; 1186 unsigned int info; 1187 unsigned long long linfo; 1188 blockdev_info_t devinfo; 1189 1190 switch ((int)buffer->buf_ioctlcmd) { 1191 case IOCTL_BLOCK_GETBLOCKSIZE: 1192 info = softc->idecommon_sectorsize; 1193 hs_memcpy_to_hs(buffer->buf_ptr,&info,sizeof(info)); 1194 break; 1195 case IOCTL_BLOCK_GETTOTALBLOCKS: 1196 linfo = softc->idecommon_ttlsect; 1197 hs_memcpy_to_hs(buffer->buf_ptr,&linfo,sizeof(linfo)); 1198 break; 1199 case IOCTL_BLOCK_GETDEVTYPE: 1200 devinfo.blkdev_totalblocks = softc->idecommon_ttlsect; 1201 devinfo.blkdev_blocksize = softc->idecommon_sectorsize; 1202 devinfo.blkdev_devtype = (softc->idecommon_devtype == IDE_DEVTYPE_CDROM) ? 1203 BLOCK_DEVTYPE_CDROM : BLOCK_DEVTYPE_DISK; 1204 hs_memcpy_to_hs(buffer->buf_ptr,&devinfo,sizeof(devinfo)); 1205 break; 1206 default: 1207 return -1; 1208 } 1209 1210 return 0; 1211} 1212 1213/* ********************************************************************* 1214 * idecommon_close(ctx) 1215 * 1216 * Close the I/O device. 1217 * 1218 * Input parameters: 1219 * ctx - device context 1220 * 1221 * Return value: 1222 * 0 if ok, else error code 1223 ********************************************************************* */ 1224 1225int idecommon_close(cfe_devctx_t *ctx) 1226{ 1227 /* idecommon_t *softc = ctx->dev_softc; */ 1228 1229 return 0; 1230} 1231 1232 1233/* ********************************************************************* 1234 * idecommon_init(ide,devtype) 1235 * 1236 * Set up internal values based on the device type 1237 * 1238 * Input parameters: 1239 * ide - IDE interface 1240 * devtype - device type 1241 * 1242 * Return value: 1243 * nothing 1244 ********************************************************************* */ 1245 1246void idecommon_init(idecommon_t *ide,int devtype) 1247{ 1248 1249 ide->idecommon_devtype = devtype; 1250 1251 switch (ide->idecommon_devtype) { 1252 case IDE_DEVTYPE_DISK: 1253 ide->idecommon_atapi = FALSE; 1254 ide->idecommon_sectorsize = DISK_SECTORSIZE; 1255 break; 1256 case IDE_DEVTYPE_CDROM: 1257 ide->idecommon_atapi = TRUE; 1258 ide->idecommon_sectorsize = CDROM_SECTORSIZE; 1259 break; 1260 case IDE_DEVTYPE_ATAPIDISK: 1261 ide->idecommon_atapi = TRUE; 1262 ide->idecommon_sectorsize = DISK_SECTORSIZE; 1263 break; 1264 default: 1265 ide->idecommon_atapi = FALSE; 1266 ide->idecommon_sectorsize = DISK_SECTORSIZE; 1267 break; 1268 } 1269 1270 if (ide->idecommon_atapi) { 1271 ide->idecommon_readfunc = idecommon_read_atapi; 1272 ide->idecommon_writefunc = idecommon_write_atapi; 1273 } 1274 else { 1275 ide->idecommon_readfunc = idecommon_read_lba; 1276 ide->idecommon_writefunc = idecommon_write_lba; 1277 } 1278} 1279 1280/* ********************************************************************* 1281 * idecommon_attach(devdisp) 1282 * 1283 * Set up a cfe_devdisp structure that points at the idecommon 1284 * structures. 1285 * 1286 * Input parameters: 1287 * devdisp - cfe_devdisp_t structure 1288 * 1289 * Return value: 1290 * nothing 1291 ********************************************************************* */ 1292void idecommon_attach(cfe_devdisp_t *disp) 1293{ 1294 disp->dev_open = idecommon_open; 1295 disp->dev_read = idecommon_read; 1296 disp->dev_inpstat = idecommon_inpstat; 1297 disp->dev_write = idecommon_write; 1298 disp->dev_ioctl = idecommon_ioctl; 1299 disp->dev_close = idecommon_close; 1300 disp->dev_poll = NULL; 1301 disp->dev_reset = NULL; 1302} 1303