comparison packages/devs/disk/ide/current/src/ide_disk.c @ 2535:6ffeb2616b4b

* cdl/ide_disk.cdl: Rename of the devices to be /dev/idediskX/Y so that all disk drivers have unique device names. * cdl/ide_disk.cdl: * src/ide_diskc: Add a configurable startup delay to allow slow disks to initialize. Add support for 8-bit data path. Remove the identity check which are retired in the ATA standard. Optimize the read/write functions.
author asl
date Sun, 24 Aug 2008 12:55:41 +0000
parents 6d4c075d2939
children 74dbf4c3f2e1
comparison
equal deleted inserted replaced
2534:41a4df71f380 2535:6ffeb2616b4b
46 //####DESCRIPTIONEND#### 46 //####DESCRIPTIONEND####
47 // 47 //
48 //========================================================================== 48 //==========================================================================
49 49
50 #include <pkgconf/devs_disk_ide.h> 50 #include <pkgconf/devs_disk_ide.h>
51 #include <pkgconf/io_disk.h>
51 52
52 #include <cyg/infra/cyg_type.h> 53 #include <cyg/infra/cyg_type.h>
53 #include <cyg/infra/cyg_ass.h> 54 #include <cyg/infra/cyg_ass.h>
54 #include <cyg/infra/diag.h> 55 #include <cyg/infra/diag.h>
55 #include <cyg/hal/hal_arch.h> 56 #include <cyg/hal/hal_arch.h>
62 63
63 #include "ide_disk.h" 64 #include "ide_disk.h"
64 65
65 // ---------------------------------------------------------------------------- 66 // ----------------------------------------------------------------------------
66 67
67 //#define DEBUG 1 68 #ifdef CYGDBG_IO_DISK_DEBUG
69 # define DEBUG 1
70 #endif
68 71
69 #ifdef DEBUG 72 #ifdef DEBUG
70 # define D(fmt,args...) diag_printf(fmt, ## args) 73 # define D(fmt,args...) diag_printf(fmt, ## args)
71 #else 74 #else
72 # define D(fmt,args...) 75 # define D(fmt,args...)
92 95
93 #ifdef CYGVAR_DEVS_DISK_IDE_DISK3 96 #ifdef CYGVAR_DEVS_DISK_IDE_DISK3
94 IDE_DISK_INSTANCE(3, 1, 1, true, CYGDAT_IO_DISK_IDE_DISK3_NAME); 97 IDE_DISK_INSTANCE(3, 1, 1, true, CYGDAT_IO_DISK_IDE_DISK3_NAME);
95 #endif 98 #endif
96 99
100 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
101
97 // ---------------------------------------------------------------------------- 102 // ----------------------------------------------------------------------------
98 103
99 static void 104 static void
100 id_strcpy(char *dest, cyg_uint16 *src, cyg_uint16 size) 105 id_strcpy(char *dest, cyg_uint16 *src, cyg_uint16 size)
101 { 106 {
102 int i; 107 int i;
103 108
104 for (i = 0; i < size; i+=2) 109 for (i=0; i<size; i+=2) {
105 {
106 *dest++ = (char)(*src >> 8); 110 *dest++ = (char)(*src >> 8);
107 *dest++ = (char)(*src & 0x00FF); 111 *dest++ = (char)(*src & 0x00FF);
108 src++; 112 src++;
109 } 113 }
110 *dest = '\0'; 114 *dest = '\0';
119 do { 123 do {
120 HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status); 124 HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
121 } while (status & (IDE_STAT_BSY | IDE_STAT_DRQ)); 125 } while (status & (IDE_STAT_BSY | IDE_STAT_DRQ));
122 } 126 }
123 127
128 // ----------------------------------------------------------------------------
124 // Wait while the device is busy with the last command 129 // Wait while the device is busy with the last command
130
125 static inline int 131 static inline int
126 __wait_busy(int ctlr) 132 __wait_busy(int ctlr)
127 { 133 {
128 cyg_uint8 status; 134 cyg_uint8 status;
129 cyg_ucount32 tries; 135 cyg_ucount32 tries;
134 if ((status & IDE_STAT_BSY) == 0) 140 if ((status & IDE_STAT_BSY) == 0)
135 return 1; 141 return 1;
136 } 142 }
137 return 0; 143 return 0;
138 } 144 }
145
146 // ----------------------------------------------------------------------------
139 147
140 static inline int 148 static inline int
141 __wait_for_drq(int ctlr) 149 __wait_for_drq(int ctlr)
142 { 150 {
143 cyg_uint8 status; 151 cyg_uint8 status;
154 } 162 }
155 } 163 }
156 return 0; 164 return 0;
157 } 165 }
158 166
167 // ----------------------------------------------------------------------------
159 // Return true if any devices attached to controller 168 // Return true if any devices attached to controller
169
160 static int 170 static int
161 ide_presence_detect(int ctlr) 171 ide_presence_detect(int ctlr)
162 { 172 {
163 cyg_uint8 sel, val; 173 cyg_uint8 sel, val;
164 int i; 174 int i;
165 175
166 for (i = 0; i < 2; i++) { 176 for (i = 0; i < HAL_IDE_NUM_CONTROLLERS; i++) {
167 sel = (i << 4) | 0xA0; 177 sel = (i << 4) | 0xA0;
168 CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000); 178 CYGACC_CALL_IF_DELAY_US(50000U);
169 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, sel); 179 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, sel);
170 CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000); 180 CYGACC_CALL_IF_DELAY_US(50000U);
171 HAL_IDE_READ_UINT8(ctlr, IDE_REG_DEVICE, val); 181 HAL_IDE_READ_UINT8(ctlr, IDE_REG_DEVICE, val);
172 if (val == sel) { 182 if (val == sel) {
173 #ifndef CYGSEM_DEVS_DISK_IDE_VMWARE 183 #ifndef CYGSEM_DEVS_DISK_IDE_VMWARE
174 if (i) 184 if (i)
175 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, 0); 185 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, 0);
178 } 188 }
179 } 189 }
180 return 0; 190 return 0;
181 } 191 }
182 192
193 // ----------------------------------------------------------------------------
194
183 static int 195 static int
184 ide_reset(int ctlr) 196 ide_reset(int ctlr)
185 { 197 {
186 cyg_uint8 status; 198 cyg_uint8 status;
187 int delay; 199 int delay;
191 // the reset and setup functions were already done 203 // the reset and setup functions were already done
192 // by it's bios and complains if one uses reset here... 204 // by it's bios and complains if one uses reset here...
193 // 205 //
194 #ifndef CYGSEM_DEVS_DISK_IDE_VMWARE 206 #ifndef CYGSEM_DEVS_DISK_IDE_VMWARE
195 HAL_IDE_WRITE_CONTROL(ctlr, 6); // polled mode, reset asserted 207 HAL_IDE_WRITE_CONTROL(ctlr, 6); // polled mode, reset asserted
196 CYGACC_CALL_IF_DELAY_US(5000); 208 CYGACC_CALL_IF_DELAY_US(5000U);
197 HAL_IDE_WRITE_CONTROL(ctlr, 2); // polled mode, reset cleared 209 HAL_IDE_WRITE_CONTROL(ctlr, 2); // polled mode, reset cleared
198 CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000); 210 CYGACC_CALL_IF_DELAY_US(50000U);
199 #endif 211 #endif
200 212
201 // wait 30 seconds max for not busy and drive ready 213 // wait 30 seconds max for not busy and drive ready
202 for (delay = 0; delay < 300; ++delay) { 214 for (delay=0; delay<300; ++delay) {
203 CYGACC_CALL_IF_DELAY_US((cyg_uint32)100000); 215 CYGACC_CALL_IF_DELAY_US(100000U);
204 HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status); 216 HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, status);
205 if (!(status & IDE_STAT_BSY)) { 217 if (!(status & IDE_STAT_BSY)) {
206 if (status & IDE_STAT_DRDY) { 218 if (status & IDE_STAT_DRDY) {
207 return 1; 219 return 1;
208 } 220 }
209 } 221 }
210 } 222 }
211 return 0; 223 return 0;
212 } 224 }
213 225
226 // ----------------------------------------------------------------------------
227
214 static int 228 static int
215 ide_ident(int ctlr, int dev, cyg_uint16 *buf) 229 ide_ident(int ctlr, int dev, cyg_uint16 *buf)
216 { 230 {
217 int i; 231 int i;
218 232
219 if (!__wait_busy(ctlr)) { 233 if (!__wait_busy(ctlr))
220 return 0; 234 return 0;
221 } 235
222
223 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4); 236 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
224 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0xEC); 237 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0xEC);
225 CYGACC_CALL_IF_DELAY_US((cyg_uint32)50000); 238 CYGACC_CALL_IF_DELAY_US(50000U);
226 239
227 if (!__wait_for_drq(ctlr)) { 240 if (!__wait_for_drq(ctlr))
228 return 0; 241 return 0;
229 } 242
230 243 for (i=0; i<(CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE/sizeof(cyg_uint16));
231 for (i = 0; i < (CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE / sizeof(cyg_uint16)); 244 i++, buf++) {
232 i++, buf++) 245 HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *buf);
233 HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *buf); 246 }
234
235 return 1; 247 return 1;
236 } 248 }
249
250 // ----------------------------------------------------------------------------
251 // Requests the disk to use an 8-bit data path. This is probably ignored by
252 // most modern drives, but is supported by compact flash devices.
253
254 #ifdef CYGDAT_DEVS_DISK_IDE_8_BIT_DATA_PATH
255 static int
256 ide_8bit_mode(int ctlr, int dev, cyg_bool on)
257 {
258 cyg_uint8 stat;
259
260 if (!__wait_busy(ctlr))
261 return 0;
262
263 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, dev << 4);
264 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_FEATURES, 0x01);
265 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0xEF);
266
267 if (!__wait_busy(ctlr))
268 return 0;
269
270 HAL_IDE_READ_UINT8(ctlr, IDE_REG_STATUS, stat);
271 return (stat & 1) ? 0 : 1;
272 }
273 #endif
274
275 // ----------------------------------------------------------------------------
276 // Reads a group of contiguous sectors from the drive.
277 // It can read up to 256 sectors.
237 278
238 static int 279 static int
239 ide_read_sector(int ctlr, int dev, cyg_uint32 start, 280 ide_read_sector(int ctlr, int dev, cyg_uint32 start,
240 cyg_uint8 *buf, cyg_uint32 len) 281 cyg_uint8 *buf, cyg_uint32 len)
241 { 282 {
242 int j, c; 283 int i, nword;
243 cyg_uint16 p; 284 cyg_uint8 lenb;
244 cyg_uint8 * b=buf; 285 cyg_uint16 w;
245 286
246 if(!__wait_busy(ctlr)) { 287 if (len==0 || !__wait_busy(ctlr))
247 return 0; 288 return 0;
248 } 289
249 290 len = MIN(len, 256);
250 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, 1); // count =1 291 lenb = (len == 256) ? 0 : ((cyg_uint8) len);
292
293 nword = len * CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE / sizeof(cyg_uint16);
294
295 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, lenb);
251 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, start & 0xff); 296 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, start & 0xff);
252 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, (start >> 8) & 0xff); 297 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, (start >> 8) & 0xff);
253 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI, (start >> 16) & 0xff); 298 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI, (start >> 16) & 0xff);
254 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, 299 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE,
255 ((start >> 24) & 0xf) | (dev << 4) | 0x40); 300 ((start >> 24) & 0xf) | (dev << 4) | 0x40);
256 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0x20); 301 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0x20);
257 302
258 if (!__wait_for_drq(ctlr)) 303 if (!__wait_for_drq(ctlr))
259 return 0; 304 return 0;
260 // 305
261 // It would be fine if all buffers were word aligned, 306 if ((int) buf & 1) {
262 // but who knows 307 // Unaligned buffer, so split each word manually
263 // 308 for (i=0; i<nword; i++) {
264 for (j = 0, c=0 ; j < (CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE / sizeof(cyg_uint16)); 309 HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, w);
265 j++) { 310 *buf++ = w & 0xff;
266 HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, p); 311 *buf++ = (w>>8) & 0xff;
267 if (c++<(len*512)) *b++=p&0xff; 312 }
268 if (c++<(len*512)) *b++=(p>>8)&0xff; 313 }
269 } 314 else {
270 return 1; 315 cyg_uint16* wbuf = (cyg_uint16*) buf;
271 } 316 for (i=0; i<nword; i++, wbuf++)
317 HAL_IDE_READ_UINT16(ctlr, IDE_REG_DATA, *wbuf);
318 }
319 return (int) len;
320 }
321
322 // ----------------------------------------------------------------------------
323 // Writes a group of contiguous sectors to the drive.
324 // It can write up to 256 sectors.
272 325
273 static int 326 static int
274 ide_write_sector(int ctlr, int dev, cyg_uint32 start, 327 ide_write_sector(int ctlr, int dev, cyg_uint32 start,
275 cyg_uint8 *buf, cyg_uint32 len) 328 cyg_uint8 *buf, cyg_uint32 len)
276 { 329 {
277 int j, c; 330 int i, nword;
278 cyg_uint16 p; 331 cyg_uint8 lenb;
279 cyg_uint8 * b=buf; 332 cyg_uint16 w;
280 333
281 if(!__wait_busy(ctlr)) { 334 if (len==0 || !__wait_busy(ctlr))
282 return 0; 335 return 0;
283 } 336
284 337 len = MIN(len, 256);
285 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, 1); // count =1 338 lenb = (len == 256) ? 0 : ((cyg_uint8) len);
339
340 nword = len * CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE / sizeof(cyg_uint16);
341
342 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COUNT, lenb);
286 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, start & 0xff); 343 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBALOW, start & 0xff);
287 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, (start >> 8) & 0xff); 344 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAMID, (start >> 8) & 0xff);
288 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI, (start >> 16) & 0xff); 345 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_LBAHI, (start >> 16) & 0xff);
289 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE, 346 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_DEVICE,
290 ((start >> 24) & 0xf) | (dev << 4) | 0x40); 347 ((start >> 24) & 0xf) | (dev << 4) | 0x40);
291 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0x30); 348 HAL_IDE_WRITE_UINT8(ctlr, IDE_REG_COMMAND, 0x30);
292 349
293 if (!__wait_for_drq(ctlr)) 350 if (!__wait_for_drq(ctlr))
294 return 0; 351 return 0;
295 // 352
296 // It would be fine if all buffers were word aligned, 353 if ((int) buf & 1) {
297 // but who knows 354 // Unaligned buffer, so assemble each word manually
298 // 355 for (i=0; i<nword; ++i) {
299 for (j = 0, c=0 ; j < (CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE / sizeof(cyg_uint16)); 356 w = *buf++;
300 j++) { 357 w |= (cyg_uint16) (*buf++) << 8;
301 p = (c++<(len*512)) ? *b++ : 0; 358 HAL_IDE_WRITE_UINT16(ctlr, IDE_REG_DATA, w);
302 p |= (c++<(len*512)) ? (*b++<<8) : 0; 359 }
303 HAL_IDE_WRITE_UINT16(ctlr, IDE_REG_DATA, p); 360 }
304 } 361 else {
305 return 1; 362 cyg_uint16* wbuf = (cyg_uint16*) buf;
363 for (i=0; i<nword; ++i)
364 HAL_IDE_WRITE_UINT16(ctlr, IDE_REG_DATA, *wbuf++);
365 }
366 return (int) len;
306 } 367 }
307 368
308 // ---------------------------------------------------------------------------- 369 // ----------------------------------------------------------------------------
309 370
310 static cyg_bool 371 static cyg_bool
326 if (!num_controllers) num_controllers=HAL_IDE_INIT(); 387 if (!num_controllers) num_controllers=HAL_IDE_INIT();
327 if (info->chan>=num_controllers) { 388 if (info->chan>=num_controllers) {
328 D("No IDE controller for channel %d:%d\n", info->port, info->chan); 389 D("No IDE controller for channel %d:%d\n", info->port, info->chan);
329 return false; 390 return false;
330 } 391 }
392
393 #if CYGDAT_DEVS_DISK_IDE_STARTUP_DELAY
394 CYGACC_CALL_IF_DELAY_US(CYGDAT_DEVS_DISK_IDE_STARTUP_DELAY*1000U);
395 #endif
396
331 if (!ide_present[info->port]) { 397 if (!ide_present[info->port]) {
332 ide_present[info->port]=ide_presence_detect(info->port); 398 ide_present[info->port]=ide_presence_detect(info->port);
333 if (!ide_present[info->port]) { 399 if (!ide_present[info->port]) {
334 diag_printf("No devices on IDE controller #%d\n",info->port); 400 diag_printf("No devices on IDE controller #%d\n",info->port);
335 return false; 401 return false;
340 if (!ide_reset_done[info->port]) { 406 if (!ide_reset_done[info->port]) {
341 D("Controller #%d reset failure\n",info->port); 407 D("Controller #%d reset failure\n",info->port);
342 return false; 408 return false;
343 } 409 }
344 } 410 }
411
412 #ifdef CYGDAT_DEVS_DISK_IDE_8_BIT_DATA_PATH
413 if (!ide_8bit_mode(info->port, info->chan, true)) {
414 D("IDE disk %d:%d failed to enter 8-bit mode\n",
415 info->port, info->chan);
416 }
417 #endif
345 418
346 D("IDE %d:%d identify drive\n", info->port, info->chan); 419 D("IDE %d:%d identify drive\n", info->port, info->chan);
347 420
348 if (!ide_ident(info->port, info->chan, (cyg_uint16 *)id_buf)) { 421 if (!ide_ident(info->port, info->chan, (cyg_uint16 *)id_buf)) {
349 diag_printf("IDE %d:%d ident DRQ error\n", info->port, info->chan); 422 diag_printf("IDE %d:%d ident DRQ error\n", info->port, info->chan);
350 return false; 423 return false;
351 } 424 }
352 425
353 id_strcpy(ident.serial, ide_idData->serial, 20); 426 id_strcpy(ident.serial, ide_idData->serial, 20);
354 id_strcpy(ident.firmware_rev, ide_idData->firmware_rev, 8); 427 id_strcpy(ident.firmware_rev, ide_idData->firmware_rev, 8);
355 id_strcpy(ident.model_num, ide_idData->model_num, 40); 428 id_strcpy(ident.model_num, ide_idData->model_num, 40);
356 429
357 ident.cylinders_num = ide_idData->num_cylinders; 430 ident.cylinders_num = ide_idData->num_cylinders;
358 ident.heads_num = ide_idData->num_heads; 431 ident.heads_num = ide_idData->num_heads;
359 ident.sectors_num = ide_idData->num_sectors; 432 ident.sectors_num = ide_idData->num_sectors;
360 ident.lba_sectors_num = ide_idData->lba_total_sectors[1] << 16 | 433 ident.lba_sectors_num = ide_idData->lba_total_sectors[1] << 16 |
361 ide_idData->lba_total_sectors[0]; 434 ide_idData->lba_total_sectors[0];
362 ident.phys_block_size = 1; 435 ident.phys_block_size = 1;
436
437 // TODO: Should this be CYGDAT_DEVS_DISK_IDE_SECTOR_SIZE?
363 ident.max_transfer = 512; 438 ident.max_transfer = 512;
364 439
365 D("\tSerial : %s\n", ident.serial); 440 D("\tSerial : %s\n", ident.serial);
366 D("\tFirmware rev. : %s\n", ident.firmware_rev); 441 D("\tFirmware rev. : %s\n", ident.firmware_rev);
367 D("\tModel : %s\n", ident.model_num); 442 D("\tModel : %s\n", ident.model_num);
368 D("\tC/H/S : %d/%d/%d\n", ident.cylinders_num, 443 D("\tC/H/S : %d/%d/%d\n", ident.cylinders_num,
369 ident.heads_num, ident.sectors_num); 444 ident.heads_num, ident.sectors_num);
370 D("\tKind : %x\n", (ide_idData->general_conf>>8)&0x1f); 445
371
372 if (((ide_idData->general_conf>>8)&0x1f)!=2) {
373 diag_printf("IDE device %d:%d is not a hard disk!\n",
374 info->port, info->chan);
375 return false;
376 }
377 if (!(chan->callbacks->disk_init)(tab)) 446 if (!(chan->callbacks->disk_init)(tab))
378 return false; 447 return false;
379 448
380 if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident)) 449 if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident))
381 return false; 450 return false;