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