Annotation of qemu/roms/ipxe/src/drivers/block/ata.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.