diff options
Diffstat (limited to 'drivers/ide/ide-lib.c')
-rw-r--r-- | drivers/ide/ide-lib.c | 125 |
1 files changed, 73 insertions, 52 deletions
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 850ef63cc986..8237d89eec6e 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c | |||
@@ -71,75 +71,96 @@ EXPORT_SYMBOL(ide_xfer_verbose); | |||
71 | /** | 71 | /** |
72 | * ide_dma_speed - compute DMA speed | 72 | * ide_dma_speed - compute DMA speed |
73 | * @drive: drive | 73 | * @drive: drive |
74 | * @mode; intended mode | 74 | * @mode: modes available |
75 | * | 75 | * |
76 | * Checks the drive capabilities and returns the speed to use | 76 | * Checks the drive capabilities and returns the speed to use |
77 | * for the transfer. Returns -1 if the requested mode is unknown | 77 | * for the DMA transfer. Returns 0 if the drive is incapable |
78 | * (eg PIO) | 78 | * of DMA transfers. |
79 | */ | 79 | */ |
80 | 80 | ||
81 | u8 ide_dma_speed(ide_drive_t *drive, u8 mode) | 81 | u8 ide_dma_speed(ide_drive_t *drive, u8 mode) |
82 | { | 82 | { |
83 | struct hd_driveid *id = drive->id; | 83 | struct hd_driveid *id = drive->id; |
84 | ide_hwif_t *hwif = HWIF(drive); | 84 | ide_hwif_t *hwif = HWIF(drive); |
85 | u8 ultra_mask, mwdma_mask, swdma_mask; | ||
85 | u8 speed = 0; | 86 | u8 speed = 0; |
86 | 87 | ||
87 | if (drive->media != ide_disk && hwif->atapi_dma == 0) | 88 | if (drive->media != ide_disk && hwif->atapi_dma == 0) |
88 | return 0; | 89 | return 0; |
89 | 90 | ||
90 | switch(mode) { | 91 | /* Capable of UltraDMA modes? */ |
91 | case 0x04: | 92 | ultra_mask = id->dma_ultra & hwif->ultra_mask; |
92 | if ((id->dma_ultra & 0x0040) && | 93 | |
93 | (id->dma_ultra & hwif->ultra_mask)) | 94 | if (!(id->field_valid & 4)) |
94 | { speed = XFER_UDMA_6; break; } | 95 | mode = 0; /* fallback to MW/SW DMA if no UltraDMA */ |
95 | case 0x03: | 96 | |
96 | if ((id->dma_ultra & 0x0020) && | 97 | switch (mode) { |
97 | (id->dma_ultra & hwif->ultra_mask)) | 98 | case 4: |
98 | { speed = XFER_UDMA_5; break; } | 99 | if (ultra_mask & 0x40) { |
99 | case 0x02: | 100 | speed = XFER_UDMA_6; |
100 | if ((id->dma_ultra & 0x0010) && | 101 | break; |
101 | (id->dma_ultra & hwif->ultra_mask)) | 102 | } |
102 | { speed = XFER_UDMA_4; break; } | 103 | case 3: |
103 | if ((id->dma_ultra & 0x0008) && | 104 | if (ultra_mask & 0x20) { |
104 | (id->dma_ultra & hwif->ultra_mask)) | 105 | speed = XFER_UDMA_5; |
105 | { speed = XFER_UDMA_3; break; } | 106 | break; |
106 | case 0x01: | 107 | } |
107 | if ((id->dma_ultra & 0x0004) && | 108 | case 2: |
108 | (id->dma_ultra & hwif->ultra_mask)) | 109 | if (ultra_mask & 0x10) { |
109 | { speed = XFER_UDMA_2; break; } | 110 | speed = XFER_UDMA_4; |
110 | if ((id->dma_ultra & 0x0002) && | 111 | break; |
111 | (id->dma_ultra & hwif->ultra_mask)) | 112 | } |
112 | { speed = XFER_UDMA_1; break; } | 113 | if (ultra_mask & 0x08) { |
113 | if ((id->dma_ultra & 0x0001) && | 114 | speed = XFER_UDMA_3; |
114 | (id->dma_ultra & hwif->ultra_mask)) | 115 | break; |
115 | { speed = XFER_UDMA_0; break; } | 116 | } |
116 | case 0x00: | 117 | case 1: |
117 | if ((id->dma_mword & 0x0004) && | 118 | if (ultra_mask & 0x04) { |
118 | (id->dma_mword & hwif->mwdma_mask)) | 119 | speed = XFER_UDMA_2; |
119 | { speed = XFER_MW_DMA_2; break; } | 120 | break; |
120 | if ((id->dma_mword & 0x0002) && | 121 | } |
121 | (id->dma_mword & hwif->mwdma_mask)) | 122 | if (ultra_mask & 0x02) { |
122 | { speed = XFER_MW_DMA_1; break; } | 123 | speed = XFER_UDMA_1; |
123 | if ((id->dma_mword & 0x0001) && | 124 | break; |
124 | (id->dma_mword & hwif->mwdma_mask)) | 125 | } |
125 | { speed = XFER_MW_DMA_0; break; } | 126 | if (ultra_mask & 0x01) { |
126 | if ((id->dma_1word & 0x0004) && | 127 | speed = XFER_UDMA_0; |
127 | (id->dma_1word & hwif->swdma_mask)) | 128 | break; |
128 | { speed = XFER_SW_DMA_2; break; } | 129 | } |
129 | if ((id->dma_1word & 0x0002) && | 130 | case 0: |
130 | (id->dma_1word & hwif->swdma_mask)) | 131 | mwdma_mask = id->dma_mword & hwif->mwdma_mask; |
131 | { speed = XFER_SW_DMA_1; break; } | ||
132 | if ((id->dma_1word & 0x0001) && | ||
133 | (id->dma_1word & hwif->swdma_mask)) | ||
134 | { speed = XFER_SW_DMA_0; break; } | ||
135 | } | ||
136 | 132 | ||
137 | // printk("%s: %s: mode 0x%02x, speed 0x%02x\n", | 133 | if (mwdma_mask & 0x04) { |
138 | // __FUNCTION__, drive->name, mode, speed); | 134 | speed = XFER_MW_DMA_2; |
135 | break; | ||
136 | } | ||
137 | if (mwdma_mask & 0x02) { | ||
138 | speed = XFER_MW_DMA_1; | ||
139 | break; | ||
140 | } | ||
141 | if (mwdma_mask & 0x01) { | ||
142 | speed = XFER_MW_DMA_0; | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | swdma_mask = id->dma_1word & hwif->swdma_mask; | ||
147 | |||
148 | if (swdma_mask & 0x04) { | ||
149 | speed = XFER_SW_DMA_2; | ||
150 | break; | ||
151 | } | ||
152 | if (swdma_mask & 0x02) { | ||
153 | speed = XFER_SW_DMA_1; | ||
154 | break; | ||
155 | } | ||
156 | if (swdma_mask & 0x01) { | ||
157 | speed = XFER_SW_DMA_0; | ||
158 | break; | ||
159 | } | ||
160 | } | ||
139 | 161 | ||
140 | return speed; | 162 | return speed; |
141 | } | 163 | } |
142 | |||
143 | EXPORT_SYMBOL(ide_dma_speed); | 164 | EXPORT_SYMBOL(ide_dma_speed); |
144 | 165 | ||
145 | 166 | ||