|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2006 Michael Brown <[email protected]>. ! 3: * ! 4: * This program is free software; you can redistribute it and/or ! 5: * modify it under the terms of the GNU General Public License as ! 6: * published by the Free Software Foundation; either version 2 of the ! 7: * License, or any later version. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, but ! 10: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 12: * General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, write to the Free Software ! 16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <stddef.h> ! 22: #include <stdlib.h> ! 23: #include <string.h> ! 24: #include <assert.h> ! 25: #include <errno.h> ! 26: #include <byteswap.h> ! 27: #include <ipxe/list.h> ! 28: #include <ipxe/interface.h> ! 29: #include <ipxe/blockdev.h> ! 30: #include <ipxe/edd.h> ! 31: #include <ipxe/ata.h> ! 32: ! 33: /** @file ! 34: * ! 35: * ATA block device ! 36: * ! 37: */ ! 38: ! 39: /****************************************************************************** ! 40: * ! 41: * Interface methods ! 42: * ! 43: ****************************************************************************** ! 44: */ ! 45: ! 46: /** ! 47: * Issue ATA command ! 48: * ! 49: * @v control ATA control interface ! 50: * @v data ATA data interface ! 51: * @v command ATA command ! 52: * @ret tag Command tag, or negative error ! 53: */ ! 54: int ata_command ( struct interface *control, struct interface *data, ! 55: struct ata_cmd *command ) { ! 56: struct interface *dest; ! 57: ata_command_TYPE ( void * ) *op = ! 58: intf_get_dest_op ( control, ata_command, &dest ); ! 59: void *object = intf_object ( dest ); ! 60: int tag; ! 61: ! 62: if ( op ) { ! 63: tag = op ( object, data, command ); ! 64: } else { ! 65: /* Default is to fail to issue the command */ ! 66: tag = -EOPNOTSUPP; ! 67: } ! 68: ! 69: intf_put ( dest ); ! 70: return tag; ! 71: } ! 72: ! 73: /****************************************************************************** ! 74: * ! 75: * ATA devices and commands ! 76: * ! 77: ****************************************************************************** ! 78: */ ! 79: ! 80: /** List of all ATA commands */ ! 81: static LIST_HEAD ( ata_commands ); ! 82: ! 83: /** An ATA device */ ! 84: struct ata_device { ! 85: /** Reference count */ ! 86: struct refcnt refcnt; ! 87: /** Block control interface */ ! 88: struct interface block; ! 89: /** ATA control interface */ ! 90: struct interface ata; ! 91: ! 92: /** Device number ! 93: * ! 94: * Must be ATA_DEV_MASTER or ATA_DEV_SLAVE. ! 95: */ ! 96: unsigned int device; ! 97: /** Maximum number of blocks per single transfer */ ! 98: unsigned int max_count; ! 99: /** Device uses LBA48 extended addressing */ ! 100: int lba48; ! 101: }; ! 102: ! 103: /** An ATA command */ ! 104: struct ata_command { ! 105: /** Reference count */ ! 106: struct refcnt refcnt; ! 107: /** ATA device */ ! 108: struct ata_device *atadev; ! 109: /** List of ATA commands */ ! 110: struct list_head list; ! 111: ! 112: /** Block data interface */ ! 113: struct interface block; ! 114: /** ATA data interface */ ! 115: struct interface ata; ! 116: ! 117: /** Command type */ ! 118: struct ata_command_type *type; ! 119: /** Command tag */ ! 120: uint32_t tag; ! 121: ! 122: /** Private data */ ! 123: uint8_t priv[0]; ! 124: }; ! 125: ! 126: /** An ATA command type */ ! 127: struct ata_command_type { ! 128: /** Name */ ! 129: const char *name; ! 130: /** Additional working space */ ! 131: size_t priv_len; ! 132: /** Command for non-LBA48-capable devices */ ! 133: uint8_t cmd_lba; ! 134: /** Command for LBA48-capable devices */ ! 135: uint8_t cmd_lba48; ! 136: /** ! 137: * Calculate data-in buffer ! 138: * ! 139: * @v atacmd ATA command ! 140: * @v buffer Available buffer ! 141: * @v len Available buffer length ! 142: * @ret data_in Data-in buffer ! 143: * @ret data_in_len Data-in buffer length ! 144: */ ! 145: void ( * data_in ) ( struct ata_command *atacmd, userptr_t buffer, ! 146: size_t len, userptr_t *data_in, ! 147: size_t *data_in_len ); ! 148: /** ! 149: * Calculate data-out buffer ! 150: * ! 151: * ! 152: * @v atacmd ATA command ! 153: * @v buffer Available buffer ! 154: * @v len Available buffer length ! 155: * @ret data_out Data-out buffer ! 156: * @ret data_out_len Data-out buffer length ! 157: */ ! 158: void ( * data_out ) ( struct ata_command *atacmd, userptr_t buffer, ! 159: size_t len, userptr_t *data_out, ! 160: size_t *data_out_len ); ! 161: /** ! 162: * Handle ATA command completion ! 163: * ! 164: * @v atacmd ATA command ! 165: * @v rc Reason for completion ! 166: */ ! 167: void ( * done ) ( struct ata_command *atacmd, int rc ); ! 168: }; ! 169: ! 170: /** ! 171: * Get reference to ATA device ! 172: * ! 173: * @v atadev ATA device ! 174: * @ret atadev ATA device ! 175: */ ! 176: static inline __attribute__ (( always_inline )) struct ata_device * ! 177: atadev_get ( struct ata_device *atadev ) { ! 178: ref_get ( &atadev->refcnt ); ! 179: return atadev; ! 180: } ! 181: ! 182: /** ! 183: * Drop reference to ATA device ! 184: * ! 185: * @v atadev ATA device ! 186: */ ! 187: static inline __attribute__ (( always_inline )) void ! 188: atadev_put ( struct ata_device *atadev ) { ! 189: ref_put ( &atadev->refcnt ); ! 190: } ! 191: ! 192: /** ! 193: * Get reference to ATA command ! 194: * ! 195: * @v atacmd ATA command ! 196: * @ret atacmd ATA command ! 197: */ ! 198: static inline __attribute__ (( always_inline )) struct ata_command * ! 199: atacmd_get ( struct ata_command *atacmd ) { ! 200: ref_get ( &atacmd->refcnt ); ! 201: return atacmd; ! 202: } ! 203: ! 204: /** ! 205: * Drop reference to ATA command ! 206: * ! 207: * @v atacmd ATA command ! 208: */ ! 209: static inline __attribute__ (( always_inline )) void ! 210: atacmd_put ( struct ata_command *atacmd ) { ! 211: ref_put ( &atacmd->refcnt ); ! 212: } ! 213: ! 214: /** ! 215: * Get ATA command private data ! 216: * ! 217: * @v atacmd ATA command ! 218: * @ret priv Private data ! 219: */ ! 220: static inline __attribute__ (( always_inline )) void * ! 221: atacmd_priv ( struct ata_command *atacmd ) { ! 222: return atacmd->priv; ! 223: } ! 224: ! 225: /** ! 226: * Free ATA command ! 227: * ! 228: * @v refcnt Reference count ! 229: */ ! 230: static void atacmd_free ( struct refcnt *refcnt ) { ! 231: struct ata_command *atacmd = ! 232: container_of ( refcnt, struct ata_command, refcnt ); ! 233: ! 234: /* Remove from list of commands */ ! 235: list_del ( &atacmd->list ); ! 236: atadev_put ( atacmd->atadev ); ! 237: ! 238: /* Free command */ ! 239: free ( atacmd ); ! 240: } ! 241: ! 242: /** ! 243: * Close ATA command ! 244: * ! 245: * @v atacmd ATA command ! 246: * @v rc Reason for close ! 247: */ ! 248: static void atacmd_close ( struct ata_command *atacmd, int rc ) { ! 249: struct ata_device *atadev = atacmd->atadev; ! 250: ! 251: if ( rc != 0 ) { ! 252: DBGC ( atadev, "ATA %p tag %08x closed: %s\n", ! 253: atadev, atacmd->tag, strerror ( rc ) ); ! 254: } ! 255: ! 256: /* Shut down interfaces */ ! 257: intf_shutdown ( &atacmd->ata, rc ); ! 258: intf_shutdown ( &atacmd->block, rc ); ! 259: } ! 260: ! 261: /** ! 262: * Handle ATA command completion ! 263: * ! 264: * @v atacmd ATA command ! 265: * @v rc Reason for close ! 266: */ ! 267: static void atacmd_done ( struct ata_command *atacmd, int rc ) { ! 268: ! 269: /* Hand over to the command completion handler */ ! 270: atacmd->type->done ( atacmd, rc ); ! 271: } ! 272: ! 273: /** ! 274: * Use provided data buffer for ATA command ! 275: * ! 276: * @v atacmd ATA command ! 277: * @v buffer Available buffer ! 278: * @v len Available buffer length ! 279: * @ret data Data buffer ! 280: * @ret data_len Data buffer length ! 281: */ ! 282: static void atacmd_data_buffer ( struct ata_command *atacmd __unused, ! 283: userptr_t buffer, size_t len, ! 284: userptr_t *data, size_t *data_len ) { ! 285: *data = buffer; ! 286: *data_len = len; ! 287: } ! 288: ! 289: /** ! 290: * Use no data buffer for ATA command ! 291: * ! 292: * @v atacmd ATA command ! 293: * @v buffer Available buffer ! 294: * @v len Available buffer length ! 295: * @ret data Data buffer ! 296: * @ret data_len Data buffer length ! 297: */ ! 298: static void atacmd_data_none ( struct ata_command *atacmd __unused, ! 299: userptr_t buffer __unused, size_t len __unused, ! 300: userptr_t *data __unused, ! 301: size_t *data_len __unused ) { ! 302: /* Nothing to do */ ! 303: } ! 304: ! 305: /** ! 306: * Use private data buffer for ATA command ! 307: * ! 308: * @v atacmd ATA command ! 309: * @v buffer Available buffer ! 310: * @v len Available buffer length ! 311: * @ret data Data buffer ! 312: * @ret data_len Data buffer length ! 313: */ ! 314: static void atacmd_data_priv ( struct ata_command *atacmd, ! 315: userptr_t buffer __unused, size_t len __unused, ! 316: userptr_t *data, size_t *data_len ) { ! 317: *data = virt_to_user ( atacmd_priv ( atacmd ) ); ! 318: *data_len = atacmd->type->priv_len; ! 319: } ! 320: ! 321: /** ATA READ command type */ ! 322: static struct ata_command_type atacmd_read = { ! 323: .name = "READ", ! 324: .cmd_lba = ATA_CMD_READ, ! 325: .cmd_lba48 = ATA_CMD_READ_EXT, ! 326: .data_in = atacmd_data_buffer, ! 327: .data_out = atacmd_data_none, ! 328: .done = atacmd_close, ! 329: }; ! 330: ! 331: /** ATA WRITE command type */ ! 332: static struct ata_command_type atacmd_write = { ! 333: .name = "WRITE", ! 334: .cmd_lba = ATA_CMD_WRITE, ! 335: .cmd_lba48 = ATA_CMD_WRITE_EXT, ! 336: .data_in = atacmd_data_none, ! 337: .data_out = atacmd_data_buffer, ! 338: .done = atacmd_close, ! 339: }; ! 340: ! 341: /** ATA IDENTIFY private data */ ! 342: struct ata_identify_private { ! 343: /** Identity data */ ! 344: struct ata_identity identity; ! 345: }; ! 346: ! 347: /** ! 348: * Return ATA model string (for debugging) ! 349: * ! 350: * @v identify ATA identity data ! 351: * @ret model Model string ! 352: */ ! 353: static const char * ata_model ( struct ata_identity *identity ) { ! 354: static union { ! 355: uint16_t words[ sizeof ( identity->model ) / 2 ]; ! 356: char text[ sizeof ( identity->model ) + 1 /* NUL */ ]; ! 357: } buf; ! 358: unsigned int i; ! 359: ! 360: for ( i = 0 ; i < ( sizeof ( identity->model ) / 2 ) ; i++ ) ! 361: buf.words[i] = bswap_16 ( identity->model[i] ); ! 362: ! 363: return buf.text; ! 364: } ! 365: ! 366: /** ! 367: * Handle ATA IDENTIFY command completion ! 368: * ! 369: * @v atacmd ATA command ! 370: * @v rc Reason for completion ! 371: */ ! 372: static void atacmd_identify_done ( struct ata_command *atacmd, int rc ) { ! 373: struct ata_device *atadev = atacmd->atadev; ! 374: struct ata_identify_private *priv = atacmd_priv ( atacmd ); ! 375: struct ata_identity *identity = &priv->identity; ! 376: struct block_device_capacity capacity; ! 377: ! 378: /* Close if command failed */ ! 379: if ( rc != 0 ) { ! 380: atacmd_close ( atacmd, rc ); ! 381: return; ! 382: } ! 383: ! 384: /* Extract capacity */ ! 385: if ( identity->supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) { ! 386: atadev->lba48 = 1; ! 387: capacity.blocks = le64_to_cpu ( identity->lba48_sectors ); ! 388: } else { ! 389: capacity.blocks = le32_to_cpu ( identity->lba_sectors ); ! 390: } ! 391: capacity.blksize = ATA_SECTOR_SIZE; ! 392: capacity.max_count = atadev->max_count; ! 393: DBGC ( atadev, "ATA %p is a %s\n", atadev, ata_model ( identity ) ); ! 394: DBGC ( atadev, "ATA %p has %#llx blocks (%ld MB) and uses %s\n", ! 395: atadev, capacity.blocks, ! 396: ( ( signed long ) ( capacity.blocks >> 11 ) ), ! 397: ( atadev->lba48 ? "LBA48" : "LBA" ) ); ! 398: ! 399: /* Return capacity to caller */ ! 400: block_capacity ( &atacmd->block, &capacity ); ! 401: ! 402: /* Close command */ ! 403: atacmd_close ( atacmd, 0 ); ! 404: } ! 405: ! 406: /** ATA IDENTITY command type */ ! 407: static struct ata_command_type atacmd_identify = { ! 408: .name = "IDENTIFY", ! 409: .priv_len = sizeof ( struct ata_identify_private ), ! 410: .cmd_lba = ATA_CMD_IDENTIFY, ! 411: .cmd_lba48 = ATA_CMD_IDENTIFY, ! 412: .data_in = atacmd_data_priv, ! 413: .data_out = atacmd_data_none, ! 414: .done = atacmd_identify_done, ! 415: }; ! 416: ! 417: /** ATA command block interface operations */ ! 418: static struct interface_operation atacmd_block_op[] = { ! 419: INTF_OP ( intf_close, struct ata_command *, atacmd_close ), ! 420: }; ! 421: ! 422: /** ATA command block interface descriptor */ ! 423: static struct interface_descriptor atacmd_block_desc = ! 424: INTF_DESC_PASSTHRU ( struct ata_command, block, ! 425: atacmd_block_op, ata ); ! 426: ! 427: /** ATA command ATA interface operations */ ! 428: static struct interface_operation atacmd_ata_op[] = { ! 429: INTF_OP ( intf_close, struct ata_command *, atacmd_done ), ! 430: }; ! 431: ! 432: /** ATA command ATA interface descriptor */ ! 433: static struct interface_descriptor atacmd_ata_desc = ! 434: INTF_DESC_PASSTHRU ( struct ata_command, ata, ! 435: atacmd_ata_op, block ); ! 436: ! 437: /** ! 438: * Create ATA command ! 439: * ! 440: * @v atadev ATA device ! 441: * @v block Block data interface ! 442: * @v type ATA command type ! 443: * @v lba Starting logical block address ! 444: * @v count Number of blocks to transfer ! 445: * @v buffer Data buffer ! 446: * @v len Length of data buffer ! 447: * @ret rc Return status code ! 448: */ ! 449: static int atadev_command ( struct ata_device *atadev, ! 450: struct interface *block, ! 451: struct ata_command_type *type, ! 452: uint64_t lba, unsigned int count, ! 453: userptr_t buffer, size_t len ) { ! 454: struct ata_command *atacmd; ! 455: struct ata_cmd command; ! 456: int tag; ! 457: int rc; ! 458: ! 459: /* Allocate and initialise structure */ ! 460: atacmd = zalloc ( sizeof ( *atacmd ) + type->priv_len ); ! 461: if ( ! atacmd ) { ! 462: rc = -ENOMEM; ! 463: goto err_zalloc; ! 464: } ! 465: ref_init ( &atacmd->refcnt, atacmd_free ); ! 466: intf_init ( &atacmd->block, &atacmd_block_desc, &atacmd->refcnt ); ! 467: intf_init ( &atacmd->ata, &atacmd_ata_desc, ! 468: &atacmd->refcnt ); ! 469: atacmd->atadev = atadev_get ( atadev ); ! 470: list_add ( &atacmd->list, &ata_commands ); ! 471: atacmd->type = type; ! 472: ! 473: /* Sanity check */ ! 474: if ( len != ( count * ATA_SECTOR_SIZE ) ) { ! 475: DBGC ( atadev, "ATA %p tag %08x buffer length mismatch (count " ! 476: "%d len %zd)\n", atadev, atacmd->tag, count, len ); ! 477: rc = -EINVAL; ! 478: goto err_len; ! 479: } ! 480: ! 481: /* Construct command */ ! 482: memset ( &command, 0, sizeof ( command ) ); ! 483: command.cb.lba.native = lba; ! 484: command.cb.count.native = count; ! 485: command.cb.device = ( atadev->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA ); ! 486: command.cb.lba48 = atadev->lba48; ! 487: if ( ! atadev->lba48 ) ! 488: command.cb.device |= command.cb.lba.bytes.low_prev; ! 489: command.cb.cmd_stat = ! 490: ( atadev->lba48 ? type->cmd_lba48 : type->cmd_lba ); ! 491: type->data_in ( atacmd, buffer, len, ! 492: &command.data_in, &command.data_in_len ); ! 493: type->data_out ( atacmd, buffer, len, ! 494: &command.data_out, &command.data_out_len ); ! 495: ! 496: /* Issue command */ ! 497: if ( ( tag = ata_command ( &atadev->ata, &atacmd->ata, ! 498: &command ) ) < 0 ) { ! 499: rc = tag; ! 500: DBGC ( atadev, "ATA %p tag %08x could not issue command: %s\n", ! 501: atadev, atacmd->tag, strerror ( rc ) ); ! 502: goto err_command; ! 503: } ! 504: atacmd->tag = tag; ! 505: ! 506: DBGC2 ( atadev, "ATA %p tag %08x %s cmd %02x dev %02x LBA%s %08llx " ! 507: "count %04x\n", atadev, atacmd->tag, atacmd->type->name, ! 508: command.cb.cmd_stat, command.cb.device, ! 509: ( command.cb.lba48 ? "48" : "" ), ! 510: ( unsigned long long ) command.cb.lba.native, ! 511: command.cb.count.native ); ! 512: ! 513: /* Attach to parent interface, mortalise self, and return */ ! 514: intf_plug_plug ( &atacmd->block, block ); ! 515: ref_put ( &atacmd->refcnt ); ! 516: return 0; ! 517: ! 518: err_command: ! 519: err_len: ! 520: atacmd_close ( atacmd, rc ); ! 521: ref_put ( &atacmd->refcnt ); ! 522: err_zalloc: ! 523: return rc; ! 524: } ! 525: ! 526: /** ! 527: * Issue ATA block read ! 528: * ! 529: * @v atadev ATA device ! 530: * @v block Block data interface ! 531: * @v lba Starting logical block address ! 532: * @v count Number of blocks to transfer ! 533: * @v buffer Data buffer ! 534: * @v len Length of data buffer ! 535: * @ret rc Return status code ! 536: ! 537: */ ! 538: static int atadev_read ( struct ata_device *atadev, ! 539: struct interface *block, ! 540: uint64_t lba, unsigned int count, ! 541: userptr_t buffer, size_t len ) { ! 542: return atadev_command ( atadev, block, &atacmd_read, ! 543: lba, count, buffer, len ); ! 544: } ! 545: ! 546: /** ! 547: * Issue ATA block write ! 548: * ! 549: * @v atadev ATA device ! 550: * @v block Block data interface ! 551: * @v lba Starting logical block address ! 552: * @v count Number of blocks to transfer ! 553: * @v buffer Data buffer ! 554: * @v len Length of data buffer ! 555: * @ret rc Return status code ! 556: */ ! 557: static int atadev_write ( struct ata_device *atadev, ! 558: struct interface *block, ! 559: uint64_t lba, unsigned int count, ! 560: userptr_t buffer, size_t len ) { ! 561: return atadev_command ( atadev, block, &atacmd_write, ! 562: lba, count, buffer, len ); ! 563: } ! 564: ! 565: /** ! 566: * Read ATA device capacity ! 567: * ! 568: * @v atadev ATA device ! 569: * @v block Block data interface ! 570: * @ret rc Return status code ! 571: */ ! 572: static int atadev_read_capacity ( struct ata_device *atadev, ! 573: struct interface *block ) { ! 574: struct ata_identity *identity; ! 575: ! 576: assert ( atacmd_identify.priv_len == sizeof ( *identity ) ); ! 577: assert ( atacmd_identify.priv_len == ATA_SECTOR_SIZE ); ! 578: return atadev_command ( atadev, block, &atacmd_identify, ! 579: 0, 1, UNULL, ATA_SECTOR_SIZE ); ! 580: } ! 581: ! 582: /** ! 583: * Close ATA device ! 584: * ! 585: * @v atadev ATA device ! 586: * @v rc Reason for close ! 587: */ ! 588: static void atadev_close ( struct ata_device *atadev, int rc ) { ! 589: struct ata_command *atacmd; ! 590: struct ata_command *tmp; ! 591: ! 592: /* Shut down interfaces */ ! 593: intf_shutdown ( &atadev->block, rc ); ! 594: intf_shutdown ( &atadev->ata, rc ); ! 595: ! 596: /* Shut down any remaining commands */ ! 597: list_for_each_entry_safe ( atacmd, tmp, &ata_commands, list ) { ! 598: if ( atacmd->atadev != atadev ) ! 599: continue; ! 600: atacmd_get ( atacmd ); ! 601: atacmd_close ( atacmd, rc ); ! 602: atacmd_put ( atacmd ); ! 603: } ! 604: } ! 605: ! 606: /** ! 607: * Describe ATA device using EDD ! 608: * ! 609: * @v atadev ATA device ! 610: * @v type EDD interface type ! 611: * @v path EDD device path ! 612: * @ret rc Return status code ! 613: */ ! 614: static int atadev_edd_describe ( struct ata_device *atadev, ! 615: struct edd_interface_type *type, ! 616: union edd_device_path *path ) { ! 617: ! 618: type->type = cpu_to_le64 ( EDD_INTF_TYPE_ATA ); ! 619: path->ata.slave = ( ( atadev->device == ATA_DEV_SLAVE ) ? 0x01 : 0x00 ); ! 620: return 0; ! 621: } ! 622: ! 623: /** ATA device block interface operations */ ! 624: static struct interface_operation atadev_block_op[] = { ! 625: INTF_OP ( block_read, struct ata_device *, atadev_read ), ! 626: INTF_OP ( block_write, struct ata_device *, atadev_write ), ! 627: INTF_OP ( block_read_capacity, struct ata_device *, ! 628: atadev_read_capacity ), ! 629: INTF_OP ( intf_close, struct ata_device *, atadev_close ), ! 630: INTF_OP ( edd_describe, struct ata_device *, atadev_edd_describe ), ! 631: }; ! 632: ! 633: /** ATA device block interface descriptor */ ! 634: static struct interface_descriptor atadev_block_desc = ! 635: INTF_DESC_PASSTHRU ( struct ata_device, block, ! 636: atadev_block_op, ata ); ! 637: ! 638: /** ATA device ATA interface operations */ ! 639: static struct interface_operation atadev_ata_op[] = { ! 640: INTF_OP ( intf_close, struct ata_device *, atadev_close ), ! 641: }; ! 642: ! 643: /** ATA device ATA interface descriptor */ ! 644: static struct interface_descriptor atadev_ata_desc = ! 645: INTF_DESC_PASSTHRU ( struct ata_device, ata, ! 646: atadev_ata_op, block ); ! 647: ! 648: /** ! 649: * Open ATA device ! 650: * ! 651: * @v block Block control interface ! 652: * @v ata ATA control interface ! 653: * @v device ATA device number ! 654: * @v max_count Maximum number of blocks per single transfer ! 655: * @ret rc Return status code ! 656: */ ! 657: int ata_open ( struct interface *block, struct interface *ata, ! 658: unsigned int device, unsigned int max_count ) { ! 659: struct ata_device *atadev; ! 660: ! 661: /* Allocate and initialise structure */ ! 662: atadev = zalloc ( sizeof ( *atadev ) ); ! 663: if ( ! atadev ) ! 664: return -ENOMEM; ! 665: ref_init ( &atadev->refcnt, NULL ); ! 666: intf_init ( &atadev->block, &atadev_block_desc, &atadev->refcnt ); ! 667: intf_init ( &atadev->ata, &atadev_ata_desc, &atadev->refcnt ); ! 668: atadev->device = device; ! 669: atadev->max_count = max_count; ! 670: ! 671: /* Attach to ATA and parent and interfaces, mortalise self, ! 672: * and return ! 673: */ ! 674: intf_plug_plug ( &atadev->ata, ata ); ! 675: intf_plug_plug ( &atadev->block, block ); ! 676: ref_put ( &atadev->refcnt ); ! 677: return 0; ! 678: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.