diff options
| author | Tejun Heo <htejun@gmail.com> | 2006-03-05 14:31:56 -0500 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-03-11 19:03:39 -0500 |
| commit | cb95d562e40140572efbca809f372e608aff7326 (patch) | |
| tree | 3ffa5b34bdce55dd387fdb1be0412555a642ac6f | |
| parent | 1da7b0d01b20bf21f3263d8d2f17fa49a214d773 (diff) | |
[PATCH] libata: add xfer_mask handling functions
Add ata_pack_xfermask(), ata_xfer_mask2mode(), ata_xfer_mode2mask(),
ata_xfer_mode2shift() and ata_id_xfermask(). These functions will be
used by following patches to simplify xfer_mask handling.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/scsi/libata-core.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 18418c82d6f6..9946618f1a35 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
| @@ -231,6 +231,108 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) | |||
| 231 | return -1; | 231 | return -1; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | /** | ||
| 235 | * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask | ||
| 236 | * @pio_mask: pio_mask | ||
| 237 | * @mwdma_mask: mwdma_mask | ||
| 238 | * @udma_mask: udma_mask | ||
| 239 | * | ||
| 240 | * Pack @pio_mask, @mwdma_mask and @udma_mask into a single | ||
| 241 | * unsigned int xfer_mask. | ||
| 242 | * | ||
| 243 | * LOCKING: | ||
| 244 | * None. | ||
| 245 | * | ||
| 246 | * RETURNS: | ||
| 247 | * Packed xfer_mask. | ||
| 248 | */ | ||
| 249 | static unsigned int ata_pack_xfermask(unsigned int pio_mask, | ||
| 250 | unsigned int mwdma_mask, | ||
| 251 | unsigned int udma_mask) | ||
| 252 | { | ||
| 253 | return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) | | ||
| 254 | ((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) | | ||
| 255 | ((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA); | ||
| 256 | } | ||
| 257 | |||
| 258 | static const struct ata_xfer_ent { | ||
| 259 | unsigned int shift, bits; | ||
| 260 | u8 base; | ||
| 261 | } ata_xfer_tbl[] = { | ||
| 262 | { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 }, | ||
| 263 | { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 }, | ||
| 264 | { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 }, | ||
| 265 | { -1, }, | ||
| 266 | }; | ||
| 267 | |||
| 268 | /** | ||
| 269 | * ata_xfer_mask2mode - Find matching XFER_* for the given xfer_mask | ||
| 270 | * @xfer_mask: xfer_mask of interest | ||
| 271 | * | ||
| 272 | * Return matching XFER_* value for @xfer_mask. Only the highest | ||
| 273 | * bit of @xfer_mask is considered. | ||
| 274 | * | ||
| 275 | * LOCKING: | ||
| 276 | * None. | ||
| 277 | * | ||
| 278 | * RETURNS: | ||
| 279 | * Matching XFER_* value, 0 if no match found. | ||
| 280 | */ | ||
| 281 | static u8 ata_xfer_mask2mode(unsigned int xfer_mask) | ||
| 282 | { | ||
| 283 | int highbit = fls(xfer_mask) - 1; | ||
| 284 | const struct ata_xfer_ent *ent; | ||
| 285 | |||
| 286 | for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) | ||
| 287 | if (highbit >= ent->shift && highbit < ent->shift + ent->bits) | ||
| 288 | return ent->base + highbit - ent->shift; | ||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | /** | ||
| 293 | * ata_xfer_mode2mask - Find matching xfer_mask for XFER_* | ||
| 294 | * @xfer_mode: XFER_* of interest | ||
| 295 | * | ||
| 296 | * Return matching xfer_mask for @xfer_mode. | ||
| 297 | * | ||
| 298 | * LOCKING: | ||
| 299 | * None. | ||
| 300 | * | ||
| 301 | * RETURNS: | ||
| 302 | * Matching xfer_mask, 0 if no match found. | ||
| 303 | */ | ||
| 304 | static unsigned int ata_xfer_mode2mask(u8 xfer_mode) | ||
| 305 | { | ||
| 306 | const struct ata_xfer_ent *ent; | ||
| 307 | |||
| 308 | for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) | ||
| 309 | if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits) | ||
| 310 | return 1 << (ent->shift + xfer_mode - ent->base); | ||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | /** | ||
| 315 | * ata_xfer_mode2shift - Find matching xfer_shift for XFER_* | ||
| 316 | * @xfer_mode: XFER_* of interest | ||
| 317 | * | ||
| 318 | * Return matching xfer_shift for @xfer_mode. | ||
| 319 | * | ||
| 320 | * LOCKING: | ||
| 321 | * None. | ||
| 322 | * | ||
| 323 | * RETURNS: | ||
| 324 | * Matching xfer_shift, -1 if no match found. | ||
| 325 | */ | ||
| 326 | static int ata_xfer_mode2shift(unsigned int xfer_mode) | ||
| 327 | { | ||
| 328 | const struct ata_xfer_ent *ent; | ||
| 329 | |||
| 330 | for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) | ||
| 331 | if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits) | ||
| 332 | return ent->shift; | ||
| 333 | return -1; | ||
| 334 | } | ||
| 335 | |||
| 234 | static const char * const xfer_mode_str[] = { | 336 | static const char * const xfer_mode_str[] = { |
| 235 | "PIO0", | 337 | "PIO0", |
| 236 | "PIO1", | 338 | "PIO1", |
| @@ -682,6 +784,51 @@ static inline void ata_dump_id(const u16 *id) | |||
| 682 | id[93]); | 784 | id[93]); |
| 683 | } | 785 | } |
| 684 | 786 | ||
| 787 | /** | ||
| 788 | * ata_id_xfermask - Compute xfermask from the given IDENTIFY data | ||
| 789 | * @id: IDENTIFY data to compute xfer mask from | ||
| 790 | * | ||
| 791 | * Compute the xfermask for this device. This is not as trivial | ||
| 792 | * as it seems if we must consider early devices correctly. | ||
| 793 | * | ||
| 794 | * FIXME: pre IDE drive timing (do we care ?). | ||
| 795 | * | ||
| 796 | * LOCKING: | ||
| 797 | * None. | ||
| 798 | * | ||
| 799 | * RETURNS: | ||
| 800 | * Computed xfermask | ||
| 801 | */ | ||
| 802 | static unsigned int ata_id_xfermask(const u16 *id) | ||
| 803 | { | ||
| 804 | unsigned int pio_mask, mwdma_mask, udma_mask; | ||
| 805 | |||
| 806 | /* Usual case. Word 53 indicates word 64 is valid */ | ||
| 807 | if (id[ATA_ID_FIELD_VALID] & (1 << 1)) { | ||
| 808 | pio_mask = id[ATA_ID_PIO_MODES] & 0x03; | ||
| 809 | pio_mask <<= 3; | ||
| 810 | pio_mask |= 0x7; | ||
| 811 | } else { | ||
| 812 | /* If word 64 isn't valid then Word 51 high byte holds | ||
| 813 | * the PIO timing number for the maximum. Turn it into | ||
| 814 | * a mask. | ||
| 815 | */ | ||
| 816 | pio_mask = (2 << (id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ; | ||
| 817 | |||
| 818 | /* But wait.. there's more. Design your standards by | ||
| 819 | * committee and you too can get a free iordy field to | ||
| 820 | * process. However its the speeds not the modes that | ||
| 821 | * are supported... Note drivers using the timing API | ||
| 822 | * will get this right anyway | ||
| 823 | */ | ||
| 824 | } | ||
| 825 | |||
| 826 | mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07; | ||
| 827 | udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; | ||
| 828 | |||
| 829 | return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask); | ||
| 830 | } | ||
| 831 | |||
| 685 | /* | 832 | /* |
| 686 | * Compute the PIO modes available for this device. This is not as | 833 | * Compute the PIO modes available for this device. This is not as |
| 687 | * trivial as it seems if we must consider early devices correctly. | 834 | * trivial as it seems if we must consider early devices correctly. |
