* libchip/ide/ata_internal.h, libchip/ide/ata.c: Moved code into
	separate functions.  Added public ata_breq_init(),
	ata_identify_device(), and ata_process_request_on_init_phase()
	functions.
This commit is contained in:
Sebastian Huber
2010-08-17 13:41:29 +00:00
parent 8b82bc3b41
commit f5194a9485
3 changed files with 223 additions and 171 deletions

View File

@@ -1,3 +1,10 @@
2010-08-17 Sebastian Huber <sebastian.huber@embedded-brains.de>
* libchip/ide/ata_internal.h, libchip/ide/ata.c: Moved code into
separate functions. Added public ata_breq_init(),
ata_identify_device(), and ata_process_request_on_init_phase()
functions.
2010-06-24 Arnout Vandecappelle <arnout@mind.be>
PR 1586/misc

View File

@@ -118,13 +118,6 @@ typedef bool preemption_key;
/* FIXME: case if ATA device is FLASH device need more attention */
#undef ATA_DEV_IS_FLASH_DISK
/* Block device request with a single buffer provided */
typedef struct blkdev_request1 {
rtems_blkdev_request req;
rtems_blkdev_sg_buffer sg[1];
} blkdev_request1;
/* Array indexed by controllers minor number */
static ata_ide_ctrl_t ata_ide_ctrls[IDE_CTRL_MAX_MINOR_NUMBER];
@@ -151,10 +144,6 @@ static rtems_chain_control ata_int_vec[ATA_MAX_RTEMS_INT_VEC_NUMBER + 1];
static void
ata_process_request(rtems_device_minor_number ctrl_minor);
static void
ata_process_request_on_init_phase(rtems_device_minor_number ctrl_minor,
ata_req_t *areq);
static void
ata_add_to_controller_queue(rtems_device_minor_number ctrl_minor,
ata_req_t *areq);
@@ -1037,6 +1026,97 @@ ata_ioctl(rtems_disk_device *dd, uint32_t cmd, void *argp)
return 0;
}
static void ata_execute_device_diagnostic(
rtems_device_minor_number ctrl_minor,
uint16_t *sector_buffer
)
{
#if ATA_EXEC_DEVICE_DIAGNOSTIC
ata_req_t areq;
blkdev_request1 breq;
ata_breq_init(&breq, sector_buffer);
/*
* Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is
* there any ATA device on the controller.
*
* This command may fail and it assumes we have a master device and may
* be a slave device. I think the identify command will handle
* detection better than this method.
*/
memset(&areq, 0, sizeof(ata_req_t));
areq.type = ATA_COMMAND_TYPE_NON_DATA;
areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
areq.regs.regs[IDE_REGISTER_COMMAND] =
ATA_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC;
areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);
areq.breq = (rtems_blkdev_request *)&breq;
/*
* Process the request. Special processing of requests on
* initialization phase is needed because at this moment there
* is no multitasking enviroment
*/
ata_process_request_on_init_phase(ctrl_minor, &areq);
/*
* check status of I/O operation
*/
if (breq.req.status == RTEMS_SUCCESSFUL)
{
/* disassemble returned diagnostic codes */
if (areq.info == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT)
{
printk("ATA: ctrl:%d: primary, secondary\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor,0).present = true;
ATA_DEV_INFO(ctrl_minor,1).present = true;
}
else if (areq.info == ATA_DEV0_PASSED_DEV1_FAILED)
{
printk("ATA: ctrl:%d: primary\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor,0).present = true;
ATA_DEV_INFO(ctrl_minor,1).present = false;
}
else if (areq.info < ATA_DEV1_PASSED_DEV0_FAILED)
{
printk("ATA: ctrl:%d: secondary\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor,0).present = false;
ATA_DEV_INFO(ctrl_minor,1).present = true;
}
else
{
printk("ATA: ctrl:%d: none\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor, 0).present = false;
ATA_DEV_INFO(ctrl_minor, 1).present = false;
}
/* refine the returned codes */
if (ATA_DEV_INFO(ctrl_minor, 1).present)
{
uint16_t ec = 0;
ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec);
if (ec & ATA_DEV1_PASSED_DEV0_FAILED)
{
printk("ATA: ctrl:%d: secondary inforced\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor, 1).present = true;
}
else
{
printk("ATA: ctrl:%d: secondary removed\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor, 1).present = false;
}
}
}
else
#endif
{
ATA_DEV_INFO(ctrl_minor, 0).present = true;
ATA_DEV_INFO(ctrl_minor,1).present = true;
}
}
/*
* ata_initialize --
* Initializes all ATA devices found on initialized IDE controllers.
@@ -1057,13 +1137,8 @@ rtems_ata_initialize(rtems_device_major_number major,
{
uint32_t ctrl_minor;
rtems_status_code status;
ata_req_t areq;
blkdev_request1 breq;
uint8_t i, dev = 0;
uint16_t *buffer;
#if ATA_EXEC_DEVICE_DIAGNOSTIC
uint16_t ec;
#endif
int i, dev = 0;
char name[ATA_MAX_NAME_LENGTH];
dev_t device;
ata_int_st_t *int_st;
@@ -1169,12 +1244,6 @@ rtems_ata_initialize(rtems_device_major_number major,
* requests should be formed; ATA requests contain block device request,
* so form block device request first
*/
memset(&breq, 0, sizeof(blkdev_request1));
breq.req.req_done = NULL;
breq.req.done_arg = &breq;
breq.req.bufnum = 1;
breq.req.bufs[0].length = ATA_SECTOR_SIZE;
breq.req.bufs[0].buffer = buffer;
/*
* for each presented IDE controller execute EXECUTE DEVICE DIAGNOSTIC
@@ -1267,160 +1336,30 @@ rtems_ata_initialize(rtems_device_major_number major,
IDE_REGISTER_DEVICE_CONTROL_nIEN);
}
#if ATA_EXEC_DEVICE_DIAGNOSTIC
/*
* Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is
* there any ATA device on the controller.
*
* This command may fail and it assumes we have a master device and may
* be a slave device. I think the identify command will handle
* detection better than this method.
*/
memset(&areq, 0, sizeof(ata_req_t));
areq.type = ATA_COMMAND_TYPE_NON_DATA;
areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
areq.regs.regs[IDE_REGISTER_COMMAND] =
ATA_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC;
areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);
areq.breq = (rtems_blkdev_request *)&breq;
/*
* Process the request. Special processing of requests on
* initialization phase is needed because at this moment there
* is no multitasking enviroment
*/
ata_process_request_on_init_phase(ctrl_minor, &areq);
/*
* check status of I/O operation
*/
if (breq.req.status == RTEMS_SUCCESSFUL)
{
/* disassemble returned diagnostic codes */
if (areq.info == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT)
{
printk("ATA: ctrl:%d: primary, secondary\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor,0).present = true;
ATA_DEV_INFO(ctrl_minor,1).present = true;
}
else if (areq.info == ATA_DEV0_PASSED_DEV1_FAILED)
{
printk("ATA: ctrl:%d: primary\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor,0).present = true;
ATA_DEV_INFO(ctrl_minor,1).present = false;
}
else if (areq.info < ATA_DEV1_PASSED_DEV0_FAILED)
{
printk("ATA: ctrl:%d: secondary\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor,0).present = false;
ATA_DEV_INFO(ctrl_minor,1).present = true;
}
else
{
printk("ATA: ctrl:%d: none\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor, 0).present = false;
ATA_DEV_INFO(ctrl_minor, 1).present = false;
}
/* refine the returned codes */
if (ATA_DEV_INFO(ctrl_minor, 1).present)
{
ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec);
if (ec & ATA_DEV1_PASSED_DEV0_FAILED)
{
printk("ATA: ctrl:%d: secondary inforced\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor, 1).present = true;
}
else
{
printk("ATA: ctrl:%d: secondary removed\n", ctrl_minor);
ATA_DEV_INFO(ctrl_minor, 1).present = false;
}
}
}
else
#endif
{
ATA_DEV_INFO(ctrl_minor, 0).present = true;
ATA_DEV_INFO(ctrl_minor,1).present = true;
}
ata_execute_device_diagnostic(ctrl_minor, buffer);
/* for each found ATA device obtain it configuration */
for (dev = 0; dev < 2; dev++)
if (ATA_DEV_INFO(ctrl_minor, dev).present)
{
/*
* Issue DEVICE IDENTIFY ATA command and get device
* configuration
*/
memset(&areq, 0, sizeof(ata_req_t));
areq.type = ATA_COMMAND_TYPE_PIO_IN;
areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
areq.regs.regs[IDE_REGISTER_COMMAND] =
ATA_COMMAND_IDENTIFY_DEVICE;
areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS);
areq.breq = (rtems_blkdev_request *)&breq;
status = ata_identify_device(
ctrl_minor,
dev,
buffer,
&ATA_DEV_INFO(ctrl_minor, dev));
if (status != RTEMS_SUCCESSFUL)
continue;
areq.cnt = breq.req.bufnum;
/*
* choose most appropriate ATA device data I/O speed supported
* by the controller
*/
status = ide_controller_config_io_speed(
ctrl_minor,
ATA_DEV_INFO(ctrl_minor, dev).modes_available);
if (status != RTEMS_SUCCESSFUL)
continue;
areq.regs.regs[IDE_REGISTER_DEVICE_HEAD] |=
(dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS);
/*
* Process the request. Special processing of requests on
* initialization phase is needed because at this moment there
* is no multitasking enviroment
*/
ata_process_request_on_init_phase(ctrl_minor, &areq);
/* check status of I/O operation */
if (breq.req.status != RTEMS_SUCCESSFUL)
continue;
/*
* Parse returned device configuration and fill in ATA internal
* device info structure
*/
ATA_DEV_INFO(ctrl_minor, dev).cylinders =
CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_CLNDS]);
ATA_DEV_INFO(ctrl_minor, dev).heads =
CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_HEADS]);
ATA_DEV_INFO(ctrl_minor, dev).sectors =
CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_SECS]);
ATA_DEV_INFO(ctrl_minor, dev).lba_sectors =
CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS1]);
ATA_DEV_INFO(ctrl_minor, dev).lba_sectors <<= 16;
ATA_DEV_INFO(ctrl_minor, dev).lba_sectors += CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS0]);
ATA_DEV_INFO(ctrl_minor, dev).lba_avaible =
(CF_LE_W(buffer[ATA_IDENT_WORD_CAPABILITIES]) >> 9) & 0x1;
if ((CF_LE_W(buffer[ATA_IDENT_WORD_FIELD_VALIDITY]) &
ATA_IDENT_BIT_VALID) == 0) {
/* no "supported modes" info -> use default */
ATA_DEV_INFO(ctrl_minor, dev).mode_active = ATA_MODES_PIO3;
}
else {
ATA_DEV_INFO(ctrl_minor, dev).modes_available =
((CF_LE_W(buffer[64]) & 0x1) ? ATA_MODES_PIO3 : 0) |
((CF_LE_W(buffer[64]) & 0x2) ? ATA_MODES_PIO4 : 0) |
((CF_LE_W(buffer[63]) & 0x1) ? ATA_MODES_DMA0 : 0) |
((CF_LE_W(buffer[63]) & 0x2) ?
ATA_MODES_DMA0 | ATA_MODES_DMA1 : 0) |
((CF_LE_W(buffer[63]) & 0x4) ?
ATA_MODES_DMA0 | ATA_MODES_DMA1 | ATA_MODES_DMA2 : 0);
if (ATA_DEV_INFO(ctrl_minor, dev).modes_available == 0)
continue;
/*
* choose most appropriate ATA device data I/O speed supported
* by the controller
*/
status = ide_controller_config_io_speed(
ctrl_minor,
ATA_DEV_INFO(ctrl_minor, dev).modes_available);
if (status != RTEMS_SUCCESSFUL)
continue;
}
/*
* Ok, let register new ATA device in the system
*/
@@ -1473,7 +1412,7 @@ rtems_ata_initialize(rtems_device_major_number major,
* RETURNS:
* NONE
*/
static void
void
ata_process_request_on_init_phase(rtems_device_minor_number ctrl_minor,
ata_req_t *areq)
{
@@ -1571,3 +1510,89 @@ ata_process_request_on_init_phase(rtems_device_minor_number ctrl_minor,
break;
}
}
void ata_breq_init(blkdev_request1 *breq, uint16_t *sector_buffer)
{
memset(breq, 0, sizeof(*breq));
breq->req.done_arg = breq;
breq->req.bufnum = 1;
breq->req.bufs [0].length = ATA_SECTOR_SIZE;
breq->req.bufs [0].buffer = sector_buffer;
}
rtems_status_code ata_identify_device(
rtems_device_minor_number ctrl_minor,
int dev,
uint16_t *sector_buffer,
ata_dev_t *device_entry
)
{
ata_req_t areq;
blkdev_request1 breq;
ata_breq_init(&breq, sector_buffer);
/*
* Issue DEVICE IDENTIFY ATA command and get device
* configuration
*/
memset(&areq, 0, sizeof(ata_req_t));
areq.type = ATA_COMMAND_TYPE_PIO_IN;
areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
areq.regs.regs [IDE_REGISTER_COMMAND] = ATA_COMMAND_IDENTIFY_DEVICE;
areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS);
areq.breq = (rtems_blkdev_request *)&breq;
areq.cnt = breq.req.bufnum;
areq.regs.regs [IDE_REGISTER_DEVICE_HEAD] |=
dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS;
/*
* Process the request. Special processing of requests on
* initialization phase is needed because at this moment there
* is no multitasking enviroment
*/
ata_process_request_on_init_phase(ctrl_minor, &areq);
/* check status of I/O operation */
if (breq.req.status != RTEMS_SUCCESSFUL) {
return RTEMS_IO_ERROR;
}
/*
* Parse returned device configuration and fill in ATA internal
* device info structure
*/
device_entry->cylinders =
CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_CLNDS]);
device_entry->heads =
CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_HEADS]);
device_entry->sectors =
CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_SECS]);
device_entry->lba_sectors =
CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS1]);
device_entry->lba_sectors <<= 16;
device_entry->lba_sectors += CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS0]);
device_entry->lba_avaible =
(CF_LE_W(sector_buffer[ATA_IDENT_WORD_CAPABILITIES]) >> 9) & 0x1;
if ((CF_LE_W(sector_buffer[ATA_IDENT_WORD_FIELD_VALIDITY]) &
ATA_IDENT_BIT_VALID) == 0) {
/* no "supported modes" info -> use default */
device_entry->mode_active = ATA_MODES_PIO3;
} else {
device_entry->modes_available =
((CF_LE_W(sector_buffer[64]) & 0x1) ? ATA_MODES_PIO3 : 0) |
((CF_LE_W(sector_buffer[64]) & 0x2) ? ATA_MODES_PIO4 : 0) |
((CF_LE_W(sector_buffer[63]) & 0x1) ? ATA_MODES_DMA0 : 0) |
((CF_LE_W(sector_buffer[63]) & 0x2) ?
ATA_MODES_DMA0 | ATA_MODES_DMA1 : 0) |
((CF_LE_W(sector_buffer[63]) & 0x4) ?
ATA_MODES_DMA0 | ATA_MODES_DMA1 | ATA_MODES_DMA2 : 0);
if (device_entry->modes_available == 0) {
return RTEMS_IO_ERROR;
}
}
return RTEMS_SUCCESSFUL;
}

View File

@@ -300,4 +300,24 @@ typedef struct ata_ide_ctrl_s {
rtems_chain_control reqs; /* requests chain */
} ata_ide_ctrl_t;
/* Block device request with a single buffer provided */
typedef struct blkdev_request1 {
rtems_blkdev_request req;
rtems_blkdev_sg_buffer sg[1];
} blkdev_request1;
void ata_breq_init(blkdev_request1 *breq, uint16_t *sector_buffer);
rtems_status_code ata_identify_device(
rtems_device_minor_number ctrl_minor,
int dev,
uint16_t *sector_buffer,
ata_dev_t *device_entry
);
void ata_process_request_on_init_phase(
rtems_device_minor_number ctrl_minor,
ata_req_t *areq
);
#endif /* __ATA_INTERNAL_H__ */