You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  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. #include <stddef.h>
  19. #include <string.h>
  20. #include <assert.h>
  21. #include <byteswap.h>
  22. #include <gpxe/blockdev.h>
  23. #include <gpxe/ata.h>
  24. /** @file
  25. *
  26. * ATA block device
  27. *
  28. */
  29. static inline __attribute__ (( always_inline )) struct ata_device *
  30. block_to_ata ( struct block_device *blockdev ) {
  31. return container_of ( blockdev, struct ata_device, blockdev );
  32. }
  33. /**
  34. * Issue ATA command
  35. *
  36. * @v ata ATA device
  37. * @v command ATA command
  38. * @ret rc Return status code
  39. */
  40. static inline __attribute__ (( always_inline )) int
  41. ata_command ( struct ata_device *ata, struct ata_command *command ) {
  42. DBG ( "ATA cmd %02x dev %02x LBA%s %llx count %04x\n",
  43. command->cb.cmd_stat, command->cb.device,
  44. ( command->cb.lba48 ? "48" : "" ),
  45. ( unsigned long long ) command->cb.lba.native,
  46. command->cb.count.native );
  47. return ata->command ( ata, command );
  48. }
  49. /**
  50. * Read block from ATA device
  51. *
  52. * @v blockdev Block device
  53. * @v block LBA block number
  54. * @v count Block count
  55. * @v buffer Data buffer
  56. * @ret rc Return status code
  57. */
  58. static int ata_read ( struct block_device *blockdev, uint64_t block,
  59. unsigned long count, userptr_t buffer ) {
  60. struct ata_device *ata = block_to_ata ( blockdev );
  61. struct ata_command command;
  62. memset ( &command, 0, sizeof ( command ) );
  63. command.cb.lba.native = block;
  64. command.cb.count.native = count;
  65. command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
  66. command.cb.lba48 = ata->lba48;
  67. if ( ! ata->lba48 )
  68. command.cb.device |= command.cb.lba.bytes.low_prev;
  69. command.cb.cmd_stat = ( ata->lba48 ? ATA_CMD_READ_EXT : ATA_CMD_READ );
  70. command.data_in = buffer;
  71. return ata_command ( ata, &command );
  72. }
  73. /**
  74. * Write block to ATA device
  75. *
  76. * @v blockdev Block device
  77. * @v block LBA block number
  78. * @v count Block count
  79. * @v buffer Data buffer
  80. * @ret rc Return status code
  81. */
  82. static int ata_write ( struct block_device *blockdev, uint64_t block,
  83. unsigned long count, userptr_t buffer ) {
  84. struct ata_device *ata = block_to_ata ( blockdev );
  85. struct ata_command command;
  86. memset ( &command, 0, sizeof ( command ) );
  87. command.cb.lba.native = block;
  88. command.cb.count.native = count;
  89. command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
  90. command.cb.lba48 = ata->lba48;
  91. if ( ! ata->lba48 )
  92. command.cb.device |= command.cb.lba.bytes.low_prev;
  93. command.cb.cmd_stat = ( ata->lba48 ?
  94. ATA_CMD_WRITE_EXT : ATA_CMD_WRITE );
  95. command.data_out = buffer;
  96. return ata_command ( ata, &command );
  97. }
  98. /**
  99. * Identify ATA device
  100. *
  101. * @v blockdev Block device
  102. * @ret rc Return status code
  103. */
  104. static int ata_identify ( struct block_device *blockdev ) {
  105. struct ata_device *ata = block_to_ata ( blockdev );
  106. struct ata_command command;
  107. struct ata_identity identity;
  108. int rc;
  109. /* Issue IDENTIFY */
  110. memset ( &command, 0, sizeof ( command ) );
  111. command.cb.count.native = 1;
  112. command.cb.device = ( ata->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
  113. command.cb.cmd_stat = ATA_CMD_IDENTIFY;
  114. command.data_in = virt_to_user ( &identity );
  115. linker_assert ( sizeof ( identity ) == ATA_SECTOR_SIZE,
  116. __ata_identity_bad_size__ );
  117. if ( ( rc = ata_command ( ata, &command ) ) != 0 )
  118. return rc;
  119. /* Fill in block device parameters */
  120. blockdev->blksize = ATA_SECTOR_SIZE;
  121. if ( identity.supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) {
  122. ata->lba48 = 1;
  123. blockdev->blocks = le64_to_cpu ( identity.lba48_sectors );
  124. } else {
  125. blockdev->blocks = le32_to_cpu ( identity.lba_sectors );
  126. }
  127. return 0;
  128. }
  129. /**
  130. * Initialise ATA device
  131. *
  132. * @v ata ATA device
  133. * @ret rc Return status code
  134. *
  135. * Initialises an ATA device. The ata_device::command field and the
  136. * @c ATA_FL_SLAVE portion of the ata_device::flags field must already
  137. * be filled in. This function will configure ata_device::blockdev,
  138. * including issuing an IDENTIFY DEVICE call to determine the block
  139. * size and total device size.
  140. */
  141. int init_atadev ( struct ata_device *ata ) {
  142. /** Fill in read and write methods, and get device capacity */
  143. ata->blockdev.read = ata_read;
  144. ata->blockdev.write = ata_write;
  145. return ata_identify ( &ata->blockdev );
  146. }