aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-03-05 14:31:56 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-11 19:03:39 -0500
commitcb95d562e40140572efbca809f372e608aff7326 (patch)
tree3ffa5b34bdce55dd387fdb1be0412555a642ac6f /drivers/scsi/libata-core.c
parent1da7b0d01b20bf21f3263d8d2f17fa49a214d773 (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.c147
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 */
249static 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
258static 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 */
281static 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 */
304static 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 */
326static 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
234static const char * const xfer_mode_str[] = { 336static 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 */
802static 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.