2 #include "ata_ide_drive.h"
4 #include <kernel/dev/arch/i386/ide/ide_bus.h>
5 #include <kernel/heap.h>
6 #include <kernel/debug.h>
7 #include <kernel/lock.h>
8 #define CB_DC_HD15 0x08 // bit should always be set to one
9 #define CB_DC_NIEN 0x02 // disable interrupts
11 #define CB_DH_DEV0 0xa0 // select device 0
12 #define CB_DH_DEV1 0xb0 // select device 1
17 // Most mandtory and optional ATA commands (from ATA-3),
19 #define CMD_CFA_ERASE_SECTORS 0xC0
20 #define CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
21 #define CMD_CFA_TRANSLATE_SECTOR 0x87
22 #define CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
23 #define CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
24 #define CMD_CHECK_POWER_MODE1 0xE5
25 #define CMD_CHECK_POWER_MODE2 0x98
26 #define CMD_DEVICE_RESET 0x08
27 #define CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
28 #define CMD_FLUSH_CACHE 0xE7
29 #define CMD_FORMAT_TRACK 0x50
30 #define CMD_IDENTIFY_DEVICE 0xEC
31 #define CMD_IDENTIFY_DEVICE_PACKET 0xA1
32 #define CMD_IDENTIFY_PACKET_DEVICE 0xA1
33 #define CMD_IDLE1 0xE3
34 #define CMD_IDLE2 0x97
35 #define CMD_IDLE_IMMEDIATE1 0xE1
36 #define CMD_IDLE_IMMEDIATE2 0x95
37 #define CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
38 #define CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
40 #define CMD_PACKET 0xA0
41 #define CMD_READ_BUFFER 0xE4
42 #define CMD_READ_DMA 0xC8
43 #define CMD_READ_DMA_QUEUED 0xC7
44 #define CMD_READ_MULTIPLE 0xC4
45 #define CMD_READ_SECTORS 0x20
46 #define CMD_READ_VERIFY_SECTORS 0x40
47 #define CMD_RECALIBRATE 0x10
49 #define CMD_SET_FEATURES 0xEF
50 #define CMD_SET_MULTIPLE_MODE 0xC6
51 #define CMD_SLEEP1 0xE6
52 #define CMD_SLEEP2 0x99
53 #define CMD_STANDBY1 0xE2
54 #define CMD_STANDBY2 0x96
55 #define CMD_STANDBY_IMMEDIATE1 0xE0
56 #define CMD_STANDBY_IMMEDIATE2 0x94
57 #define CMD_WRITE_BUFFER 0xE8
58 #define CMD_WRITE_DMA 0xCA
59 #define CMD_WRITE_DMA_QUEUED 0xCC
60 #define CMD_WRITE_MULTIPLE 0xC5
61 #define CMD_WRITE_SECTORS 0x30
62 #define CMD_WRITE_VERIFY 0x3C
66 #define CB_STAT_BSY 0x80 // busy
67 #define CB_STAT_RDY 0x40 // ready
68 #define CB_STAT_DF 0x20 // device fault
69 #define CB_STAT_WFT 0x20 // write fault (old name)
70 #define CB_STAT_SKC 0x10 // seek complete
71 #define CB_STAT_SERV 0x10 // service
72 #define CB_STAT_DRQ 0x08 // data request
73 #define CB_STAT_CORR 0x04 // corrected
74 #define CB_STAT_IDX 0x02 // index
75 #define CB_STAT_ERR 0x01 // error (ATA)
76 #define CB_STAT_CHK 0x01 // check (ATAPI)
79 #define ERR_EXPIRED_TIME_OUT -1
80 #define ERR_DISK_BUSY -2
81 #define ERR_HARDWARE_ERROR -3
82 #define ERR_DRQ_NOT_SET -4
83 #define ERR_TRANSMIT_BUFFER_NOT_EMPTY -5
84 #define ERR_DEVICE_FAULT -6
86 #define DRIVE_SUPPORT_LBA 0x0200
91 #define TRACE(x) dprintf x
96 #define STATUS_WAITING_INTR 1
98 typedef struct s_ata_command
115 ide_bus
*attached_bus
;
116 void *attached_bus_cookie
;
120 uint16 bytes_per_sector
;
121 ide_drive_info device_info
;
123 ata_command
*active_command
;
124 mutex interrupt_mutex
;
126 static void ide_reg_poll(ide_bus
*bus
, void *b_cookie
)
131 status
= bus
->get_alt_status(b_cookie
); // poll for not busy
132 if ( ( status
& CB_STAT_BSY
) == 0 )
136 static int convert_error(int error
)
138 if(error
& CB_STAT_BSY
)
139 return ERR_DISK_BUSY
;
140 if(error
& CB_STAT_DF
)
141 return ERR_DEVICE_FAULT
;
142 if(error
& CB_STAT_ERR
)
143 return ERR_HARDWARE_ERROR
;
149 static void signal_interrupt(void *b_cookie
,void *drive_cookie
)
151 ata_drive_cookie
*cookie
= drive_cookie
;
152 TRACE(("in signal interrupt status is %d\n",cookie
->status
));
153 if(cookie
->status
== STATUS_WAITING_INTR
)
155 TRACE(("unlock mutex\n"));
156 mutex_unlock(&cookie
->interrupt_mutex
);
159 int execute_command( ide_bus
*bus
, void *b_cookie
,ata_drive_cookie
*drive_cookie
,ata_command
*command
)
161 unsigned char devHead
;
162 unsigned char devCtrl
;
163 unsigned char cylLow
;
164 unsigned char cylHigh
;
165 unsigned char status
;
166 unsigned int wordCnt
;
168 uint16
*buffer
= (uint16
*)command
->output
;
170 if(command
->useInterrupt
==true)
171 devCtrl
= CB_DC_HD15
;
173 devCtrl
= CB_DC_HD15
| CB_DC_NIEN
;
174 devHead
= drive_cookie
->position
? CB_DH_DEV1
: CB_DH_DEV0
;
175 devHead
= devHead
| ( command
->head
& 0x4f );
176 cylLow
= command
->cyl
& 0x00ff;
177 cylHigh
= ( command
->cyl
& 0xff00 ) >> 8;
178 // these commands transfer only 1 sector
179 if (( command
->cmd
== CMD_IDENTIFY_DEVICE
)|| ( command
->cmd
== CMD_IDENTIFY_DEVICE_PACKET
)|| ( command
->cmd
== CMD_READ_BUFFER
)|| ( command
->cmd
== CMD_WRITE_BUFFER
))
180 command
->numSect
= 1;
181 // only Read Multiple uses multiCnt
182 if ( (command
->cmd
!= CMD_READ_MULTIPLE
) && ( command
->cmd
!= CMD_WRITE_MULTIPLE
) && ( command
->cmd
!= CMD_CFA_WRITE_MULTIPLE_WO_ERASE
))
183 command
->multiCnt
= 1;
185 if(command
->useInterrupt
)
187 drive_cookie
->active_command
= command
;
188 drive_cookie
->status
= STATUS_WAITING_INTR
;
190 if ( bus
->select_drive( b_cookie
,drive_cookie
->position
) )
192 return ERR_EXPIRED_TIME_OUT
;
194 bus
->write_register(b_cookie
, CB_DC
, devCtrl
);
195 bus
->write_register(b_cookie
, CB_FR
, command
->fr
);
196 bus
->write_register(b_cookie
, CB_SC
, command
->sc
);
197 bus
->write_register(b_cookie
, CB_SN
, command
->sect
);
198 bus
->write_register(b_cookie
, CB_CL
, cylLow
);
199 bus
->write_register(b_cookie
, CB_CH
, cylHigh
);
200 bus
->write_register(b_cookie
, CB_DH
, devHead
);
202 bus
->write_register(b_cookie
, CB_CMD
, command
->cmd
);
204 if(command
->useInterrupt
)
206 TRACE(("locking interrupt mutex\n"));
207 mutex_lock(&drive_cookie
->interrupt_mutex
);
208 TRACE(("entering wait loop\n"));
212 bus
->delay_on_bus(b_cookie
);
218 if(command
->useInterrupt
)
220 mutex_lock(&drive_cookie
->interrupt_mutex
);
221 mutex_unlock(&drive_cookie
->interrupt_mutex
);
224 ide_reg_poll(bus
,b_cookie
);
226 status
= bus
->get_alt_status(b_cookie
);
227 if ( ( status
& ( CB_STAT_BSY
| CB_STAT_DRQ
) ) == CB_STAT_DRQ
)
229 wordCnt
= command
->multiCnt
? command
->multiCnt
: 1;
230 if ( wordCnt
> command
->numSect
)
231 wordCnt
= command
->numSect
;
232 wordCnt
= wordCnt
* 256;
233 bus
->transfer_buffer( b_cookie
,CB_DATA
, buffer
, wordCnt
,command
->read
);
234 bus
->delay_on_bus(b_cookie
);
235 command
->numSect
= command
->numSect
- ( command
->multiCnt
? command
->multiCnt
: 1 );
240 if(command
->useInterrupt
)
242 mutex_lock(&drive_cookie
->interrupt_mutex
);
243 mutex_unlock(&drive_cookie
->interrupt_mutex
);
246 ide_reg_poll(bus
,b_cookie
);
247 status
= bus
->get_alt_status(b_cookie
);
249 error_code
= convert_error(status
);
252 if ( ( status
& CB_STAT_DRQ
) == 0 )
254 return ERR_DRQ_NOT_SET
;
256 if ( command
->numSect
< 1 )
258 status
= bus
->get_alt_status(b_cookie
);
259 error_code
= convert_error(status
);
262 if( status
& CB_STAT_DRQ
)
264 return ERR_TRANSMIT_BUFFER_NOT_EMPTY
;
266 break; // go to READ_DONE
269 drive_cookie
->status
= STATUS_IDLE
;
272 int execute_command_dma( ide_bus
*bus
, void *b_cookie
,ata_drive_cookie
*drive_cookie
, ata_command
*command
)
275 unsigned char devHead
;
276 unsigned char devCtrl
;
277 unsigned char cylLow
;
278 unsigned char cylHigh
;
279 unsigned char status
;
281 unsigned long lw1
, lw2
;
284 // setup register values
286 dprintf("entering execute_command_dma %X %X %X %X %X\n",bus
,b_cookie
,drive_cookie
,command
,command
->output
);
288 devHead
= drive_cookie
->position
? CB_DH_DEV1
: CB_DH_DEV0
;
289 devHead
= devHead
| ( command
->head
& 0x4f );
290 cylLow
= command
->cyl
& 0x00ff;
291 cylHigh
= ( command
->cyl
& 0xff00 ) >> 8;
293 // Quit now if the command is incorrect.
295 if ( ( command
->cmd
!= CMD_READ_DMA
) && ( command
->cmd
!= CMD_WRITE_DMA
) )
300 // set up the dma transfer(s)
305 drive_cookie
->active_command
= command
;
306 doTwo
= bus
->setup_dma(b_cookie
,command
->cmd
== CMD_WRITE_DMA
, ns
* 512L, command
->output
);
308 if ( bus
->select_drive( b_cookie
,drive_cookie
->position
) )
310 return ERR_EXPIRED_TIME_OUT
;
312 // Set up all the registers except the command register.
313 bus
->write_register(b_cookie
, CB_DC
, devCtrl
);
314 bus
->write_register(b_cookie
, CB_FR
, command
->fr
);
315 bus
->write_register(b_cookie
, CB_SC
, command
->sc
);
316 bus
->write_register(b_cookie
, CB_SN
, command
->sect
);
317 bus
->write_register(b_cookie
, CB_CL
, cylLow
);
318 bus
->write_register(b_cookie
, CB_CH
, cylHigh
);
319 bus
->write_register(b_cookie
, CB_DH
, devHead
);
321 bus
->write_register(b_cookie
, CB_CMD
, command
->cmd
);
322 drive_cookie
->status
= STATUS_WAITING_INTR
;
323 bus
->delay_on_bus(b_cookie
);
324 bus
->start_dma( b_cookie
);
325 dprintf("first lock\n");
326 mutex_lock(&drive_cookie
->interrupt_mutex
);
327 dprintf("second lock\n");
329 mutex_lock(&drive_cookie
->interrupt_mutex
);
330 mutex_unlock(&drive_cookie
->interrupt_mutex
);
331 return bus
->finish_dma(b_cookie
);
333 static void ide_string_conv (char *str
, int len
)
337 for (i
= 0; i
< len
/ sizeof (unsigned short); i
++)
340 str
[i
*2+1] = str
[i
*2];
345 for (j
= len
- 1; j
>= 0 && str
[j
] == ' '; j
--)
349 int ide_identify_device (ide_bus
*bus
, void *b_cookie
,ata_drive_cookie
*drive_cookie
,int bus_pos
)
355 buffer
= (uint8
*)&drive_cookie
->device_info
;
356 TRACE(("executing command\n"));
357 command
.cmd
= CMD_IDENTIFY_DEVICE
;
363 command
.output
= buffer
;
365 command
.multiCnt
= 0;
367 command
.useInterrupt
= false;
368 ret
= execute_command( bus
,b_cookie
,drive_cookie
,&command
);
369 TRACE(("executing command %d\n",ret
));
372 ide_string_conv(drive_cookie
->device_info
.model
,40);
373 drive_cookie
->sector_count
= drive_cookie
->device_info
.cyls
*drive_cookie
->device_info
.heads
*drive_cookie
->device_info
.sectors
;
374 drive_cookie
->bytes_per_sector
= 512;
375 drive_cookie
->lba_supported
= drive_cookie
->device_info
.capabilities
& DRIVE_SUPPORT_LBA
;
377 TRACE( ("ide: disk at bus %d, device %d %s\n", bus_pos
, drive_cookie
->position
,drive_cookie
->device_info
.model
));
378 TRACE(("ide/%d/%d: %dMB; %d cyl, %d head, %d sec, %d bytes/sec (LBA=%d)\n",bus_pos
, drive_cookie
->position
,
379 drive_cookie
->sector_count
* drive_cookie
->bytes_per_sector
/ 1024,
380 drive_cookie
->device_info
.cyls
,
381 drive_cookie
->device_info
.heads
,
382 drive_cookie
->device_info
.sectors
,
383 drive_cookie
->bytes_per_sector
,
384 drive_cookie
->lba_supported
388 static void *init_drive(ide_bus
*bus
,void *b_cookie
,int channel
,int drive
)
390 uint8 sc
,sn
,ch
,cl
,st
;
391 unsigned char devCtrl
= CB_DC_HD15
| CB_DC_NIEN
;
394 bus
->write_register(b_cookie
,CB_DC
,devCtrl
);
395 bus
->select_drive(b_cookie
,drive
);
396 bus
->delay_on_bus(b_cookie
);
398 bus
->write_register( b_cookie
,CB_SC
, 0x55 );
399 bus
->write_register( b_cookie
,CB_SN
, 0xaa );
400 bus
->write_register( b_cookie
,CB_SC
, 0xaa );
401 bus
->write_register( b_cookie
,CB_SN
, 0x55 );
402 bus
->write_register( b_cookie
,CB_SC
, 0x55 );
403 bus
->write_register( b_cookie
,CB_SN
, 0xaa );
404 sc
= bus
->read_register( b_cookie
,CB_SC
);
405 sn
= bus
->read_register( b_cookie
,CB_SN
);
406 if(sc
!=0x55 && sn
!=0xaa)
410 bus
->select_drive(b_cookie
,drive
);
411 bus
->delay_on_bus(b_cookie
);
412 bus
->reset_bus( b_cookie
,drive
);
413 bus
->select_drive(b_cookie
,drive
);
414 bus
->delay_on_bus(b_cookie
);
415 sc
= bus
->read_register( b_cookie
,CB_SC
);
416 sn
= bus
->read_register( b_cookie
,CB_SN
);
417 if ( ( sc
== 0x01 ) && ( sn
== 0x01 ) )
420 cl
= bus
->read_register( b_cookie
,CB_CL
);
421 ch
= bus
->read_register( b_cookie
,CB_CH
);
422 st
= bus
->read_register( b_cookie
,CB_STAT
);
423 if ( ( cl
== 0x14 ) && ( ch
== 0xeb ) )
426 if ( ( cl
== 0x00 ) && ( ch
== 0x00 ) && ( st
!= 0x00 ) )
428 ata_drive_cookie
*cookie
= kmalloc(sizeof(ata_drive_cookie
));
429 cookie
->attached_bus
= bus
;
430 cookie
->attached_bus_cookie
= b_cookie
;
431 cookie
->position
= drive
;
432 mutex_init(&cookie
->interrupt_mutex
,"test");
433 if(ide_identify_device(bus
,b_cookie
,cookie
,channel
)==0)
441 void ide_btochs(uint32 block
, ata_drive_cookie
*dev
, int *cylinder
, int *head
, int *sect
)
443 uint32 sav_block
= block
;
444 *sect
= (block
% dev
->device_info
.sectors
) + 1;
445 block
/= dev
->device_info
.sectors
;
446 *head
= (block
% dev
->device_info
.heads
) | (dev
->position
? DH_DRV1
: 0);
447 block
/= dev
->device_info
.heads
;
448 *cylinder
= block
& 0xFFFF;
449 TRACE(("ide_btochs: block %d -> cyl %d head %d sect %d\n", sav_block
, *cylinder
, *head
, *sect
));
451 void ide_btolba(uint32 block
, ata_drive_cookie
*dev
, int *cylinder
,int *head
, int *sect
)
453 uint32 sav_block
= block
;
454 *sect
= block
& 0xFF;
455 *cylinder
= (block
>> 8) & 0xFFFF;
456 *head
= ((block
>> 24) & 0xF) | ( dev
->position
? DH_DRV1
: 0) | DH_LBA
;
457 TRACE(("ide_btolba: block %d -> cyl %d head %d sect %d\n", sav_block
, *cylinder
, *head
, *sect
));
459 static int read_block(void *b_cookie
,void *d_cookie
,long block
,void *buffer
,size_t size
)
461 ata_drive_cookie
*drive_cookie
= d_cookie
;
462 ide_bus
*bus
= drive_cookie
->attached_bus
;
465 TRACE(("in read_blocks %x\n",block
));
466 if(drive_cookie
->lba_supported
==1)
467 ide_btolba(block
, drive_cookie
, &cyl
, &head
, §
);
469 ide_btochs(block
, drive_cookie
, &cyl
, &head
, §
);
471 TRACE(("about to read from %d %d %d\n",cyl
,head
,sect
));
477 command
.output
= buffer
;
478 command
.numSect
= size
;
479 command
.multiCnt
= 2;
481 command
.useInterrupt
= true;
482 if(drive_cookie
->attached_bus
->support_dma(b_cookie
)==true)
484 TRACE(("Will use DMA to transfer data\n"));
485 command
.cmd
= CMD_READ_DMA
;
486 return execute_command_dma( bus
,b_cookie
,drive_cookie
,&command
);
490 TRACE(("Will use PIO to transfer data\n"));
491 command
.cmd
= CMD_READ_SECTORS
;
492 return execute_command( bus
,b_cookie
,drive_cookie
,&command
);
495 static int write_block(void *b_cookie
,void *d_cookie
,long block
,const void *buffer
,size_t size
)
497 ata_drive_cookie
*drive_cookie
= d_cookie
;
498 ide_bus
*bus
= drive_cookie
->attached_bus
;
501 if(drive_cookie
->lba_supported
==1)
502 ide_btolba(block
, drive_cookie
, &cyl
, &head
, §
);
504 ide_btochs(block
, drive_cookie
, &cyl
, &head
, §
);
510 command
.output
= buffer
;
511 command
.numSect
= size
;
512 command
.multiCnt
= 2;
513 command
.read
= false;
514 command
.useInterrupt
= true;
516 if(drive_cookie
->attached_bus
->support_dma(b_cookie
)==true)
518 command
.cmd
= CMD_WRITE_DMA
;
519 return execute_command_dma( bus
,b_cookie
,drive_cookie
,&command
);
523 command
.cmd
= CMD_WRITE_SECTORS
;
524 return execute_command( bus
,b_cookie
,drive_cookie
,&command
);
528 static uint16
get_bytes_per_sector(void *d_cookie
)
530 ata_drive_cookie
*cookie
= d_cookie
;
531 return cookie
->bytes_per_sector
;
533 static int ioctl(void *b_cookie
,void *d_cookie
,int command
,void *buffer
,size_t size
)
535 ata_drive_cookie
*cookie
= d_cookie
;
541 /*if(size!=sizeof(device_information))
547 device_information *ret = (device_information*)buffer;
548 ret->bytes_per_sector = cookie->bytes_per_sector;
549 ret->sectors = cookie->sector_count;
550 ret->heads = cookie->device_info.heads;
551 ret->cylinders = cookie->device_info.cyls;
564 ide_drive ata_ide_drive
=
570 &get_bytes_per_sector
,