aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorSergei Shtylyov <sshtylyov@ru.mvista.com>2006-10-03 04:14:17 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-03 11:04:07 -0400
commit0750508ae6479d4ac6154b35c5b82929f31efb03 (patch)
tree28df59ad1701c407ecdd3b08295093dffc678eb2 /drivers/ide
parent83d7dbc4095a0c314b191c573be5fb4fa6ce0897 (diff)
[PATCH] ide_dma_speed() fixes
ide_dma_speed() fails to actually honor the IDE drivers' mode support masks) because of the bogus checks -- thus, selecting the DMA transfer mode that the driver explicitly refuses to support is possible. Additionally, there is no check for validity of the UltraDMA mode data in the drive ID, and the function is misdocumented. Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Cc: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/ide-lib.c125
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
81u8 ide_dma_speed(ide_drive_t *drive, u8 mode) 81u8 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
143EXPORT_SYMBOL(ide_dma_speed); 164EXPORT_SYMBOL(ide_dma_speed);
144 165
145 166