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 /drivers/scsi/libata-core.c | |
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>
Diffstat (limited to 'drivers/scsi/libata-core.c')
-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 18418c82d6f..9946618f1a3 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. |