2 * Copyright (c) 2012 Petr Jerman
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * AHCI SATA driver implementation.
37 #include <ddf/interrupt.h>
39 #include <device/hw_res_parsed.h>
40 #include <device/pci.h>
44 #include <ahci_iface.h>
47 #include "ahci_sata.h"
51 #define AHCI_TIMER_TICKS 1000000000
54 ((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
57 ((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
59 static int ahci_get_sata_device_name(ddf_fun_t
*, size_t, char *);
60 static int ahci_get_num_blocks(ddf_fun_t
*, uint64_t *);
61 static int ahci_get_block_size(ddf_fun_t
*, size_t *);
62 static int ahci_read_blocks(ddf_fun_t
*, uint64_t, size_t, void *);
63 static int ahci_write_blocks(ddf_fun_t
*, uint64_t, size_t, void *);
65 static int ahci_identify_device(sata_dev_t
*);
66 static int ahci_set_highest_ultra_dma_mode(sata_dev_t
*);
67 static int ahci_rb_fpdma(sata_dev_t
*, void *, uint64_t);
68 static int ahci_wb_fpdma(sata_dev_t
*, void *, uint64_t);
70 static void ahci_sata_devices_create(ahci_dev_t
*, ddf_dev_t
*);
71 static ahci_dev_t
*ahci_ahci_create(ddf_dev_t
*);
72 static void ahci_ahci_init(ahci_dev_t
*);
74 static int ahci_dev_add(ddf_dev_t
*);
76 static void ahci_get_model_name(uint16_t *, char *);
77 static int ahci_pciintel_enable_interrupt(int);
79 static fibril_mutex_t sata_devices_count_lock
;
80 static int sata_devices_count
= 0;
82 /*----------------------------------------------------------------------------*/
83 /*-- AHCI Interface ----------------------------------------------------------*/
84 /*----------------------------------------------------------------------------*/
86 static ahci_iface_t ahci_interface
= {
87 .get_sata_device_name
= &ahci_get_sata_device_name
,
88 .get_num_blocks
= &ahci_get_num_blocks
,
89 .get_block_size
= &ahci_get_block_size
,
90 .read_blocks
= &ahci_read_blocks
,
91 .write_blocks
= &ahci_write_blocks
94 static ddf_dev_ops_t ahci_ops
= {
95 .interfaces
[AHCI_DEV_IFACE
] = &ahci_interface
98 static driver_ops_t driver_ops
= {
99 .dev_add
= &ahci_dev_add
102 static driver_t ahci_driver
= {
104 .driver_ops
= &driver_ops
107 static int ahci_get_sata_device_name(ddf_fun_t
*fun
,
108 size_t sata_dev_name_length
, char *sata_dev_name
)
110 sata_dev_t
*sata
= (sata_dev_t
*) fun
->driver_data
;
111 str_cpy(sata_dev_name
, sata_dev_name_length
, sata
->model
);
115 static int ahci_get_num_blocks(ddf_fun_t
*fun
, uint64_t *num_blocks
)
117 sata_dev_t
*sata
= (sata_dev_t
*) fun
->driver_data
;
118 *num_blocks
= sata
->blocks
;
122 static int ahci_get_block_size(ddf_fun_t
*fun
, size_t *block_size
)
124 sata_dev_t
*sata
= (sata_dev_t
*) fun
->driver_data
;
125 *block_size
= sata
->block_size
;
129 static int ahci_read_blocks(ddf_fun_t
*fun
, uint64_t blocknum
,
130 size_t count
, void *buf
)
133 sata_dev_t
*sata
= (sata_dev_t
*) fun
->driver_data
;
138 dmamem_map_anonymous(sata
->block_size
, AS_AREA_READ
| AS_AREA_WRITE
,
139 0, &phys
, (void **) &ibuf
);
140 bzero(buf
, sata
->block_size
);
142 fibril_mutex_lock(&sata
->lock
);
144 for (size_t cur
= 0; cur
< count
; cur
++) {
145 rc
= ahci_rb_fpdma(sata
, phys
, blocknum
+ cur
);
149 memcpy((void *) (((uint8_t *) buf
) + (sata
->block_size
* cur
)),
150 ibuf
, sata
->block_size
);
153 fibril_mutex_unlock(&sata
->lock
);
154 dmamem_unmap_anonymous(ibuf
);
159 static int ahci_write_blocks(ddf_fun_t
*fun
, uint64_t blocknum
,
160 size_t count
, void *buf
)
163 sata_dev_t
*sata
= (sata_dev_t
*) fun
->driver_data
;
168 dmamem_map_anonymous(sata
->block_size
, AS_AREA_READ
| AS_AREA_WRITE
,
169 0, &phys
, (void **) &ibuf
);
171 fibril_mutex_lock(&sata
->lock
);
173 for (size_t cur
= 0; cur
< count
; cur
++) {
174 memcpy(ibuf
, (void *) (((uint8_t *) buf
) + (sata
->block_size
* cur
)),
176 rc
= ahci_wb_fpdma(sata
, phys
, blocknum
+ cur
);
181 fibril_mutex_unlock(&sata
->lock
);
182 dmamem_unmap_anonymous(ibuf
);
186 /*----------------------------------------------------------------------------*/
187 /*-- AHCI Commands -----------------------------------------------------------*/
188 /*----------------------------------------------------------------------------*/
190 static void ahci_identify_device_cmd(sata_dev_t
*sata
, void *phys
)
192 volatile std_command_frame_t
*cmd
=
193 (std_command_frame_t
*) sata
->cmd_table
;
195 cmd
->fis_type
= 0x27;
202 cmd
->features_upper
= 0;
208 volatile ahci_cmd_prdt_t
*prdt
=
209 (ahci_cmd_prdt_t
*) (&sata
->cmd_table
[0x20]);
211 prdt
->data_address_low
= LO(phys
);
212 prdt
->data_address_upper
= HI(phys
);
218 sata
->cmd_header
->prdtl
= 1;
219 sata
->cmd_header
->flags
= 0x402;
220 sata
->cmd_header
->bytesprocessed
= 0;
222 sata
->port
->pxsact
|= 1;
223 sata
->port
->pxci
|= 1;
226 static void ahci_identify_packet_device_cmd(sata_dev_t
*sata
, void *phys
)
228 volatile std_command_frame_t
*cmd
=
229 (std_command_frame_t
*) sata
->cmd_table
;
231 cmd
->fis_type
= 0x27;
238 cmd
->features_upper
= 0;
244 volatile ahci_cmd_prdt_t
*prdt
=
245 (ahci_cmd_prdt_t
*) (&sata
->cmd_table
[0x20]);
247 prdt
->data_address_low
= LO(phys
);
248 prdt
->data_address_upper
= HI(phys
);
254 sata
->cmd_header
->prdtl
= 1;
255 sata
->cmd_header
->flags
= 0x402;
256 sata
->cmd_header
->bytesprocessed
= 0;
258 sata
->port
->pxsact
|= 1;
259 sata
->port
->pxci
|= 1;
262 static int ahci_identify_device(sata_dev_t
*sata
)
264 if (sata
->invalid_device
) {
266 "Identify command device on invalid device");
271 identify_data_t
*idata
;
273 dmamem_map_anonymous(512, AS_AREA_READ
| AS_AREA_WRITE
, 0, &phys
,
277 fibril_mutex_lock(&sata
->lock
);
279 ahci_identify_device_cmd(sata
, phys
);
281 fibril_mutex_lock(&sata
->event_lock
);
282 fibril_condvar_wait(&sata
->event_condvar
, &sata
->event_lock
);
283 fibril_mutex_unlock(&sata
->event_lock
);
285 ahci_port_is_t pxis
= sata
->shadow_pxis
;
286 sata
->shadow_pxis
.u32
&= ~pxis
.u32
;
288 if (sata
->invalid_device
) {
290 "Unrecoverable error during ata identify device");
294 if (ahci_port_is_tfes(pxis
)) {
295 ahci_identify_packet_device_cmd(sata
, phys
);
297 fibril_mutex_lock(&sata
->event_lock
);
298 fibril_condvar_wait(&sata
->event_condvar
, &sata
->event_lock
);
299 fibril_mutex_unlock(&sata
->event_lock
);
301 pxis
= sata
->shadow_pxis
;
302 sata
->shadow_pxis
.u32
&= ~pxis
.u32
;
304 if ((sata
->invalid_device
) || (ahci_port_is_error(pxis
))) {
306 "Unrecoverable error during ata identify packet device");
310 sata
->packet_device
= true;
312 sata
->packet_device
= false;
314 ahci_get_model_name(idata
->model_name
, sata
->model
);
317 * Due to QEMU limitation (as of 2012-06-22),
318 * only NCQ FPDMA mode is supported.
320 if ((idata
->sata_cap
& np_cap_ncq
) == 0) {
321 ddf_msg(LVL_ERROR
, "%s: NCQ must be supported", sata
->model
);
325 if (sata
->packet_device
) {
327 * Due to QEMU limitation (as of 2012-06-22),
328 * only NCQ FPDMA mode supported - block size is 512 B,
331 sata
->block_size
= 512;
334 sata
->block_size
= 512;
336 if ((idata
->caps
& rd_cap_lba
) == 0) {
337 ddf_msg(LVL_ERROR
, "%s: LBA for NCQ must be supported",
340 } else if ((idata
->cmd_set1
& cs1_addr48
) == 0) {
341 sata
->blocks
= (uint32_t) idata
->total_lba28_0
|
342 ((uint32_t) idata
->total_lba28_1
<< 16);
344 /* Device supports LBA-48 addressing. */
345 sata
->blocks
= (uint64_t) idata
->total_lba48_0
|
346 ((uint64_t) idata
->total_lba48_1
<< 16) |
347 ((uint64_t) idata
->total_lba48_2
<< 32) |
348 ((uint64_t) idata
->total_lba48_3
<< 48);
352 uint8_t udma_mask
= idata
->udma
& 0x007f;
353 if (udma_mask
== 0) {
355 "%s: UDMA mode for NCQ FPDMA mode must be supported",
359 for (unsigned int i
= 0; i
< 7; i
++) {
360 if (udma_mask
& (1 << i
))
361 sata
->highest_udma_mode
= i
;
365 fibril_mutex_unlock(&sata
->lock
);
366 dmamem_unmap_anonymous(idata
);
371 fibril_mutex_unlock(&sata
->lock
);
372 dmamem_unmap_anonymous(idata
);
377 static void ahci_set_mode_cmd(sata_dev_t
*sata
, void* phys
, uint8_t mode
)
379 volatile std_command_frame_t
*cmd
=
380 (std_command_frame_t
*) sata
->cmd_table
;
382 cmd
->fis_type
= 0x27;
385 cmd
->features
= 0x03;
389 cmd
->features_upper
= 0;
395 volatile ahci_cmd_prdt_t
* prdt
=
396 (ahci_cmd_prdt_t
*) (&sata
->cmd_table
[0x20]);
398 prdt
->data_address_low
= LO(phys
);
399 prdt
->data_address_upper
= HI(phys
);
405 sata
->cmd_header
->prdtl
= 1;
406 sata
->cmd_header
->flags
= 0x402;
407 sata
->cmd_header
->bytesprocessed
= 0;
409 sata
->port
->pxsact
|= 1;
410 sata
->port
->pxci
|= 1;
413 static int ahci_set_highest_ultra_dma_mode(sata_dev_t
*sata
)
415 if (sata
->invalid_device
) {
417 "%s: Setting highest UDMA mode on invalid device",
423 identify_data_t
*idata
;
425 dmamem_map_anonymous(512, AS_AREA_READ
| AS_AREA_WRITE
, 0, &phys
,
429 fibril_mutex_lock(&sata
->lock
);
431 uint8_t mode
= 0x40 | (sata
->highest_udma_mode
& 0x07);
432 ahci_set_mode_cmd(sata
, phys
, mode
);
434 fibril_mutex_lock(&sata
->event_lock
);
435 fibril_condvar_wait(&sata
->event_condvar
, &sata
->event_lock
);
436 fibril_mutex_unlock(&sata
->event_lock
);
438 ahci_port_is_t pxis
= sata
->shadow_pxis
;
439 sata
->shadow_pxis
.u32
&= ~pxis
.u32
;
441 if (sata
->invalid_device
) {
443 "%s: Unrecoverable error during set highest UDMA mode",
448 if (ahci_port_is_error(pxis
)) {
450 "%s: Error during set highest UDMA mode", sata
->model
);
454 fibril_mutex_unlock(&sata
->lock
);
455 dmamem_unmap_anonymous(idata
);
460 fibril_mutex_unlock(&sata
->lock
);
461 dmamem_unmap_anonymous(idata
);
466 static void ahci_rb_fpdma_cmd(sata_dev_t
*sata
, void *phys
, uint64_t blocknum
)
468 volatile ncq_command_frame_t
*cmd
=
469 (ncq_command_frame_t
*) sata
->cmd_table
;
471 cmd
->fis_type
= 0x27;
484 cmd
->sector_count_low
= 1;
485 cmd
->sector_count_high
= 0;
487 cmd
->lba0
= blocknum
& 0xff;
488 cmd
->lba1
= (blocknum
>> 8) & 0xff;
489 cmd
->lba2
= (blocknum
>> 16) & 0xff;
490 cmd
->lba3
= (blocknum
>> 24) & 0xff;
491 cmd
->lba4
= (blocknum
>> 32) & 0xff;
492 cmd
->lba5
= (blocknum
>> 40) & 0xff;
494 volatile ahci_cmd_prdt_t
*prdt
=
495 (ahci_cmd_prdt_t
*) (&sata
->cmd_table
[0x20]);
497 prdt
->data_address_low
= LO(phys
);
498 prdt
->data_address_upper
= HI(phys
);
500 prdt
->dbc
= sata
->block_size
- 1;
504 sata
->cmd_header
->prdtl
= 1;
505 sata
->cmd_header
->flags
= 0x405;
506 sata
->cmd_header
->bytesprocessed
= 0;
508 sata
->port
->pxsact
|= 1;
509 sata
->port
->pxci
|= 1;
512 static int ahci_rb_fpdma(sata_dev_t
*sata
, void *phys
, uint64_t blocknum
)
514 if (sata
->invalid_device
) {
516 "%s: FPDMA read from invalid device", sata
->model
);
520 ahci_rb_fpdma_cmd(sata
, phys
, blocknum
);
522 fibril_mutex_lock(&sata
->event_lock
);
523 fibril_condvar_wait(&sata
->event_condvar
, &sata
->event_lock
);
524 fibril_mutex_unlock(&sata
->event_lock
);
526 ahci_port_is_t pxis
= sata
->shadow_pxis
;
527 sata
->shadow_pxis
.u32
&= ~pxis
.u32
;
529 if ((sata
->invalid_device
) || (ahci_port_is_error(pxis
))_
{
531 "%s: Unrecoverable error during FPDMA read", sata
->model
);
538 static void ahci_wb_fpdma_cmd(sata_dev_t
*sata
, void *phys
, uint64_t blocknum
)
540 volatile ncq_command_frame_t
*cmd
=
541 (ncq_command_frame_t
*) sata
->cmd_table
;
543 cmd
->fis_type
= 0x27;
556 cmd
->sector_count_low
= 1;
557 cmd
->sector_count_high
= 0;
559 cmd
->lba0
= blocknum
& 0xff;
560 cmd
->lba1
= (blocknum
>> 8) & 0xff;
561 cmd
->lba2
= (blocknum
>> 16) & 0xff;
562 cmd
->lba3
= (blocknum
>> 24) & 0xff;
563 cmd
->lba4
= (blocknum
>> 32) & 0xff;
564 cmd
->lba5
= (blocknum
>> 40) & 0xff;
566 volatile ahci_cmd_prdt_t
* prdt
=
567 (ahci_cmd_prdt_t
*) (&sata
->cmd_table
[0x20]);
569 prdt
->data_address_low
= LO(phys
);
570 prdt
->data_address_upper
= HI(phys
);
572 prdt
->dbc
= sata
->block_size
- 1;
576 sata
->cmd_header
->prdtl
= 1;
577 sata
->cmd_header
->flags
= 0x445;
578 sata
->cmd_header
->bytesprocessed
= 0;
580 sata
->port
->pxsact
|= 1;
581 sata
->port
->pxci
|= 1;
584 static int ahci_wb_fpdma(sata_dev_t
*sata
, void *phys
, uint64_t blocknum
)
586 if (sata
->invalid_device
) {
588 "%s: FPDMA write to invalid device", sata
->model
);
592 ahci_wb_fpdma_cmd(sata
, phys
, blocknum
);
594 fibril_mutex_lock(&sata
->event_lock
);
595 fibril_condvar_wait(&sata
->event_condvar
, &sata
->event_lock
);
596 fibril_mutex_unlock(&sata
->event_lock
);
598 ahci_port_is_t pxis
= sata
->shadow_pxis
;
599 sata
->shadow_pxis
.u32
&= ~pxis
.u32
;
601 if ((sata
->invalid_device
) || (ahci_port_is_error(pxis
))) {
603 "%s: Unrecoverable error during fpdma write", sata
->model
);
610 /*----------------------------------------------------------------------------*/
611 /*-- Interrupts and timer unified handling -----------------------------------*/
612 /*----------------------------------------------------------------------------*/
614 static irq_pio_range_t ahci_ranges
[] = {
621 static irq_cmd_t ahci_cmds
[] = {
623 /* Disable interrupt - interrupt is deasserted in qemu 1.0.1 */
624 .cmd
= CMD_MEM_WRITE_32
,
626 .value
= AHCI_GHC_GHC_AE
629 /* Clear interrupt status register - for vbox and real hw */
630 .cmd
= CMD_MEM_REWRITE_32
,
638 /** Unified AHCI interrupt and timer interrupt handler.
640 * @param ahci AHCI device.
641 * @param is_timer Indicate timer interrupt.
644 static void ahci_interrupt_or_timer(ahci_dev_t
*ahci
, bool is_timer
)
647 * Get current value of hardware interrupt state register,
648 * clear hardware register (write to clear behavior).
652 is
.u32
= ahci
->memregs
->ghc
.is
;
653 ahci
->memregs
->ghc
.is
= is
.u32
;
654 is
.u32
= ahci
->memregs
->ghc
.is
;
656 uint32_t port_event_flags
= 0;
657 uint32_t port_mask
= 1;
658 for (unsigned int i
= 0; i
< 32; i
++) {
660 * Get current value of hardware port interrupt state register,
661 * clear hardware register (write to clear behavior).
665 pxis
.u32
= ahci
->memregs
->ports
[i
].pxis
;
666 ahci
->memregs
->ports
[i
].pxis
= pxis
.u32
;
668 sata_dev_t
*sata
= (sata_dev_t
*) ahci
->sata_devs
[i
];
670 /* add value to shadow copy of port interrupt state register. */
671 sata
->shadow_pxis
.u32
|= pxis
.u32
;
673 /* Evaluate port event. */
674 if ((ahci_port_is_end_of_operation(pxis
)) ||
675 (ahci_port_is_error(pxis
)))
676 port_event_flags
|= port_mask
;
678 if (ahci_port_is_permanent_error(pxis
))
679 sata
->invalid_device
= true;
686 for (unsigned int i
= 0; i
< 32; i
++) {
687 sata_dev_t
*sata
= (sata_dev_t
*) ahci
->sata_devs
[i
];
688 if ((port_event_flags
& port_mask
) && (sata
!= NULL
)) {
689 fibril_mutex_lock(&sata
->event_lock
);
690 fibril_condvar_signal(&sata
->event_condvar
);
691 fibril_mutex_unlock(&sata
->event_lock
);
698 /** AHCI timer interrupt handler.
700 * @param arg Pointer to AHCI device.
703 static void ahci_timer(void *arg
)
705 ahci_dev_t
*ahci
= (ahci_dev_t
*) arg
;
707 ahci_interrupt_or_timer(ahci
, 1);
708 fibril_timer_set(ahci
->timer
, AHCI_TIMER_TICKS
, ahci_timer
, ahci
);
711 /** AHCI interrupt handler.
713 * @param dev Pointer to device driver handler.
716 static void ahci_interrupt(ddf_dev_t
*dev
, ipc_callid_t iid
, ipc_call_t
*icall
)
718 ahci_dev_t
*ahci
= (ahci_dev_t
*) dev
->driver_data
;
720 ahci_interrupt_or_timer(ahci
, 0);
722 /* Enable interrupt. */
723 ahci
->memregs
->ghc
.ghc
|= 2;
726 /*----------------------------------------------------------------------------*/
727 /*-- AHCI and SATA device creating and initializing routines -----------------*/
728 /*----------------------------------------------------------------------------*/
730 static sata_dev_t
*ahci_sata_device_allocate(volatile ahci_port_t
*port
)
734 void* virt_fb
= NULL
;
735 void* virt_cmd
= NULL
;
736 void* virt_table
= NULL
;
738 sata_dev_t
*sata
= malloc(sizeof(sata_dev_t
));
742 bzero(sata
, sizeof(sata_dev_t
));
746 /* Allocate and init retfis structure. */
747 int rc
= dmamem_map_anonymous(size
, AS_AREA_READ
| AS_AREA_WRITE
, 0,
752 bzero(virt_fb
, size
);
753 sata
->port
->pxfbu
= HI(phys
);
754 sata
->port
->pxfb
= LO(phys
);
756 /* Allocate and init command header structure. */
757 rc
= dmamem_map_anonymous(size
, AS_AREA_READ
| AS_AREA_WRITE
, 0,
763 bzero(virt_cmd
, size
);
764 sata
->port
->pxclbu
= HI(phys
);
765 sata
->port
->pxclb
= LO(phys
);
766 sata
->cmd_header
= (ahci_cmdhdr_t
*) virt_cmd
;
768 /* Allocate and init command table structure. */
769 rc
= dmamem_map_anonymous(size
, AS_AREA_READ
| AS_AREA_WRITE
, 0,
775 bzero(virt_table
, size
);
776 sata
->cmd_header
->cmdtableu
= HI(phys
);
777 sata
->cmd_header
->cmdtable
= LO(phys
);
778 sata
->cmd_table
= (uint32_t*) virt_table
;
783 dmamem_unmap(virt_cmd
, size
);
785 dmamem_unmap(virt_fb
, size
);
791 * Deleting of pointers in memory hardware mapped register
792 * unneccessary, hardware port is not in operational state.
796 static int ahci_sata_device_create(ahci_dev_t
*ahci
, ddf_dev_t
*dev
,
797 volatile ahci_port_t
*port
, unsigned int port_num
)
799 ddf_fun_t
*fun
= NULL
;
800 sata_dev_t
*sata
= ahci_sata_device_allocate(port
);
805 /* Set pointers between SATA and AHCI structures. */
807 sata
->port_num
= port_num
;
808 ahci
->sata_devs
[port_num
] = sata
;
810 fibril_mutex_initialize(&sata
->lock
);
811 fibril_mutex_initialize(&sata
->event_lock
);
812 fibril_condvar_initialize(&sata
->event_condvar
);
814 /* Initialize SATA port operational registers. */
815 sata
->port
->pxis
= 0;
816 sata
->port
->pxie
= 0xffffffff;
817 sata
->port
->pxserr
= 0;
818 sata
->port
->pxcmd
|= 0x10;
819 sata
->port
->pxcmd
|= 0x01;
821 if (ahci_identify_device(sata
) != EOK
)
824 if (ahci_set_highest_ultra_dma_mode(sata
) != EOK
)
827 /* Add sata device to system. */
828 char sata_dev_name
[1024];
829 snprintf(sata_dev_name
, 1024, "ahci_%u", sata_devices_count
);
831 fibril_mutex_lock(&sata_devices_count_lock
);
832 sata_devices_count
++;
833 fibril_mutex_unlock(&sata_devices_count_lock
);
835 fun
= ddf_fun_create(dev
, fun_exposed
, sata_dev_name
);
837 ddf_msg(LVL_ERROR
, "Failed creating function.");
841 fun
->ops
= &ahci_ops
;
842 fun
->driver_data
= sata
;
843 int rc
= ddf_fun_bind(fun
);
845 ddf_msg(LVL_ERROR
, "Failed binding function.");
852 sata
->invalid_device
= true;
854 ddf_fun_destroy(fun
);
859 static void ahci_sata_devices_create(ahci_dev_t
*ahci
, ddf_dev_t
*dev
)
861 for (unsigned int port_num
= 0; port_num
< 32; port_num
++) {
862 /* Active ports only */
863 if (!(ahci
->memregs
->ghc
.pi
& (1 << port_num
)))
866 volatile ahci_port_t
*port
= ahci
->memregs
->ports
+ port_num
;
868 /* Active devices only */
869 if ((port
->pxssts
& 0x0f) != 3)
872 ahci_sata_device_create(ahci
, dev
, port
, port_num
);
876 static ahci_dev_t
*ahci_ahci_create(ddf_dev_t
*dev
)
878 ahci_dev_t
*ahci
= malloc(sizeof(ahci_dev_t
));
882 bzero(ahci
, sizeof(ahci_dev_t
));
886 hw_res_list_parsed_t hw_res_parsed
;
887 hw_res_list_parsed_init(&hw_res_parsed
);
888 if (hw_res_get_list_parsed(dev
->parent_sess
, &hw_res_parsed
, 0) != EOK
)
889 goto error_get_res_parsed
;
891 /* Register interrupt handler */
892 ahci_ranges
[0].base
= (size_t) hw_res_parsed
.mem_ranges
.ranges
[0].address
;
893 ahci_ranges
[0].size
= sizeof(ahci_dev_t
);
895 ((uint32_t *) (size_t) hw_res_parsed
.mem_ranges
.ranges
[0].address
) + 1;
897 ((uint32_t *) (size_t) hw_res_parsed
.mem_ranges
.ranges
[0].address
) + 2;
903 ct
.ranges
= ahci_ranges
;
905 int rc
= register_interrupt_handler(dev
, hw_res_parsed
.irqs
.irqs
[0],
906 ahci_interrupt
, &ct
);
909 ddf_msg(LVL_ERROR
, "Failed register_interrupt_handler function.");
910 goto error_register_interrupt_handler
;
913 if (ahci_pciintel_enable_interrupt(hw_res_parsed
.irqs
.irqs
[0]) != EOK
) {
914 ddf_msg(LVL_ERROR
, "Failed enable interupt.");
915 goto error_enable_interrupt
;
918 /* Map AHCI register. */
919 physmem_map((void *) (size_t) (hw_res_parsed
.mem_ranges
.ranges
[0].address
),
920 8, AS_AREA_READ
| AS_AREA_WRITE
, (void **) &ahci
->memregs
);
921 hw_res_list_parsed_clean(&hw_res_parsed
);
923 if (ahci
->memregs
== NULL
)
924 goto error_map_registers
;
926 ahci
->timer
= fibril_timer_create();
931 error_enable_interrupt
:
932 error_register_interrupt_handler
:
933 hw_res_list_parsed_clean(&hw_res_parsed
);
934 error_get_res_parsed
:
938 static void ahci_ahci_init(ahci_dev_t
*ahci
)
940 /* Enable interrupt and bus mastering */
941 ahci_pcireg_cmd_t cmd
;
943 pci_config_space_read_16(ahci
->dev
->parent_sess
, AHCI_PCI_CMD
, &cmd
.u16
);
946 pci_config_space_write_16(ahci
->dev
->parent_sess
, AHCI_PCI_CMD
, cmd
.u16
);
948 /* Set master latency timer */
949 pci_config_space_write_8(ahci
->dev
->parent_sess
, AHCI_PCI_MLT
, 32);
951 /* Disable command completion coalescing feature. */
952 ahci_ghc_ccc_ctl_t ccc
;
953 ccc
.u32
= ahci
->memregs
->ghc
.ccc_ctl
;
955 ahci
->memregs
->ghc
.ccc_ctl
= ccc
.u32
;
957 /* Enable AHCI and interrupt. */
958 ahci
->memregs
->ghc
.ghc
= AHCI_GHC_GHC_AE
| AHCI_GHC_GHC_IE
;
961 fibril_timer_set(ahci
->timer
, AHCI_TIMER_TICKS
, ahci_timer
, ahci
);
964 static int ahci_dev_add(ddf_dev_t
*dev
)
966 dev
->parent_sess
= devman_parent_device_connect(EXCHANGE_SERIALIZE
,
967 dev
->handle
, IPC_FLAG_BLOCKING
);
968 if (dev
->parent_sess
== NULL
)
971 ahci_dev_t
*ahci
= ahci_ahci_create(dev
);
975 dev
->driver_data
= ahci
;
976 ahci_ahci_init(ahci
);
977 ahci_sata_devices_create(ahci
, dev
);
982 /*----------------------------------------------------------------------------*/
983 /*-- Helpers and utilities ---------------------------------------------------*/
984 /*----------------------------------------------------------------------------*/
986 static void ahci_get_model_name(uint16_t *src
, char *dst
)
991 for (unsigned int i
= 0; i
< 20; i
++) {
993 model
[2 * i
] = w
>> 8;
994 model
[2 * i
+ 1] = w
& 0x00ff;
998 while ((len
> 0) && (model
[len
- 1] == 0x20))
1002 for (unsigned int i
= 0; i
< len
; i
++) {
1003 uint8_t c
= model
[i
];
1007 chr_encode(c
, dst
, &pos
, 40);
1013 static int ahci_pciintel_enable_interrupt(int irq
)
1015 async_sess_t
*irc_sess
= NULL
;
1016 irc_sess
= service_connect_blocking(EXCHANGE_SERIALIZE
, SERVICE_IRC
, 0, 0);
1021 async_exch_t
*exch
= async_exchange_begin(irc_sess
);
1022 const int rc
= async_req_1_0(exch
, IRC_ENABLE_INTERRUPT
, irq
);
1023 async_exchange_end(exch
);
1025 async_hangup(irc_sess
);
1029 /*----------------------------------------------------------------------------*/
1030 /*-- AHCI Main routine -------------------------------------------------------*/
1031 /*----------------------------------------------------------------------------*/
1033 int main(int argc
, char *argv
[])
1035 printf("%s: HelenOS AHCI device driver\n", NAME
);
1036 ddf_log_init(NAME
, LVL_ERROR
);
1037 fibril_mutex_initialize(&sata_devices_count_lock
);
1038 return ddf_driver_main(&ahci_driver
);