From c58791932fa147f595ecb662c08e53a1cfbe4925 Mon Sep 17 00:00:00 2001 From: Ralf Corsepius Date: Thu, 4 Dec 2003 14:19:05 +0000 Subject: 2003-12-04 Ralf Corsepius * src/ata.c: Remove. --- cpukit/libblock/ChangeLog | 4 + cpukit/libblock/src/ata.c | 1321 --------------------------------------------- 2 files changed, 4 insertions(+), 1321 deletions(-) delete mode 100644 cpukit/libblock/src/ata.c (limited to 'cpukit/libblock') diff --git a/cpukit/libblock/ChangeLog b/cpukit/libblock/ChangeLog index 7c541a4935..2b73912853 100644 --- a/cpukit/libblock/ChangeLog +++ b/cpukit/libblock/ChangeLog @@ -1,3 +1,7 @@ +2003-12-04 Ralf Corsepius + + * src/ata.c: Remove. + 2003-11-30 Ralf Corsepius * Makefile.am: Add $(dirstamp) to compilation rules. diff --git a/cpukit/libblock/src/ata.c b/cpukit/libblock/src/ata.c deleted file mode 100644 index 457bc27824..0000000000 --- a/cpukit/libblock/src/ata.c +++ /dev/null @@ -1,1321 +0,0 @@ -/* - * ata.c - * - * ATA RTEMS driver. ATA driver is hardware independant implementation of - * ATA-2 standart, working draft X3T10/0948D, revision 4c. ATA driver bases - * on RTEMS IDE controller driver. - * - * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia - * Authors: Eugeny S. Mints - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.com/license/LICENSE. - * - * $Id$ - * - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include /* for "memset" declaration */ - -#include -#include -#include -#include -#include -#include - -#define DEBUG - -#ifdef DEBUG -#include -#endif - -#define SAFE -#ifdef SAFE -typedef rtems_mode preemption_key; - -#define DISABLE_PREEMPTION(key) \ - do { \ - rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &(key)); \ - } while (0) - -#define ENABLE_PREEMPTION(key) \ - do { \ - rtems_mode temp; \ - rtems_task_mode((key), RTEMS_PREEMPT_MASK, &temp); \ - } while (0) - -#else - -typedef boolean preemption_key; - -#define DISABLE_PREEMPTION(key) \ - do { \ - (key) = _Thread_Executing->is_preemptible; \ - _Thread_Executing->is_preemptible = 0; \ - } while (0) - -#define ENABLE_PREEMPTION(key) \ - do { \ - _Thread_Executing->is_preemptible = (key); \ - if (_Thread_Evaluate_mode()) \ - _Thread_Dispatch(); \ - } while (0) - -#endif - -/* 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 { - blkdev_request req; - 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]; - -/* - * Mapping from ATA-minor numbers to - * controller-minor and device on this controller. - */ -static ata_ide_dev_t ata_devs[2 * IDE_CTRL_MAX_MINOR_NUMBER]; -static int ata_devs_number; - -/* Flag meaning that ATA driver has already been initialized */ -static rtems_boolean ata_initialized = FALSE; - - -/* task and queue used for asynchronous I/O operations */ -static rtems_id ata_task_id; -static rtems_id ata_queue_id; - -/* Mapping of interrupt vectors to devices */ -static 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); - -/* - * read/write, open/close and ioctl are provided by general block device - * driver. Only initialization and ata-specific ioctl are here. - */ - -/* ata_io_data_request -- - * Form read/write request for an ATA device and enqueue it to - * IDE controller. - * - * PARAMETERS: - * device - device identifier - * req - read/write request from block device driver - * - * RETURNS: - * RTEMS_SUCCESSFUL on success, or error code if - * error occured - */ -static rtems_status_code -ata_io_data_request(dev_t device, blkdev_request *req) -{ - ata_req_t *areq; /* ATA request */ - rtems_device_minor_number rel_minor; /* relative minor which indexes - * ata_devs array - */ - rtems_device_minor_number ctrl_minor; - unsigned8 dev; - - rel_minor = (rtems_filesystem_dev_minor_t(device)) / - ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE; - - /* get controller which serves the ATA device */ - ctrl_minor = ata_devs[rel_minor].ctrl_minor; - - /* get ATA device identifier (0 or 1) */ - dev = ata_devs[rel_minor].device; - - areq = malloc(sizeof(ata_req_t)); - if (areq == NULL) - { - return RTEMS_NO_MEMORY; - } - - areq->breq = req; - areq->cnt = req->count; - areq->cbuf = 0; - areq->pos = 0; - - /* set up registers masks */ - areq->regs.to_write = ATA_REGISTERS_POSITION; - areq->regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS); - - /* choose device on the controller for which the command will be issued */ - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] = - (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS); - - /* Find ATA command and its type */ - if (ATA_DEV_INFO(ctrl_minor, dev).mode_active & ATA_MODES_DMA) - { - /* XXX: never has been tested */ - areq->type = ATA_COMMAND_TYPE_DMA; - if (req->req == BLKDEV_REQ_READ) - areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_READ_DMA; - else - areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_WRITE_DMA; - } - else - { - if (req->req == BLKDEV_REQ_READ) - { - areq->type = ATA_COMMAND_TYPE_PIO_IN; - - /* - * choose command to issue: if the number of blocks to be - * exchanged is greater then 1 and for ATA command READ MULTIPLE - * data block consists of more then 1 sector choose READ MULTIPLE - * otherwise READ SECTORS - */ - areq->regs.regs[IDE_REGISTER_COMMAND] = - ((ATA_DEV_INFO(ctrl_minor, dev).max_multiple) && - (req->count > 1) && - (ATA_DEV_INFO(ctrl_minor, dev).current_multiple > 1)) ? - ATA_COMMAND_READ_MULTIPLE : - ATA_COMMAND_READ_SECTORS; - } - else - { - areq->type = ATA_COMMAND_TYPE_PIO_OUT; - - /* - * choose command to issue: if the number of blocks to be - * exchanged is greater then 1 and for ATA command WRITE MULTIPLE - * data block consists of more then 1 sector choose WRITE MULTIPLE - * otherwise WRITE SECTORS - */ - areq->regs.regs[IDE_REGISTER_COMMAND] = - ((ATA_DEV_INFO(ctrl_minor, dev).max_multiple) && - (req->count > 1) && - (ATA_DEV_INFO(ctrl_minor, dev).current_multiple > 1)) ? - ATA_COMMAND_WRITE_MULTIPLE : - ATA_COMMAND_WRITE_SECTORS; - } - } - - /* - * Fill position registers - */ - if (ATA_DEV_INFO(ctrl_minor, dev).lba_avaible) - { - areq->regs.regs[IDE_REGISTER_LBA0] = (unsigned8)req->start; - areq->regs.regs[IDE_REGISTER_LBA1] = (unsigned8)(req->start >> 8); - areq->regs.regs[IDE_REGISTER_LBA2] = (unsigned8)(req->start >> 16); - areq->regs.regs[IDE_REGISTER_LBA3] |= (unsigned8) (req->start >> 24); - areq->regs.regs[IDE_REGISTER_LBA3] |= IDE_REGISTER_LBA3_L; - } - else - { - unsigned32 count = req->start; - - areq->regs.regs[IDE_REGISTER_SECTOR_NUMBER] = - (count % ATA_DEV_INFO(ctrl_minor, dev).sectors) + 1; - - /* now count = number of tracks: */ - count /= ATA_DEV_INFO(ctrl_minor, dev).sectors; - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] |= - (count / ATA_DEV_INFO(ctrl_minor, dev).cylinders); - - /* now count = number of cylinders */ - count %= ATA_DEV_INFO(ctrl_minor, dev).cylinders; - areq->regs.regs[IDE_REGISTER_CYLINDER_LOW] = (unsigned8)count; - areq->regs.regs[IDE_REGISTER_CYLINDER_HIGH] = (unsigned8)(count >> 8); - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &= - ~IDE_REGISTER_DEVICE_HEAD_L; - } - - /* fill sector count register */ - areq->regs.regs[IDE_REGISTER_SECTOR_COUNT] = areq->breq->count; - - /* add request to the queue of awaiting requests to the controller */ - ata_add_to_controller_queue(ctrl_minor, areq); - - return RTEMS_SUCCESSFUL; -} - -/* ata_non_data_request -- - * Form and serve request of NON DATA type for an ATA device. - * Processing of NON DATA request is SYNChronous operation. - * - * PARAMETERS: - * device - device identifier - * cmd - command - * argp - arguments for command - * - * RETURNS: - * RTEMS_SUCCESSFUL on success, or error code if - * error occured - */ -static rtems_status_code -ata_non_data_request(dev_t device, int cmd, void *argp) -{ - rtems_status_code rc; - ata_req_t *areq; /* ATA request */ - rtems_device_minor_number rel_minor; /* relative minor which indexes - * ata_devs array - */ - rtems_device_minor_number ctrl_minor; - unsigned8 dev; - ata_queue_msg_t msg; - - rel_minor = (rtems_filesystem_dev_minor_t(device)) / - ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE; - - /* get controller which serves the ATA device */ - ctrl_minor = ata_devs[rel_minor].ctrl_minor; - - /* get ATA device identifier (0 or 1) */ - dev = ata_devs[rel_minor].device; - - /* form the request */ - areq = malloc(sizeof(ata_req_t)); - if (areq == NULL) - { - return RTEMS_NO_MEMORY; - } - 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_DEVICE_HEAD] |= - (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS); - areq->breq = NULL; - areq->regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR); - - /* - * depending on command fill command register and additional registers - * which are needed for command execution - */ - switch(cmd) - { - case ATAIO_SET_MULTIPLE_MODE: - areq->regs.regs[IDE_REGISTER_COMMAND] = - ATA_COMMAND_SET_MULTIPLE_MODE; - areq->regs.to_write |= - ATA_REGISTERS_VALUE(IDE_REGISTER_SECTOR_COUNT); - areq->regs.regs[IDE_REGISTER_SECTOR_COUNT] = *(unsigned8 *)argp; - break; - - default: - free(areq); - return RTEMS_INVALID_NUMBER; - break; - } - - rc = rtems_semaphore_create(rtems_build_name('I', 'D', 'E', 'S'), - 0, - RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | - RTEMS_NO_INHERIT_PRIORITY | - RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, - 0, - &(areq->sema)); - if (rc != RTEMS_SUCCESSFUL) - { - free(areq); - return rc; - } - - ata_add_to_controller_queue(ctrl_minor, areq); - - /* wait for request processing... */ - rc = rtems_semaphore_obtain(areq->sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (rc != RTEMS_SUCCESSFUL) - { - free(areq); - return rc; - } - - rtems_semaphore_delete(areq->sema); - - /* - * if no error occurred and if necessary, update internal ata driver data - * structures to reflect changes (in device configuration, for example) - */ - if (areq->status == RTEMS_SUCCESSFUL) - { - switch(cmd) - { - case ATAIO_SET_MULTIPLE_MODE: - ATA_DEV_INFO(ctrl_minor, dev).current_multiple = - *(unsigned8 *)argp; - break; - - default: - rc = RTEMS_INVALID_NUMBER; - break; - } - } - else - { - /* XXX: should be correct error processing: for ex, may be - * ABRT and then we should return RTEMS_NOT_IMPLEMENTED - */ - rc = RTEMS_IO_ERROR; - } - - /* tell ata driver that controller ready to serve next request */ - ATA_SEND_EVT(msg, ATA_MSG_SUCCESS_EVT, ctrl_minor, 0); - - return rc; -} - -/* ata_process_request -- - * Get first request from controller's queue and process it. - * - * PARAMETERS: - * ctrl_minor - controller identifier - * - * RETURNS: - * NONE - */ -static void -ata_process_request(rtems_device_minor_number ctrl_minor) -{ - ata_req_t *areq; - unsigned16 byte; /* emphasize that only 8 low bits is meaningful */ - ata_queue_msg_t msg; - unsigned8 i, dev; - unsigned16 val; - unsigned16 data_bs; /* the number of 512-bytes sectors in one - * data block - */ - ISR_Level level; - - /* if no requests to controller then do nothing */ - if (Chain_Is_empty(&ata_ide_ctrls[ctrl_minor].reqs)) - return; - - /* get first request in the controller's queue */ - _ISR_Disable(level); - areq = (ata_req_t *)(ata_ide_ctrls[ctrl_minor].reqs.first); - _ISR_Enable(level); - - /* get ATA device identifier (0 or 1) */ - dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] & - IDE_REGISTER_DEVICE_HEAD_DEV; - - /* get data block size */ - data_bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ? - ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1; - - /* execute device select protocol */ - ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD, - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]); - - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte); - } while ((byte & IDE_REGISTER_STATUS_BSY) || - (!(byte & IDE_REGISTER_STATUS_DRDY))); - - /* fill in all necessary registers on the controller */ - for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++) - { - unsigned32 reg = (1 << i); - if (areq->regs.to_write & reg) - ide_controller_write_register(ctrl_minor, i, areq->regs.regs[i]); - } - - /* continue to execute ATA protocols depending on type of request */ - if (areq->type == ATA_COMMAND_TYPE_PIO_OUT) - { - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &byte); - } while (byte & IDE_REGISTER_STATUS_BSY); - - if (byte & IDE_REGISTER_STATUS_DRQ) - { - ide_controller_write_data_block( - ctrl_minor, - MIN(data_bs, areq->cnt) * ATA_SECTOR_SIZE, - areq->breq->bufs, &areq->cbuf, - &areq->pos); - areq->cnt -= MIN(data_bs, areq->cnt); - } - else - { - if (IDE_Controller_Table[ctrl_minor].int_driven == 0) - { - ide_controller_read_register( - ctrl_minor, - IDE_REGISTER_ALTERNATE_STATUS_OFFSET, - &val); - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &val); - - ATA_SEND_EVT(msg, ATA_MSG_ERROR_EVT, ctrl_minor, - RTEMS_IO_ERROR); - } - } - } - - if (IDE_Controller_Table[ctrl_minor].int_driven == 0) - { - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &byte); - } while (byte & IDE_REGISTER_STATUS_BSY); - - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0); - } -} - -/* ata_request_done -- - * Extract request from controller queue, execute callback if necessary - * and process next request for the controller. - * - * PARAMETERS: - * areq - ATA request - * ctrl_minor - controller identifier - * status - status with which request has been done - * error - error, if status != RTEMS_SUCCESSFUL - * - * RETURNS: - * NONE - */ -static inline void -ata_request_done(ata_req_t *areq, rtems_device_minor_number ctrl_minor, - rtems_status_code status, int error) -{ - preemption_key key; - - assert(areq); - - DISABLE_PREEMPTION(key); - ATA_EXEC_CALLBACK(areq, status, error); - Chain_Extract(&areq->link); - free(areq); - - if (!Chain_Is_empty(&ata_ide_ctrls[ctrl_minor].reqs)) - { - ENABLE_PREEMPTION(key); - ata_process_request(ctrl_minor); - return; - } - ENABLE_PREEMPTION(key); -} - -/* ata_non_data_request_done -- - * Set up request status and release request's semaphore. - * - * PARAMETERS: - * areq - ATA request - * ctrl_minor - controller identifier - * status - status with which request has been done - * error - error, if status != RTEMS_SUCCESSFUL - * - * RETURNS: - * NONE - */ -static inline void -ata_non_data_request_done(ata_req_t *areq, - rtems_device_minor_number ctrl_minor, - rtems_status_code status, int error) -{ - areq->status = status; - areq->error = error; - rtems_semaphore_release(areq->sema); -} - - -/* ata_add_to_controller_queue -- - * Add request to the controller's queue. - * - * PARAMETERS: - * ctrl_minor - controller identifier - * areq - ATA request - * - * RETURNS: - * NONE - */ -static void -ata_add_to_controller_queue(rtems_device_minor_number ctrl_minor, - ata_req_t *areq) -{ - Chain_Append(&ata_ide_ctrls[ctrl_minor].reqs, &areq->link); - if (Chain_Has_only_one_node(&ata_ide_ctrls[ctrl_minor].reqs)) - { - unsigned16 val; - ata_queue_msg_t msg; - -#ifdef DEBUG - /* - * read IDE_REGISTER_ALTERNATE_STATUS instead IDE_REGISTER_STATUS - * to prevent clearing of pending interrupt - */ - ide_controller_read_register(ctrl_minor, - IDE_REGISTER_ALTERNATE_STATUS, - &val); - if (val & IDE_REGISTER_STATUS_BSY) - return; -#endif - ATA_SEND_EVT(msg, ATA_MSG_PROCESS_NEXT_EVT, ctrl_minor, 0); - } -} - - -/* ata_interrupt_handler -- - * ATA driver interrrupt handler. If interrrupt happend it mapped it to - * controller (controllerS, if a number of controllers share one int line) - * and generates ATA event(s). - * - * PARAMETERS: - * vec - interrupt vector - * - * RETURNS: - * NONE - */ -rtems_isr -ata_interrupt_handler(rtems_vector_number vec) -{ - Chain_Node *the_node = ((Chain_Control *)(&ata_int_vec[vec]))->first; - ata_queue_msg_t msg; - unsigned16 byte; /* emphasize that only 8 low bits is meaningful */ - - for ( ; !Chain_Is_tail(&ata_int_vec[vec], the_node) ; ) - { - /* if (1) - is temporary hack - currently I don't know how to identify - * controller which asserted interrupt if few controllers share one - * interrupt line - */ - if (1) - { - msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor; - ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS, - &byte); - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0); - } - the_node = the_node->next; - } -} - -/* ata_pio_in_protocol -- - * ATA PIO_IN protocol implementation, see specification - * - * PARAMETERS: - * ctrl_minor - controller identifier - * areq - ATA request - * - * RETURNS: - * NONE - */ -static inline void -ata_pio_in_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq) -{ - unsigned16 bs, val; - unsigned8 dev; - unsigned32 min_val; - ata_queue_msg_t msg; - - dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] & - IDE_REGISTER_DEVICE_HEAD_DEV; - - bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ? - ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1; - min_val = MIN(bs, areq->cnt); - - ide_controller_read_data_block(ctrl_minor, min_val * ATA_SECTOR_SIZE, - areq->breq->bufs, &areq->cbuf, &areq->pos); - - areq->cnt -= min_val; - if (areq->cnt == 0) - { - ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL, RTEMS_SUCCESSFUL); - } - else if (IDE_Controller_Table[ctrl_minor].int_driven == 0) - { - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val); - } while (val & IDE_REGISTER_STATUS_BSY); - - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0); - } -} - -/* ata_pio_out_protocol -- - * ATA PIO_OUT protocol implementation, see specification - * - * PARAMETERS: - * ctrl_minor - controller identifier - * areq - ATA request - * - * RETURNS: - * NONE - */ -static inline void -ata_pio_out_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq) -{ - unsigned16 bs, val; - unsigned8 dev; - unsigned32 min_val; - ata_queue_msg_t msg; - - dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] & - IDE_REGISTER_DEVICE_HEAD_DEV; - - bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ? - ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1; - - min_val = MIN(bs, areq->cnt); - - if (areq->cnt == 0) - { - ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL, RTEMS_SUCCESSFUL); - } - else - { - ide_controller_write_data_block(ctrl_minor, min_val * ATA_SECTOR_SIZE, - areq->breq->bufs, &areq->cbuf, - &areq->pos); - areq->cnt -= min_val; - if (IDE_Controller_Table[ctrl_minor].int_driven == 0) - { - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &val); - } while (val & IDE_REGISTER_STATUS_BSY); - - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0); - } - } -} - -/* ata_queue_task -- - * Task which manages ATA driver events queue. - * - * PARAMETERS: - * arg - ignored - * - * RETURNS: - * NONE - * - * NOTES: - * should be non-preemptive - */ -static rtems_task -ata_queue_task(rtems_task_argument arg) -{ - ata_queue_msg_t msg; - rtems_unsigned32 size; - ata_req_t *areq; - rtems_device_minor_number ctrl_minor; - unsigned16 val; - unsigned16 val1; - rtems_status_code rc; - ISR_Level level; - - while (1) - { - /* get event which has happend */ - rc = rtems_message_queue_receive(ata_queue_id, &msg, &size, RTEMS_WAIT, - RTEMS_NO_TIMEOUT); - if (rc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR); - - /* get controller on which event has happend */ - ctrl_minor = msg.ctrl_minor; - - /* get current request to the controller */ - _ISR_Disable(level); - areq = (ata_req_t *)(ata_ide_ctrls[ctrl_minor].reqs.first); - _ISR_Enable(level); - - switch(msg.type) - { - case ATA_MSG_PROCESS_NEXT_EVT: - /* process next request in the controller queue */ - ata_process_request(ctrl_minor); - break; - - case ATA_MSG_SUCCESS_EVT: - /* - * finish processing of current request with successful - * status and start processing of the next request in the - * controller queue - */ - ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL, - msg.error); - break; - - case ATA_MSG_ERROR_EVT: - /* - * finish processing of current request with error - * status and start processing of the next request in the - * controller queue - */ - ata_request_done(areq, ctrl_minor, RTEMS_UNSATISFIED, - msg.error); - break; - - case ATA_MSG_GEN_EVT: - /* - * continue processing of the current request to the - * controller according to current request state and - * ATA protocol - */ - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &val); - /* process error case */ - if (val & IDE_REGISTER_STATUS_ERR) - { - ide_controller_read_register(ctrl_minor, - IDE_REGISTER_ERROR, - &val); - if (areq->type == ATA_COMMAND_TYPE_NON_DATA) - ata_non_data_request_done(areq, ctrl_minor, - RTEMS_UNSATISFIED, - RTEMS_IO_ERROR); - else - ata_request_done(areq, ctrl_minor, RTEMS_UNSATISFIED, - RTEMS_IO_ERROR); - break; - } - - switch(areq->type) - { - case ATA_COMMAND_TYPE_PIO_IN: - ata_pio_in_protocol(ctrl_minor, areq); - break; - - case ATA_COMMAND_TYPE_PIO_OUT: - ata_pio_out_protocol(ctrl_minor, areq); - break; - - case ATA_COMMAND_TYPE_NON_DATA: - ide_controller_read_register(ctrl_minor, - IDE_REGISTER_ERROR, - &val1); - ata_non_data_request_done(areq, ctrl_minor, - RTEMS_SUCCESSFUL, - val1); - break; - - default: - printf("ata_queue_task: non-supported command type\n"); - ata_request_done(areq, ctrl_minor, - RTEMS_UNSATISFIED, - RTEMS_NOT_IMPLEMENTED); - break; - } - break; - - default: - rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR); - break; - } - } -} - -/* ata_ioctl -- - * ATA driver ioctl interface. - * - * PARAMETERS: - * device - device identifier - * cmd - command - * argp - arguments - * - * RETURNS: - * depend on 'cmd' - */ -int -ata_ioctl(dev_t device, int cmd, void *argp) -{ - rtems_status_code status; - rtems_device_minor_number rel_minor; - - rel_minor = (rtems_filesystem_dev_minor_t(device)) / - ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE; - - /* - * in most cases this means that device 'device' is not an registred ATA - * device - */ - if (ata_devs[rel_minor].device == ATA_UNDEFINED_VALUE) - { - errno = ENODEV; - return -1; - } - - switch (cmd) - { - case BLKIO_REQUEST: - status = ata_io_data_request(device, (blkdev_request *)argp); - break; - - case ATAIO_SET_MULTIPLE_MODE: - status = ata_non_data_request(device, cmd, argp); - break; - - default: - errno = EBADRQC; - return -1; - break; - } - - if (status != RTEMS_SUCCESSFUL) - { - errno = EIO; - return -1; - } - return 0; -} - -/* - * ata_initialize -- - * Initializes all ATA devices found on initialized IDE controllers. - * - * PARAMETERS: - * major - device major number - * minor - device minor number - * args - arguments - * - * RETURNS: - * RTEMS_SUCCESSFUL on success, or error code if - * error occured - */ -rtems_device_driver -ata_initialize(rtems_device_major_number major, - rtems_device_minor_number minor_arg, - void *args) -{ - unsigned32 ctrl_minor; - rtems_status_code status; - ata_req_t areq; - blkdev_request1 breq; - unsigned8 i, dev = 0; - unsigned16 *buffer; - unsigned16 ec; - char name[ATA_MAX_NAME_LENGTH]; - dev_t device; - ata_int_st_t *int_st; - rtems_isr_entry old_isr; - - if (ata_initialized) - return RTEMS_SUCCESSFUL; - - /* initialization of disk devices library */ - status = rtems_disk_io_initialize(); - if (status != RTEMS_SUCCESSFUL) - return status; - - /* create queue for asynchronous requests handling */ - status = rtems_message_queue_create( - rtems_build_name('A', 'T', 'A', 'Q'), - ATA_DRIVER_MESSAGE_QUEUE_SIZE, - sizeof(ata_queue_msg_t), - RTEMS_FIFO | RTEMS_LOCAL, - &ata_queue_id); - if (status != RTEMS_SUCCESSFUL) - { - rtems_disk_io_done(); - return status; - } - - /* - * create ATA driver task, see comments for task implementation for - * details - */ - status = rtems_task_create( - rtems_build_name ('A', 'T', 'A', 'T'), - ATA_DRIVER_TASK_PRIORITY, - ATA_DRIVER_TASK_STACK_SIZE, - RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_ASR | - RTEMS_INTERRUPT_LEVEL(0), - RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, - &ata_task_id); - if (status != RTEMS_SUCCESSFUL) - { - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return status; - } - - /* - * start ATA driver task. Actually the task will not start immediately - - * it will start only after multitasking support will be started - */ - status = rtems_task_start(ata_task_id, ata_queue_task, 0); - if (status != RTEMS_SUCCESSFUL) - { - rtems_task_delete(ata_task_id); - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return status; - } - - buffer = (unsigned16 *)malloc(ATA_SECTOR_SIZE); - if (buffer == NULL) - { - rtems_task_delete(ata_task_id); - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return RTEMS_NO_MEMORY; - } - - ata_devs_number = 0; - - for (i = 0; i < (2 * IDE_CTRL_MAX_MINOR_NUMBER); i++) - ata_devs[i].device = ATA_UNDEFINED_VALUE; - - /* prepare ATA driver for handling interrupt driven devices */ - for (i = 0; i < ATA_MAX_RTEMS_INT_VEC_NUMBER; i++) - Chain_Initialize_empty(&ata_int_vec[i]); - - /* - * during ATA driver initialization EXECUTE DEVICE DIAGNOSTIC and - * IDENTIFY DEVICE ATA command should be issued; for these purposes ATA - * 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.count = 1; - breq.req.bufs[0].length = ATA_SECTOR_SIZE; - breq.req.bufs[0].buffer = buffer; - - /* - * for each presented IDE controller execute EXECUTE DEVICE DIAGNOSTIC - * ATA command; for each found device execute IDENTIFY DEVICE ATA - * command - */ - for (ctrl_minor = 0; ctrl_minor < IDE_Controller_Count; ctrl_minor++) - if (IDE_Controller_Table[ctrl_minor].status == IDE_CTRL_INITIALIZED) - { - Chain_Initialize_empty(&ata_ide_ctrls[ctrl_minor].reqs); - - if (IDE_Controller_Table[ctrl_minor].int_driven == TRUE) - { - int_st = malloc(sizeof(ata_int_st_t)); - if (int_st == NULL) - { - free(buffer); - rtems_task_delete(ata_task_id); - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return RTEMS_NO_MEMORY; - } - - int_st->ctrl_minor = ctrl_minor; - - status = rtems_interrupt_catch( - ata_interrupt_handler, - IDE_Controller_Table[ctrl_minor].int_vec, - &old_isr); - if (status != RTEMS_SUCCESSFUL) - { - free(int_st); - free(buffer); - rtems_task_delete(ata_task_id); - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return status; - } - Chain_Append( - &ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec], - &int_st->link); - - /* disable interrupts */ - ide_controller_write_register(ctrl_minor, - IDE_REGISTER_DEVICE_CONTROL_OFFSET, - IDE_REGISTER_DEVICE_CONTROL_nIEN); - } - - /* - * Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is - * there any ATA device on the controller. - */ - 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 = (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) - continue; - - /* disassemble returned diagnostic codes */ - if (breq.req.error == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT) - { - ATA_DEV_INFO(ctrl_minor, 0).present = 1; - ATA_DEV_INFO(ctrl_minor,1).present = 1; - } - else if (breq.req.error == ATA_DEV0_PASSED_DEV1_FAILED) - { - ATA_DEV_INFO(ctrl_minor,0).present = 1; - ATA_DEV_INFO(ctrl_minor,1).present = 0; - } - else if (breq.req.error < ATA_DEV1_PASSED_DEV0_FAILED) - { - ATA_DEV_INFO(ctrl_minor,0).present = 0; - ATA_DEV_INFO(ctrl_minor,1).present = 1; - } - else - { - ATA_DEV_INFO(ctrl_minor, 0).present = 0; - ATA_DEV_INFO(ctrl_minor, 1).present = 0; - } - - /* refine the returned codes */ - if (ATA_DEV_INFO(ctrl_minor, 1).present != 0) - { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec); - if (ec & ATA_DEV1_PASSED_DEV0_FAILED) - ATA_DEV_INFO(ctrl_minor, 1).present = 1; - else - ATA_DEV_INFO(ctrl_minor, 1).present = 0; - } - - /* 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 = (blkdev_request *)&breq; - - areq.cnt = breq.req.count; - - 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_SECS0]) << 16) + - CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS1]); - ATA_DEV_INFO(ctrl_minor, dev).lba_avaible = - (CF_LE_W(buffer[ATA_IDENT_WORD_CAPABILITIES]) >> 9) & 0x1; - ATA_DEV_INFO(ctrl_minor, dev).max_multiple = - (unsigned8) (CF_LE_W(buffer[ATA_IDENT_WORD_RW_MULT])); - ATA_DEV_INFO(ctrl_minor, dev).current_multiple = - (CF_LE_W(buffer[ATA_IDENT_WORD_MULT_SECS]) & 0x100) ? - (unsigned8)(CF_LE_W(buffer[ATA_IDENT_WORD_MULT_SECS])) : - 0; - - 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_avaible = - ((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_avaible == 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_avaible); - if (status != RTEMS_SUCCESSFUL) - continue; - } - /* - * Ok, let register new ATA device in the system - */ - ata_devs[ata_devs_number].ctrl_minor = ctrl_minor; - ata_devs[ata_devs_number].device = dev; - - snprintf(name, ATA_MAX_NAME_LENGTH, "/dev/hd%c", - 'a' + 2 * ctrl_minor + dev); - device = rtems_filesystem_make_dev_t( - major, - (ata_devs_number * - ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE)); - - status = rtems_disk_create_phys(device, ATA_SECTOR_SIZE, - ATA_DEV_INFO(ctrl_minor, dev).lba_avaible ? - ATA_DEV_INFO(ctrl_minor, dev).lba_sectors : - (ATA_DEV_INFO(ctrl_minor, dev).heads * - ATA_DEV_INFO(ctrl_minor, dev).cylinders * - ATA_DEV_INFO(ctrl_minor, dev).sectors), - (block_device_ioctl) ata_ioctl, name); - if (status != RTEMS_SUCCESSFUL) - { - ata_devs[ata_devs_number].device = ATA_UNDEFINED_VALUE; - continue; - } - ata_devs_number++; - } - if (IDE_Controller_Table[ctrl_minor].int_driven == TRUE) - { - ide_controller_write_register(ctrl_minor, - IDE_REGISTER_DEVICE_CONTROL_OFFSET, - 0x00); - } - } - - free(buffer); - ata_initialized = TRUE; - return RTEMS_SUCCESSFUL; -} - -/* ata_process_request_on_init_phase -- - * Process the ATA request during system initialization. Request - * processing is syncronous and doesn't use multiprocessing enviroment. - * - * PARAMETERS: - * ctrl_minor - controller identifier - * areq - ATA request - * - * RETURNS: - * NONE - */ -static void -ata_process_request_on_init_phase(rtems_device_minor_number ctrl_minor, - ata_req_t *areq) -{ - unsigned16 byte;/* emphasize that only 8 low bits is meaningful */ - unsigned8 i, dev; - unsigned16 val, val1; - unsigned16 data_bs; /* the number of 512 bytes sectors into one - * data block - */ - assert(areq); - - dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] & - IDE_REGISTER_DEVICE_HEAD_DEV; - - data_bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ? - ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1; - - ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD, - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]); - - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte); - } while ((byte & IDE_REGISTER_STATUS_BSY) || - (!(byte & IDE_REGISTER_STATUS_DRDY))); - - for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++) - { - unsigned32 reg = (1 << i); - if (areq->regs.to_write & reg) - ide_controller_write_register(ctrl_minor, i, - areq->regs.regs[i]); - } - - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte); - } while (byte & IDE_REGISTER_STATUS_BSY); - - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val); - ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &val1); - - if (val & IDE_REGISTER_STATUS_ERR) - { - areq->breq->status = RTEMS_UNSATISFIED; - areq->breq->error = RTEMS_IO_ERROR; - return; - } - - switch(areq->type) - { - case ATA_COMMAND_TYPE_PIO_IN: - ide_controller_read_data_block( - ctrl_minor, - MIN(data_bs, areq->cnt) * ATA_SECTOR_SIZE, - areq->breq->bufs, &areq->cbuf, - &areq->pos); - - areq->cnt -= MIN(data_bs, areq->cnt); - if (areq->cnt == 0) - { - areq->breq->status = RTEMS_SUCCESSFUL; - } - else - { - /* - * this shouldn't happend on the initialization - * phase! - */ - rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR); - } - break; - - case ATA_COMMAND_TYPE_NON_DATA: - areq->breq->status = RTEMS_SUCCESSFUL; - areq->breq->error = val1; - break; - - default: - printf("ata_queue_task: non-supported command type\n"); - areq->breq->status = RTEMS_UNSATISFIED; - areq->breq->error = RTEMS_NOT_IMPLEMENTED; - break; - } -} -- cgit v1.2.3