ata.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stddef.h>
00022 #include <string.h>
00023 #include <assert.h>
00024 #include <errno.h>
00025 #include <byteswap.h>
00026 #include <gpxe/blockdev.h>
00027 #include <gpxe/process.h>
00028 #include <gpxe/ata.h>
00029
00030
00031
00032
00033
00034
00035
00036 static inline __attribute__ (( always_inline )) struct ata_device *
00037 block_to_ata ( struct block_device *blockdev ) {
00038 return container_of ( blockdev, struct ata_device, blockdev );
00039 }
00040
00041
00042
00043
00044
00045
00046
00047
00048 static inline __attribute__ (( always_inline )) int
00049 ata_command ( struct ata_device *ata, struct ata_command *command ) {
00050 int rc;
00051
00052 DBG ( "ATA cmd %02x dev %02x LBA%s %llx count %04x\n",
00053 command->cb.cmd_stat, command->cb.device,
00054 ( command->cb.lba48 ? "48" : "" ),
00055 ( unsigned long long ) command->cb.lba.native,
00056 command->cb.count.native );
00057
00058
00059 command->rc = -EINPROGRESS;
00060
00061
00062 if ( ( rc = ata->command ( ata, command ) ) != 0 ) {
00063
00064 DBG ( "ATA could not issue command: %s\n", strerror ( rc ) );
00065 return rc;
00066 }
00067
00068
00069 while ( command->rc == -EINPROGRESS )
00070 step();
00071 if ( ( rc = command->rc ) != 0 ) {
00072
00073 DBG ( "ATA command failed: %s\n", strerror ( rc ) );
00074 return rc;
00075 }
00076
00077 return 0;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 static int ata_read ( struct block_device *blockdev, uint64_t block,
00090 unsigned long count, userptr_t buffer ) {
00091 struct ata_device *ata = block_to_ata ( blockdev );
00092 struct ata_command command;
00093
00094 memset ( &command, 0, sizeof ( command ) );
00095 command.cb.lba.native = block;
00096 command.cb.count.native = count;
00097 command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
00098 command.cb.lba48 = ata->lba48;
00099 if ( ! ata->lba48 )
00100 command.cb.device |= command.cb.lba.bytes.low_prev;
00101 command.cb.cmd_stat = ( ata->lba48 ? ATA_CMD_READ_EXT : ATA_CMD_READ );
00102 command.data_in = buffer;
00103 return ata_command ( ata, &command );
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 static int ata_write ( struct block_device *blockdev, uint64_t block,
00116 unsigned long count, userptr_t buffer ) {
00117 struct ata_device *ata = block_to_ata ( blockdev );
00118 struct ata_command command;
00119
00120 memset ( &command, 0, sizeof ( command ) );
00121 command.cb.lba.native = block;
00122 command.cb.count.native = count;
00123 command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
00124 command.cb.lba48 = ata->lba48;
00125 if ( ! ata->lba48 )
00126 command.cb.device |= command.cb.lba.bytes.low_prev;
00127 command.cb.cmd_stat = ( ata->lba48 ?
00128 ATA_CMD_WRITE_EXT : ATA_CMD_WRITE );
00129 command.data_out = buffer;
00130 return ata_command ( ata, &command );
00131 }
00132
00133
00134
00135
00136
00137
00138
00139 static int ata_identify ( struct block_device *blockdev ) {
00140 struct ata_device *ata = block_to_ata ( blockdev );
00141 struct ata_command command;
00142 struct ata_identity identity;
00143 int rc;
00144
00145
00146 memset ( &command, 0, sizeof ( command ) );
00147 command.cb.count.native = 1;
00148 command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
00149 command.cb.cmd_stat = ATA_CMD_IDENTIFY;
00150 command.data_in = virt_to_user ( &identity );
00151 linker_assert ( sizeof ( identity ) == ATA_SECTOR_SIZE,
00152 __ata_identity_bad_size__ );
00153 if ( ( rc = ata_command ( ata, &command ) ) != 0 )
00154 return rc;
00155
00156
00157 blockdev->blksize = ATA_SECTOR_SIZE;
00158 if ( identity.supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) {
00159 ata->lba48 = 1;
00160 blockdev->blocks = le64_to_cpu ( identity.lba48_sectors );
00161 } else {
00162 blockdev->blocks = le32_to_cpu ( identity.lba_sectors );
00163 }
00164 return 0;
00165 }
00166
00167 static struct block_device_operations ata_operations = {
00168 .read = ata_read,
00169 .write = ata_write
00170 };
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 int init_atadev ( struct ata_device *ata ) {
00185
00186 ata->blockdev.op = &ata_operations;
00187 return ata_identify ( &ata->blockdev );
00188 }