source: rtems/c/src/libchip/ide/ata.c @ 3735f08

4.104.114.95
Last change on this file since 3735f08 was 3735f08, checked in by Chris Johns <chrisj@…>, on 07/29/08 at 02:23:48

2008-07-29 Chris Johns <chrisj@…>

  • libchip/i2c/spi-sd-card.c: Updated to the libblock changes.
  • libchip/ide/ata.c: Change to use a mutex rather than disable pre-emption. Updated to the libblock changes.
  • libchip/ide/ata_internal.h: Updated to the new chains API.
  • libchip/ide/ide_controller.c: Updated to the libblock changes. Added come debug tracing.
  • libchip/ide/ide_ctrl_cfg.h, libchip/ide/ide_ctrl_io.h: Updated to the libblock changes.
  • Property mode set to 100644
File size: 49.8 KB
RevLine 
[109fc26]1/*
2 * ata.c
3 *
[a3d3d9a]4 * ATA RTEMS driver. ATA driver is hardware independant implementation of
5 * ATA-2 standart, working draft X3T10/0948D, revision 4c. ATA driver bases
[109fc26]6 * on RTEMS IDE controller driver.
7 *
8 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
9 * Authors: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
10 *
11 * The license and distribution terms for this file may be
12 * found in the file LICENSE in this distribution or at
[94365d9]13 * http://www.rtems.com/license/LICENSE.
[a3d3d9a]14 *
[109fc26]15 * $Id$
[a3d3d9a]16 *
[109fc26]17 */
18#include <errno.h>
[4caeb10]19#include <rtems/chain.h>
[109fc26]20#include <assert.h>
21#include <string.h> /* for "memset" declaration */
22
23#include <rtems/diskdevs.h>
24#include <rtems/blkdev.h>
25#include <libchip/ide_ctrl_io.h>
26#include <libchip/ide_ctrl_cfg.h>
27#include "ata_internal.h"
28#include <libchip/ata.h>
[3735f08]29//#define DEBUG
[109fc26]30
31#ifdef DEBUG
32#include <stdio.h>
33#endif
34
[d5ed9e1]35/*
36 * FIXME: make this better...
37 * find out, which exception model is used
38 * assume, that all i386 BSPs use new exception handling
39 * assume, that some PPC BSPs use new exception handling
40 * assume, that all other BSPs use old exception handling
41 */
42#if defined(_OLD_EXCEPTIONS) || (!defined(__i386__) && !defined(__PPC__))
43
44#define ATA_USE_OLD_EXCEPTIONS
45#endif
46
47#if !defined(ATA_USE_OLD_EXCEPTIONS)
48#include <bsp/irq.h>
49#define ATA_IRQ_CHAIN_MAX_CNT 4 /* support up to 4 ATA devices */
50typedef struct {
51  rtems_irq_number name;
[b9c38ed]52  rtems_chain_control irq_chain;
[d5ed9e1]53} ata_irq_chain_t;
54
55ata_irq_chain_t ata_irq_chain[ATA_IRQ_CHAIN_MAX_CNT];
56int ata_irq_chain_cnt = 0;
57#endif
58
[109fc26]59#define SAFE
[3735f08]60#define SAFE_MUTEX
61
[109fc26]62#ifdef SAFE
[3735f08]63#ifdef SAFE_MUTEX
64static rtems_id ata_lock;
65static void
66rtems_ata_lock ()
67{
68  rtems_status_code sc = rtems_semaphore_obtain (ata_lock,
69                                                 RTEMS_WAIT,
70                                                 RTEMS_NO_TIMEOUT);
71  if (sc != RTEMS_SUCCESSFUL)
72    rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
73}
74
75static void
76rtems_ata_unlock ()
77{
78  rtems_status_code sc = rtems_semaphore_release (ata_lock);
79  if (sc != RTEMS_SUCCESSFUL)
80    rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
81}
82
83#define RTEMS_ATA_LOCK_ATTRIBS \
84  (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
85   RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
86
87#define PREEMPTION_KEY(key)
88#define DISABLE_PREEMPTION(key) rtems_ata_lock ()
89#define ENABLE_PREEMPTION(key)  rtems_ata_unlock ()
90
91#else /* !SAFE_MUTEX */
[109fc26]92typedef rtems_mode preemption_key;
93
[3735f08]94#define PREEMPTION_KEY(key) preemption_key key
95
96#define DISABLE_PREEMPTION(key)                                        \
[109fc26]97    do {                                                               \
98        rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &(key)); \
99    } while (0)
100
101#define ENABLE_PREEMPTION(key) \
102    do {                                                        \
103        rtems_mode temp;                                        \
104        rtems_task_mode((key), RTEMS_PREEMPT_MASK, &temp);      \
105    } while (0)
[3735f08]106#endif
107#else /* !SAFE */
[109fc26]108typedef boolean preemption_key;
109
[3735f08]110#define PREEMPTION_KEY(key) preemption_key key
111
[109fc26]112#define DISABLE_PREEMPTION(key) \
113    do {                                             \
114        (key) = _Thread_Executing->is_preemptible;   \
115        _Thread_Executing->is_preemptible = 0;       \
116    } while (0)
[a3d3d9a]117
[109fc26]118#define ENABLE_PREEMPTION(key) \
119    do {                                             \
120        _Thread_Executing->is_preemptible = (key);   \
121        if (_Thread_Evaluate_mode())                 \
122            _Thread_Dispatch();                      \
123    } while (0)
124
125#endif
126
127/* FIXME: case if ATA device is FLASH device need more attention */
128#undef ATA_DEV_IS_FLASH_DISK
129
130/* Block device request with a single buffer provided */
131typedef struct blkdev_request1 {
[3735f08]132    rtems_blkdev_request   req;
133    rtems_blkdev_sg_buffer sg[1];
[109fc26]134} blkdev_request1;
135
136
137/* Array indexed by controllers minor number */
138static ata_ide_ctrl_t ata_ide_ctrls[IDE_CTRL_MAX_MINOR_NUMBER];
139
140/*
[a3d3d9a]141 * Mapping from ATA-minor numbers to
[109fc26]142 * controller-minor and device on this controller.
143 */
144static ata_ide_dev_t ata_devs[2 * IDE_CTRL_MAX_MINOR_NUMBER];
145static int ata_devs_number;
146
147/* Flag meaning that ATA driver has already been initialized */
148static rtems_boolean ata_initialized = FALSE;
149
150
151/* task and queue used for asynchronous I/O operations */
152static rtems_id ata_task_id;
153static rtems_id ata_queue_id;
154
[d5ed9e1]155#if defined (ATA_USE_OLD_EXCEPTIONS)
[109fc26]156/* Mapping of interrupt vectors to devices */
[b9c38ed]157static rtems_chain_control ata_int_vec[ATA_MAX_RTEMS_INT_VEC_NUMBER + 1];
[d5ed9e1]158#endif
[109fc26]159
160static void
161ata_process_request(rtems_device_minor_number ctrl_minor);
162
163static void
164ata_process_request_on_init_phase(rtems_device_minor_number  ctrl_minor,
165                                  ata_req_t                 *areq);
166
[a3d3d9a]167static void
168ata_add_to_controller_queue(rtems_device_minor_number  ctrl_minor,
[109fc26]169                            ata_req_t                 *areq);
170
171/*
[a3d3d9a]172 * read/write, open/close and ioctl are provided by general block device
[109fc26]173 * driver. Only initialization and ata-specific ioctl are here.
174 */
175
[a3d3d9a]176/* ata_io_data_request --
177 *     Form read/write request for an ATA device and enqueue it to
178 *     IDE controller.
179 *
[109fc26]180 * PARAMETERS:
181 *     device - device identifier
182 *     req    - read/write request from block device driver
183 *
184 * RETURNS:
185 *     RTEMS_SUCCESSFUL on success, or error code if
[a3d3d9a]186 *     error occured
[109fc26]187 */
188static rtems_status_code
[3735f08]189ata_io_data_request(dev_t device, rtems_blkdev_request *req)
[109fc26]190{
191    ata_req_t                 *areq; /* ATA request */
[a3d3d9a]192    rtems_device_minor_number  rel_minor; /* relative minor which indexes
[109fc26]193                                           * ata_devs array
194                                           */
195    rtems_device_minor_number  ctrl_minor;
[ee4f57d]196    uint8_t                    dev;
[a3d3d9a]197
198    rel_minor = (rtems_filesystem_dev_minor_t(device)) /
[109fc26]199                ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE;
[a3d3d9a]200
[109fc26]201    /* get controller which serves the ATA device */
202    ctrl_minor = ata_devs[rel_minor].ctrl_minor;
203
204    /* get ATA device identifier (0 or 1) */
205    dev = ata_devs[rel_minor].device;
206
207    areq = malloc(sizeof(ata_req_t));
208    if (areq == NULL)
209    {
210        return RTEMS_NO_MEMORY;
211    }
[a3d3d9a]212
[109fc26]213    areq->breq = req;
214    areq->cnt = req->count;
215    areq->cbuf = 0;
216    areq->pos = 0;
[a3d3d9a]217
218    /* set up registers masks */
[109fc26]219    areq->regs.to_write = ATA_REGISTERS_POSITION;
220    areq->regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS);
[a3d3d9a]221
[109fc26]222    /* choose device on the controller for which the command will be issued */
[a3d3d9a]223    areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] =
[109fc26]224                                    (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS);
225
226    /* Find ATA command and its type */
227    if (ATA_DEV_INFO(ctrl_minor, dev).mode_active & ATA_MODES_DMA)
228    {
229        /* XXX: never has been tested */
230        areq->type = ATA_COMMAND_TYPE_DMA;
[3735f08]231        if (req->req == RTEMS_BLKDEV_REQ_READ)
[109fc26]232            areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_READ_DMA;
[a3d3d9a]233        else
[109fc26]234            areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_WRITE_DMA;
235    }
[a3d3d9a]236    else
[109fc26]237    {
[3735f08]238        if (req->req == RTEMS_BLKDEV_REQ_READ)
[109fc26]239        {
[3735f08]240#ifdef DEBUG
241            printf("ata_io_data_request: type: READ: %d, %d\n",
242                   req->bufs[0].block, req->count);
243#endif           
[109fc26]244            areq->type = ATA_COMMAND_TYPE_PIO_IN;
[a3d3d9a]245
246            /*
247             * choose command to issue: if the number of blocks to be
[109fc26]248             * exchanged is greater then 1 and for ATA command READ MULTIPLE
249             * data block consists of more then 1 sector choose READ MULTIPLE
250             * otherwise READ SECTORS
251             */
[a3d3d9a]252            areq->regs.regs[IDE_REGISTER_COMMAND] =
253                ((ATA_DEV_INFO(ctrl_minor, dev).max_multiple) &&
254                 (req->count > 1) &&
255                 (ATA_DEV_INFO(ctrl_minor, dev).current_multiple > 1)) ?
256                 ATA_COMMAND_READ_MULTIPLE :
[109fc26]257                 ATA_COMMAND_READ_SECTORS;
258        }
259        else
260        {
[3735f08]261#ifdef DEBUG
262            printf("ata_io_data_request: type: WRITE: %d, %d\n",
263                   req->bufs[0].block, req->count);
264#endif           
[109fc26]265            areq->type = ATA_COMMAND_TYPE_PIO_OUT;
266
[a3d3d9a]267            /*
268             * choose command to issue: if the number of blocks to be
[109fc26]269             * exchanged is greater then 1 and for ATA command WRITE MULTIPLE
270             * data block consists of more then 1 sector choose WRITE MULTIPLE
271             * otherwise WRITE SECTORS
272             */
[a3d3d9a]273            areq->regs.regs[IDE_REGISTER_COMMAND] =
[109fc26]274              ((ATA_DEV_INFO(ctrl_minor, dev).max_multiple) &&
275               (req->count > 1) &&
[a3d3d9a]276               (ATA_DEV_INFO(ctrl_minor, dev).current_multiple > 1)) ?
277               ATA_COMMAND_WRITE_MULTIPLE :
[109fc26]278               ATA_COMMAND_WRITE_SECTORS;
279        }
280    }
281
282    /*
283     * Fill position registers
284     */
285    if (ATA_DEV_INFO(ctrl_minor, dev).lba_avaible)
286    {
[3735f08]287        uint32_t start = req->bufs[0].block;
288        areq->regs.regs[IDE_REGISTER_LBA0] = (uint8_t)start;
289        areq->regs.regs[IDE_REGISTER_LBA1] = (uint8_t)(start >> 8);
290        areq->regs.regs[IDE_REGISTER_LBA2] = (uint8_t)(start >> 16);
291        areq->regs.regs[IDE_REGISTER_LBA3] |= (uint8_t) (start >> 24);
[109fc26]292        areq->regs.regs[IDE_REGISTER_LBA3] |= IDE_REGISTER_LBA3_L;
293    }
294    else
295    {
[3735f08]296        uint32_t   count = req->bufs[0].block;
[109fc26]297
298        areq->regs.regs[IDE_REGISTER_SECTOR_NUMBER] =
299                        (count % ATA_DEV_INFO(ctrl_minor, dev).sectors) + 1;
300
301        /* now count = number of tracks: */
302        count /= ATA_DEV_INFO(ctrl_minor, dev).sectors;
[a3d3d9a]303        areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] |=
[109fc26]304                          (count / ATA_DEV_INFO(ctrl_minor, dev).cylinders);
305
306        /* now count = number of cylinders */
307        count %= ATA_DEV_INFO(ctrl_minor, dev).cylinders;
[509fec9c]308        areq->regs.regs[IDE_REGISTER_CYLINDER_LOW] = (uint8_t)count;
309        areq->regs.regs[IDE_REGISTER_CYLINDER_HIGH] = (uint8_t)(count >> 8);
[a3d3d9a]310        areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &=
[109fc26]311                                                ~IDE_REGISTER_DEVICE_HEAD_L;
312    }
313
314    /* fill sector count register */
315    areq->regs.regs[IDE_REGISTER_SECTOR_COUNT] = areq->breq->count;
[a3d3d9a]316
[109fc26]317    /* add request to the queue of awaiting requests to the controller */
318    ata_add_to_controller_queue(ctrl_minor, areq);
[3735f08]319   
[109fc26]320    return RTEMS_SUCCESSFUL;
321}
322
[a3d3d9a]323/* ata_non_data_request --
324 *     Form and serve request of NON DATA type for an ATA device.
[109fc26]325 *     Processing of NON DATA request is SYNChronous operation.
[a3d3d9a]326 *
[109fc26]327 * PARAMETERS:
328 *     device - device identifier
329 *     cmd    - command
330 *     argp   - arguments for command
331 *
332 * RETURNS:
333 *     RTEMS_SUCCESSFUL on success, or error code if
[a3d3d9a]334 *     error occured
[109fc26]335 */
336static rtems_status_code
337ata_non_data_request(dev_t device, int cmd, void *argp)
338{
339    rtems_status_code          rc;
340    ata_req_t                 *areq;       /* ATA request */
341    rtems_device_minor_number  rel_minor; /* relative minor which indexes
342                                           * ata_devs array
343                                           */
344    rtems_device_minor_number  ctrl_minor;
[ee4f57d]345    uint8_t                    dev;
[a3d3d9a]346    ata_queue_msg_t            msg;
347
[109fc26]348    rel_minor = (rtems_filesystem_dev_minor_t(device)) /
[a3d3d9a]349                ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE;
[109fc26]350
351    /* get controller which serves the ATA device */
352    ctrl_minor = ata_devs[rel_minor].ctrl_minor;
353
354    /* get ATA device identifier (0 or 1) */
355    dev = ata_devs[rel_minor].device;
356
357    /* form the request */
358    areq = malloc(sizeof(ata_req_t));
359    if (areq == NULL)
360    {
361        return RTEMS_NO_MEMORY;
362    }
[a3d3d9a]363    memset(areq, 0, sizeof(ata_req_t));
[109fc26]364
365    areq->type = ATA_COMMAND_TYPE_NON_DATA;
366    areq->regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
[a3d3d9a]367    areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] |=
[109fc26]368                                    (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS);
369    areq->breq = NULL;
370    areq->regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);
[a3d3d9a]371
372    /*
373     * depending on command fill command register and additional registers
[109fc26]374     * which are needed for command execution
375     */
376    switch(cmd)
[a3d3d9a]377    {
[109fc26]378        case ATAIO_SET_MULTIPLE_MODE:
[a3d3d9a]379            areq->regs.regs[IDE_REGISTER_COMMAND] =
[109fc26]380                                                ATA_COMMAND_SET_MULTIPLE_MODE;
[a3d3d9a]381            areq->regs.to_write |=
[109fc26]382                               ATA_REGISTERS_VALUE(IDE_REGISTER_SECTOR_COUNT);
[509fec9c]383            areq->regs.regs[IDE_REGISTER_SECTOR_COUNT] = *(uint8_t*)argp;
[109fc26]384            break;
[a3d3d9a]385
[109fc26]386        default:
387            free(areq);
388            return RTEMS_INVALID_NUMBER;
[a3d3d9a]389            break;
390    }
[109fc26]391
[a3d3d9a]392    rc = rtems_semaphore_create(rtems_build_name('I', 'D', 'E', 'S'),
393                                0,
394                                RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE |
[109fc26]395                                RTEMS_NO_INHERIT_PRIORITY |
396                                RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
397                                0,
398                                &(areq->sema));
399    if (rc != RTEMS_SUCCESSFUL)
400    {
401        free(areq);
402        return rc;
[a3d3d9a]403    }
404
[109fc26]405    ata_add_to_controller_queue(ctrl_minor, areq);
[a3d3d9a]406
[109fc26]407    /* wait for request processing... */
408    rc = rtems_semaphore_obtain(areq->sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
409    if (rc != RTEMS_SUCCESSFUL)
410    {
411        free(areq);
412        return rc;
[a3d3d9a]413    }
[109fc26]414
415    rtems_semaphore_delete(areq->sema);
[a3d3d9a]416
417    /*
418     * if no error occurred and if necessary, update internal ata driver data
[109fc26]419     * structures to reflect changes (in device configuration, for example)
[a3d3d9a]420     */
[109fc26]421    if (areq->status == RTEMS_SUCCESSFUL)
422    {
423        switch(cmd)
[a3d3d9a]424        {
[109fc26]425            case ATAIO_SET_MULTIPLE_MODE:
[a3d3d9a]426                ATA_DEV_INFO(ctrl_minor, dev).current_multiple =
[509fec9c]427                                                           *(uint8_t*)argp;
[109fc26]428                break;
[a3d3d9a]429
[109fc26]430            default:
431                rc = RTEMS_INVALID_NUMBER;
[a3d3d9a]432                break;
433        }
434    }
435    else
436    {
437        /* XXX: should be correct error processing: for ex, may be
[109fc26]438         * ABRT and then we should return RTEMS_NOT_IMPLEMENTED
439         */
440        rc = RTEMS_IO_ERROR;
[a3d3d9a]441    }
442
[109fc26]443    /* tell ata driver that controller ready to serve next request */
444    ATA_SEND_EVT(msg, ATA_MSG_SUCCESS_EVT, ctrl_minor, 0);
[a3d3d9a]445
[109fc26]446    return rc;
447}
448
[a3d3d9a]449/* ata_process_request --
450 *     Get first request from controller's queue and process it.
451 *
[109fc26]452 * PARAMETERS:
453 *     ctrl_minor - controller identifier
454 *
455 * RETURNS:
[a3d3d9a]456 *     NONE
[109fc26]457 */
458static void
459ata_process_request(rtems_device_minor_number ctrl_minor)
460{
461    ata_req_t       *areq;
[ee4f57d]462    uint16_t         byte; /* emphasize that only 8 low bits is meaningful */
[109fc26]463    ata_queue_msg_t  msg;
[ee4f57d]464    uint8_t          i, dev;
465    uint16_t         val;
[a3d3d9a]466    uint16_t         data_bs; /* the number of 512-bytes sectors in one
467                               * data block
[109fc26]468                               */
[a3d3d9a]469    ISR_Level        level;
[3735f08]470   
[109fc26]471    /* if no requests to controller then do nothing */
[b9c38ed]472    if (rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs))
[109fc26]473        return;
474
475    /* get first request in the controller's queue */
476    _ISR_Disable(level);
477    areq = (ata_req_t *)(ata_ide_ctrls[ctrl_minor].reqs.first);
478    _ISR_Enable(level);
[a3d3d9a]479
[109fc26]480    /* get ATA device identifier (0 or 1) */
[a3d3d9a]481    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
[109fc26]482           IDE_REGISTER_DEVICE_HEAD_DEV;
483
484    /* get data block size */
[a3d3d9a]485    data_bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ?
486              ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1;
487
[109fc26]488    /* execute device select protocol */
[a3d3d9a]489    ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD,
[109fc26]490                                  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]);
[a3d3d9a]491
[109fc26]492    do {
493        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
[a3d3d9a]494    } while ((byte & IDE_REGISTER_STATUS_BSY) ||
[109fc26]495             (!(byte & IDE_REGISTER_STATUS_DRDY)));
496
497    /* fill in all  necessary registers on the controller */
498    for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++)
499    {
[ee4f57d]500        uint32_t   reg = (1 << i);
[109fc26]501        if (areq->regs.to_write & reg)
502            ide_controller_write_register(ctrl_minor, i, areq->regs.regs[i]);
503    }
504
[3735f08]505#ifdef DEBUG
506    printf("ata_process_request: type: %d\n", areq->type);
507#endif
508   
[109fc26]509    /* continue to execute ATA protocols depending on type of request */
510    if (areq->type == ATA_COMMAND_TYPE_PIO_OUT)
511    {
512        do {
[a3d3d9a]513            ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
[109fc26]514                                         &byte);
515        } while (byte & IDE_REGISTER_STATUS_BSY);
516
517        if (byte & IDE_REGISTER_STATUS_DRQ)
518        {
519            ide_controller_write_data_block(
[a3d3d9a]520                ctrl_minor,
[109fc26]521                MIN(data_bs, areq->cnt) * ATA_SECTOR_SIZE,
522                areq->breq->bufs, &areq->cbuf,
523                &areq->pos);
524            areq->cnt -= MIN(data_bs, areq->cnt);
[a3d3d9a]525        }
[109fc26]526        else
[a3d3d9a]527        {
[109fc26]528            if (IDE_Controller_Table[ctrl_minor].int_driven == 0)
529            {
530                ide_controller_read_register(
[a3d3d9a]531                    ctrl_minor,
[109fc26]532                    IDE_REGISTER_ALTERNATE_STATUS_OFFSET,
533                    &val);
534                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
535                                             &val);
536
[a3d3d9a]537                ATA_SEND_EVT(msg, ATA_MSG_ERROR_EVT, ctrl_minor,
[109fc26]538                             RTEMS_IO_ERROR);
539            }
[a3d3d9a]540        }
[109fc26]541    }
542
543    if (IDE_Controller_Table[ctrl_minor].int_driven == 0)
544    {
545        do {
[a3d3d9a]546            ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
[109fc26]547                                         &byte);
548        } while (byte & IDE_REGISTER_STATUS_BSY);
[a3d3d9a]549
[109fc26]550        ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
[a3d3d9a]551    }
[109fc26]552}
553
[a3d3d9a]554/* ata_request_done --
[109fc26]555 *     Extract request from controller queue, execute callback if necessary
556 *     and process next request for the controller.
[a3d3d9a]557 *
[109fc26]558 * PARAMETERS:
[a3d3d9a]559 *     areq       - ATA request
[109fc26]560 *     ctrl_minor - controller identifier
561 *     status     - status with which request has been done
562 *     error      - error, if status != RTEMS_SUCCESSFUL
563 *
564 * RETURNS:
565 *     NONE
566 */
567static inline void
568ata_request_done(ata_req_t *areq, rtems_device_minor_number ctrl_minor,
569                 rtems_status_code status, int error)
570{
571    assert(areq);
572
[3735f08]573#ifdef DEBUG
574    printf("ata_request_done: entry\n");
575#endif
576   
[109fc26]577    ATA_EXEC_CALLBACK(areq, status, error);
[b9c38ed]578    rtems_chain_extract(&areq->link);
[3735f08]579   
[b9c38ed]580    if (!rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs))
[109fc26]581    {
[3735f08]582        free(areq);
[109fc26]583        ata_process_request(ctrl_minor);
584        return;
585    }
[3735f08]586   
[3d14a45]587    free(areq);
[3735f08]588   
589#ifdef DEBUG
590    printf("ata_request_done: exit\n");
591#endif
[109fc26]592}
593
[a3d3d9a]594/* ata_non_data_request_done --
[109fc26]595 *     Set up request status and release request's semaphore.
[a3d3d9a]596 *
[109fc26]597 * PARAMETERS:
[a3d3d9a]598 *     areq       - ATA request
[109fc26]599 *     ctrl_minor - controller identifier
600 *     status     - status with which request has been done
601 *     error      - error, if status != RTEMS_SUCCESSFUL
602 *
603 * RETURNS:
604 *     NONE
605 */
606static inline void
[a3d3d9a]607ata_non_data_request_done(ata_req_t *areq,
[109fc26]608                          rtems_device_minor_number ctrl_minor,
609                          rtems_status_code status, int error)
610{
611    areq->status = status;
612    areq->error = error;
613    rtems_semaphore_release(areq->sema);
614}
615
616
[a3d3d9a]617/* ata_add_to_controller_queue --
[109fc26]618 *     Add request to the controller's queue.
[a3d3d9a]619 *
[109fc26]620 * PARAMETERS:
621 *     ctrl_minor - controller identifier
[a3d3d9a]622 *     areq       - ATA request
[109fc26]623 *
624 * RETURNS:
625 *     NONE
626 */
627static void
[a3d3d9a]628ata_add_to_controller_queue(rtems_device_minor_number  ctrl_minor,
[109fc26]629                            ata_req_t                 *areq)
630{
[3735f08]631    PREEMPTION_KEY(key);
632   
633    DISABLE_PREEMPTION(key);
634   
[b9c38ed]635    rtems_chain_append(&ata_ide_ctrls[ctrl_minor].reqs, &areq->link);
636    if (rtems_chain_has_only_one_node(&ata_ide_ctrls[ctrl_minor].reqs))
[109fc26]637    {
[d5ed9e1]638
[109fc26]639        ata_queue_msg_t msg;
640
641#ifdef DEBUG
[d5ed9e1]642        uint16_t      val;
[a3d3d9a]643        /*
[109fc26]644         * read IDE_REGISTER_ALTERNATE_STATUS instead IDE_REGISTER_STATUS
645         * to prevent clearing of pending interrupt
646         */
[a3d3d9a]647        ide_controller_read_register(ctrl_minor,
648                                     IDE_REGISTER_ALTERNATE_STATUS,
[109fc26]649                                     &val);
650        if (val & IDE_REGISTER_STATUS_BSY)
651            return;
652#endif
653        ATA_SEND_EVT(msg, ATA_MSG_PROCESS_NEXT_EVT, ctrl_minor, 0);
[a3d3d9a]654    }
[3735f08]655
656    ENABLE_PREEMPTION(key);
[a3d3d9a]657}
[109fc26]658
659
[a3d3d9a]660/* ata_interrupt_handler --
[109fc26]661 *     ATA driver interrrupt handler. If interrrupt happend it mapped it to
662 *     controller (controllerS, if a number of controllers share one int line)
663 *     and generates ATA event(s).
[a3d3d9a]664 *
[109fc26]665 * PARAMETERS:
[a3d3d9a]666 *     vec - interrupt vector
[109fc26]667 *
668 * RETURNS:
669 *     NONE
670 */
[d5ed9e1]671#if defined(ATA_USE_OLD_EXCEPTIONS)
[109fc26]672rtems_isr
673ata_interrupt_handler(rtems_vector_number vec)
674{
[b9c38ed]675    rtems_chain_node *the_node = ((rtems_chain_control *)(&ata_int_vec[vec]))->first;
[109fc26]676    ata_queue_msg_t  msg;
[ee4f57d]677    uint16_t         byte; /* emphasize that only 8 low bits is meaningful */
[a3d3d9a]678
[b9c38ed]679    for ( ; !rtems_chain_is_tail(&ata_int_vec[vec], the_node) ; )
[109fc26]680    {
681        /* if (1) - is temporary hack - currently I don't know how to identify
682         * controller which asserted interrupt if few controllers share one
683         * interrupt line
684         */
685        if (1)
686        {
687            msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor;
[a3d3d9a]688            ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS,
[109fc26]689                                         &byte);
[a3d3d9a]690            ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0);
[109fc26]691        }
692        the_node = the_node->next;
[a3d3d9a]693    }
[109fc26]694}
[d5ed9e1]695#else
696void ata_interrupt_handler(rtems_irq_hdl_param handle)
697{
698  int ata_irq_chain_index = (int) handle;
[b9c38ed]699    rtems_chain_node *the_node =
[d5ed9e1]700      ata_irq_chain[ata_irq_chain_index].irq_chain.last;
701    ata_queue_msg_t  msg;
702    uint16_t       byte; /* emphasize that only 8 low bits is meaningful */
703
704
[b9c38ed]705    for ( ; !rtems_chain_is_tail(&ata_irq_chain[ata_irq_chain_index].irq_chain,
[d5ed9e1]706                           the_node) ; )
707    {
708        /* if (1) - is temporary hack - currently I don't know how to identify
709         * controller which asserted interrupt if few controllers share one
710         * interrupt line
711         */
712        if (1)
713        {
714            msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor;
715            ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS,
716                                         &byte);
717            ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0);
718        }
719        the_node = the_node->next;
720    }
721}
722
723void ata_interrupt_on(const rtems_irq_connect_data *ptr)
724  {
725
726    /* enable ATA device interrupt */
727    ide_controller_write_register(0,
728                                  IDE_REGISTER_DEVICE_CONTROL_OFFSET,
729                                  0x00
730                                 );
731  }
732
733
734void ata_interrupt_off(const rtems_irq_connect_data *ptr)
735  {
736
737    /* disable ATA device interrupt */
738    ide_controller_write_register(0,
739                                  IDE_REGISTER_DEVICE_CONTROL_OFFSET,
740                                  IDE_REGISTER_DEVICE_CONTROL_nIEN
741                                 );
742  }
743
744
745int ata_interrupt_isOn(const rtems_irq_connect_data *ptr)
746  {
747  uint16_t byte; /* emphasize that only 8 low bits is meaningful */
748
749    /* return int. status od ATA device */
750    ide_controller_read_register(0,
751                                IDE_REGISTER_DEVICE_CONTROL_OFFSET,
752                                &byte
753                                );
754
755    return !(byte & IDE_REGISTER_DEVICE_CONTROL_nIEN);
756  }
757
758
759static rtems_irq_connect_data ata_irq_data =
760  {
761
762    0, /* filled out before use... */
[397060c]763    ata_interrupt_handler,/* filled out before use... */
764    NULL,
765    ata_interrupt_on,
766    ata_interrupt_off,
767    ata_interrupt_isOn
[d5ed9e1]768  };
769#endif
[109fc26]770
[a3d3d9a]771/* ata_pio_in_protocol --
[109fc26]772 *     ATA PIO_IN protocol implementation, see specification
[a3d3d9a]773 *
[109fc26]774 * PARAMETERS:
775 *     ctrl_minor - controller identifier
[a3d3d9a]776 *     areq       - ATA request
[109fc26]777 *
778 * RETURNS:
779 *     NONE
780 */
781static inline void
782ata_pio_in_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq)
783{
[ee4f57d]784    uint16_t        bs, val;
785    uint8_t         dev;
786    uint32_t        min_val;
[109fc26]787    ata_queue_msg_t msg;
[a3d3d9a]788
789    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
[109fc26]790           IDE_REGISTER_DEVICE_HEAD_DEV;
791
[a3d3d9a]792    bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ?
793         ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1;
[109fc26]794    min_val = MIN(bs, areq->cnt);
[a3d3d9a]795
796    ide_controller_read_data_block(ctrl_minor, min_val * ATA_SECTOR_SIZE,
[109fc26]797                                   areq->breq->bufs, &areq->cbuf, &areq->pos);
[a3d3d9a]798
[109fc26]799    areq->cnt -= min_val;
800    if (areq->cnt == 0)
801    {
802        ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL, RTEMS_SUCCESSFUL);
803    }
804    else if (IDE_Controller_Table[ctrl_minor].int_driven == 0)
805    {
806        do {
807           ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val);
808        } while (val & IDE_REGISTER_STATUS_BSY);
[a3d3d9a]809
[109fc26]810        ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
811    }
812}
813
[a3d3d9a]814/* ata_pio_out_protocol --
[109fc26]815 *     ATA PIO_OUT protocol implementation, see specification
[a3d3d9a]816 *
[109fc26]817 * PARAMETERS:
818 *     ctrl_minor - controller identifier
[a3d3d9a]819 *     areq       - ATA request
[109fc26]820 *
821 * RETURNS:
822 *     NONE
823 */
824static inline void
825ata_pio_out_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq)
826{
[ee4f57d]827    uint16_t        bs, val;
828    uint8_t         dev;
829    uint32_t        min_val;
[109fc26]830    ata_queue_msg_t msg;
[a3d3d9a]831
[3735f08]832#ifdef DEBUG
833    printf("ata_pio_out_protocol:\n");
834#endif
835   
[a3d3d9a]836    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
[109fc26]837           IDE_REGISTER_DEVICE_HEAD_DEV;
838
[a3d3d9a]839    bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ?
840         ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1;
[109fc26]841
[a3d3d9a]842    min_val = MIN(bs, areq->cnt);
[109fc26]843
844    if (areq->cnt == 0)
845    {
846        ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL, RTEMS_SUCCESSFUL);
847    }
[a3d3d9a]848    else
[109fc26]849    {
850        ide_controller_write_data_block(ctrl_minor, min_val * ATA_SECTOR_SIZE,
[a3d3d9a]851                                        areq->breq->bufs, &areq->cbuf,
[109fc26]852                                        &areq->pos);
853        areq->cnt -= min_val;
854        if (IDE_Controller_Table[ctrl_minor].int_driven == 0)
855        {
856            do {
[a3d3d9a]857                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
[109fc26]858                                             &val);
859            } while (val & IDE_REGISTER_STATUS_BSY);
860
861            ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
862        }
863  }
864}
865
[a3d3d9a]866/* ata_queue_task --
[109fc26]867 *     Task which manages ATA driver events queue.
[a3d3d9a]868 *
[109fc26]869 * PARAMETERS:
870 *     arg - ignored
871 *
872 * RETURNS:
873 *     NONE
874 *
875 * NOTES:
[a3d3d9a]876 *     should be non-preemptive
[109fc26]877 */
878static rtems_task
879ata_queue_task(rtems_task_argument arg)
880{
881    ata_queue_msg_t            msg;
[41a1c334]882    size_t                     size;
[109fc26]883    ata_req_t                 *areq;
884    rtems_device_minor_number  ctrl_minor;
[ee4f57d]885    uint16_t                   val;
886    uint16_t                   val1;
[109fc26]887    rtems_status_code          rc;
888    ISR_Level                  level;
[3735f08]889   
890    PREEMPTION_KEY(key);
[109fc26]891
[3735f08]892    DISABLE_PREEMPTION(key);
893   
[109fc26]894    while (1)
895    {
[3735f08]896        ENABLE_PREEMPTION(key);
897       
[109fc26]898        /* get event which has happend */
[a3d3d9a]899        rc = rtems_message_queue_receive(ata_queue_id, &msg, &size, RTEMS_WAIT,
[109fc26]900                                         RTEMS_NO_TIMEOUT);
901        if (rc != RTEMS_SUCCESSFUL)
902            rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
[a3d3d9a]903
[109fc26]904        /* get controller on which event has happend */
905        ctrl_minor = msg.ctrl_minor;
[a3d3d9a]906
[3735f08]907        DISABLE_PREEMPTION(key);
908       
[109fc26]909        /* get current request to the controller */
[a3d3d9a]910        _ISR_Disable(level);
[109fc26]911        areq = (ata_req_t *)(ata_ide_ctrls[ctrl_minor].reqs.first);
912        _ISR_Enable(level);
[3735f08]913       
[109fc26]914        switch(msg.type)
915        {
916            case ATA_MSG_PROCESS_NEXT_EVT:
917                /* process next request in the controller queue */
918                ata_process_request(ctrl_minor);
919                break;
920
921            case ATA_MSG_SUCCESS_EVT:
[a3d3d9a]922                /*
923                 * finish processing of current request with successful
924                 * status and start processing of the next request in the
[109fc26]925                 * controller queue
926                 */
[a3d3d9a]927                ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL,
[109fc26]928                                 msg.error);
929                break;
[a3d3d9a]930
[109fc26]931            case ATA_MSG_ERROR_EVT:
[a3d3d9a]932                /*
933                 * finish processing of current request with error
934                 * status and start processing of the next request in the
[109fc26]935                 * controller queue
936                 */
[a3d3d9a]937                ata_request_done(areq, ctrl_minor, RTEMS_UNSATISFIED,
[109fc26]938                                 msg.error);
939                break;
[a3d3d9a]940
[109fc26]941            case ATA_MSG_GEN_EVT:
[a3d3d9a]942                /*
943                 * continue processing of the current request to the
944                 * controller according to current request state and
[109fc26]945                 * ATA protocol
946                 */
[a3d3d9a]947                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
[109fc26]948                                           &val);
949                /* process error case */
950                if (val & IDE_REGISTER_STATUS_ERR)
[a3d3d9a]951                {
952                    ide_controller_read_register(ctrl_minor,
953                                                 IDE_REGISTER_ERROR,
[109fc26]954                                                 &val);
955                    if (areq->type == ATA_COMMAND_TYPE_NON_DATA)
[a3d3d9a]956                        ata_non_data_request_done(areq, ctrl_minor,
957                                                  RTEMS_UNSATISFIED,
[109fc26]958                                                  RTEMS_IO_ERROR);
[a3d3d9a]959                    else
960                        ata_request_done(areq, ctrl_minor, RTEMS_UNSATISFIED,
[109fc26]961                                         RTEMS_IO_ERROR);
[a3d3d9a]962                    break;
[109fc26]963                }
964
965                switch(areq->type)
966                {
967                    case ATA_COMMAND_TYPE_PIO_IN:
968                        ata_pio_in_protocol(ctrl_minor, areq);
969                        break;
[a3d3d9a]970
[109fc26]971                    case ATA_COMMAND_TYPE_PIO_OUT:
972                        ata_pio_out_protocol(ctrl_minor, areq);
973                        break;
[a3d3d9a]974
[109fc26]975                    case ATA_COMMAND_TYPE_NON_DATA:
[a3d3d9a]976                        ide_controller_read_register(ctrl_minor,
977                                                      IDE_REGISTER_ERROR,
[109fc26]978                                                     &val1);
979                        ata_non_data_request_done(areq, ctrl_minor,
980                                                  RTEMS_SUCCESSFUL,
981                                                  val1);
982                        break;
[a3d3d9a]983
[109fc26]984                    default:
[d5ed9e1]985#ifdef DEBUG
[109fc26]986                        printf("ata_queue_task: non-supported command type\n");
[d5ed9e1]987#endif
[109fc26]988                        ata_request_done(areq, ctrl_minor,
989                                         RTEMS_UNSATISFIED,
990                                         RTEMS_NOT_IMPLEMENTED);
[a3d3d9a]991                        break;
[109fc26]992                }
[a3d3d9a]993                break;
[109fc26]994
995            default:
[3735f08]996#ifdef DEBUG
997                printf("ata_queue_task: internal error\n");
998                rtems_task_delete (RTEMS_SELF);
999#endif
[109fc26]1000                rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
1001                break;
1002        }
1003    }
1004}
1005
[a3d3d9a]1006/* ata_ioctl --
[109fc26]1007 *     ATA driver ioctl interface.
[a3d3d9a]1008 *
[109fc26]1009 * PARAMETERS:
1010 *     device - device identifier
1011 *     cmd    - command
1012 *     argp   - arguments
1013 *
1014 * RETURNS:
1015 *     depend on 'cmd'
1016 */
[a3d3d9a]1017int
[109fc26]1018ata_ioctl(dev_t device, int cmd, void *argp)
1019{
1020    rtems_status_code         status;
1021    rtems_device_minor_number rel_minor;
[a3d3d9a]1022
[109fc26]1023    rel_minor = (rtems_filesystem_dev_minor_t(device)) /
1024                ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE;
1025
[a3d3d9a]1026    /*
[109fc26]1027     * in most cases this means that device 'device' is not an registred ATA
1028     * device
[a3d3d9a]1029     */
[109fc26]1030    if (ata_devs[rel_minor].device == ATA_UNDEFINED_VALUE)
1031    {
1032        errno = ENODEV;
1033        return -1;
[a3d3d9a]1034    }
[109fc26]1035
[a3d3d9a]1036    switch (cmd)
[109fc26]1037    {
[3735f08]1038        case RTEMS_BLKIO_REQUEST:
1039            status = ata_io_data_request(device, (rtems_blkdev_request *)argp);
[109fc26]1040            break;
[a3d3d9a]1041
[109fc26]1042        case ATAIO_SET_MULTIPLE_MODE:
1043            status = ata_non_data_request(device, cmd, argp);
1044            break;
[a3d3d9a]1045
[3735f08]1046        case RTEMS_BLKDEV_CAPABILITIES:
1047            *((uint32_t*) argp)  = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
1048            status = RTEMS_SUCCESSFUL;
1049            break;
1050
[109fc26]1051        default:
1052            errno = EBADRQC;
1053            return -1;
1054            break;
1055    }
1056
1057    if (status != RTEMS_SUCCESSFUL)
1058    {
1059        errno = EIO;
[a3d3d9a]1060        return -1;
[109fc26]1061    }
1062    return 0;
1063}
1064
1065/*
1066 * ata_initialize --
1067 *     Initializes all ATA devices found on initialized IDE controllers.
[a3d3d9a]1068 *
[109fc26]1069 * PARAMETERS:
1070 *     major - device major number
1071 *     minor - device minor number
1072 *     args   - arguments
1073 *
1074 * RETURNS:
1075 *     RTEMS_SUCCESSFUL on success, or error code if
[a3d3d9a]1076 *     error occured
[109fc26]1077 */
[a3d3d9a]1078rtems_device_driver
[3735f08]1079rtems_ata_initialize(rtems_device_major_number major,
1080                     rtems_device_minor_number minor_arg,
1081                     void *args)
[109fc26]1082{
[ee4f57d]1083    uint32_t           ctrl_minor;
[109fc26]1084    rtems_status_code  status;
1085    ata_req_t          areq;
[a3d3d9a]1086    blkdev_request1    breq;
[ee4f57d]1087    uint8_t            i, dev = 0;
1088    uint16_t          *buffer;
1089    uint16_t           ec;
[109fc26]1090    char               name[ATA_MAX_NAME_LENGTH];
1091    dev_t              device;
1092    ata_int_st_t      *int_st;
[c9b005a9]1093
[d5ed9e1]1094#if defined(ATA_USE_OLD_EXCEPTIONS)
[109fc26]1095    rtems_isr_entry    old_isr;
[d5ed9e1]1096#else
1097    int ata_irq_chain_use;
1098#endif
[109fc26]1099
1100    if (ata_initialized)
1101        return RTEMS_SUCCESSFUL;
[a3d3d9a]1102
[109fc26]1103    /* initialization of disk devices library */
1104    status = rtems_disk_io_initialize();
1105    if (status != RTEMS_SUCCESSFUL)
1106        return status;
[a3d3d9a]1107
[3735f08]1108#ifdef SAFE
1109#ifdef SAFE_MUTEX
1110    status = rtems_semaphore_create (rtems_build_name ('A', 'T', 'A', 'L'),
1111                                     1, RTEMS_ATA_LOCK_ATTRIBS, 0,
1112                                     &ata_lock);
1113    if (status != RTEMS_SUCCESSFUL)
1114        return status;
1115#endif
1116#endif
1117   
[109fc26]1118    /* create queue for asynchronous requests handling */
1119    status = rtems_message_queue_create(
1120                 rtems_build_name('A', 'T', 'A', 'Q'),
1121                 ATA_DRIVER_MESSAGE_QUEUE_SIZE,
1122                 sizeof(ata_queue_msg_t),
1123                 RTEMS_FIFO | RTEMS_LOCAL,
1124                 &ata_queue_id);
1125    if (status != RTEMS_SUCCESSFUL)
1126    {
1127        rtems_disk_io_done();
1128        return status;
[a3d3d9a]1129    }
[109fc26]1130
[a3d3d9a]1131    /*
1132     * create ATA driver task, see comments for task implementation for
1133     * details
[109fc26]1134     */
1135    status = rtems_task_create(
1136                 rtems_build_name ('A', 'T', 'A', 'T'),
[3735f08]1137                 ((rtems_ata_driver_task_priority > 0)
1138                  ? rtems_ata_driver_task_priority
[c9b005a9]1139                  : ATA_DRIVER_TASK_DEFAULT_PRIORITY),
[109fc26]1140                 ATA_DRIVER_TASK_STACK_SIZE,
[3735f08]1141                 RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
[109fc26]1142                 RTEMS_INTERRUPT_LEVEL(0),
1143                 RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
1144                 &ata_task_id);
1145    if (status != RTEMS_SUCCESSFUL)
1146    {
1147        rtems_message_queue_delete(ata_queue_id);
1148        rtems_disk_io_done();
1149        return status;
[a3d3d9a]1150    }
1151
1152    /*
1153     * start ATA driver task. Actually the task will not start immediately -
[109fc26]1154     * it will start only after multitasking support will be started
[a3d3d9a]1155     */
1156    status = rtems_task_start(ata_task_id, ata_queue_task, 0);
[109fc26]1157    if (status != RTEMS_SUCCESSFUL)
1158    {
1159        rtems_task_delete(ata_task_id);
1160        rtems_message_queue_delete(ata_queue_id);
1161        rtems_disk_io_done();
1162        return status;
[a3d3d9a]1163    }
1164
[509fec9c]1165    buffer = (uint16_t*)malloc(ATA_SECTOR_SIZE);
[109fc26]1166    if (buffer == NULL)
1167    {
1168        rtems_task_delete(ata_task_id);
1169        rtems_message_queue_delete(ata_queue_id);
1170        rtems_disk_io_done();
1171        return RTEMS_NO_MEMORY;
[a3d3d9a]1172    }
1173
[109fc26]1174    ata_devs_number = 0;
1175
1176    for (i = 0; i < (2 * IDE_CTRL_MAX_MINOR_NUMBER); i++)
1177        ata_devs[i].device = ATA_UNDEFINED_VALUE;
1178
[d5ed9e1]1179#if defined(ATA_USE_OLD_EXCEPTIONS)
[109fc26]1180    /* prepare ATA driver for handling  interrupt driven devices */
1181    for (i = 0; i < ATA_MAX_RTEMS_INT_VEC_NUMBER; i++)
[b9c38ed]1182        rtems_chain_initialize_empty(&ata_int_vec[i]);
[d5ed9e1]1183#else
1184    for (i = 0; i < ATA_IRQ_CHAIN_MAX_CNT; i++) {
[b9c38ed]1185      rtems_chain_initialize_empty(&(ata_irq_chain[i].irq_chain));
[d5ed9e1]1186    }
1187#endif
[109fc26]1188
[a3d3d9a]1189    /*
1190     * during ATA driver initialization EXECUTE DEVICE DIAGNOSTIC and
1191     * IDENTIFY DEVICE ATA command should be issued; for these purposes ATA
1192     * requests should be formed; ATA requests contain block device request,
[109fc26]1193     * so form block device request first
1194     */
1195    memset(&breq, 0, sizeof(blkdev_request1));
1196    breq.req.req_done = NULL;
1197    breq.req.done_arg = &breq;
1198    breq.req.bufnum = 1;
1199    breq.req.count = 1;
1200    breq.req.bufs[0].length = ATA_SECTOR_SIZE;
1201    breq.req.bufs[0].buffer = buffer;
1202
[a3d3d9a]1203    /*
[109fc26]1204     * for each presented IDE controller execute EXECUTE DEVICE DIAGNOSTIC
[a3d3d9a]1205     * ATA command; for each found device execute IDENTIFY DEVICE ATA
1206     * command
[109fc26]1207     */
1208    for (ctrl_minor = 0; ctrl_minor < IDE_Controller_Count; ctrl_minor++)
1209    if (IDE_Controller_Table[ctrl_minor].status == IDE_CTRL_INITIALIZED)
1210    {
[b9c38ed]1211        rtems_chain_initialize_empty(&ata_ide_ctrls[ctrl_minor].reqs);
[a3d3d9a]1212
[109fc26]1213        if (IDE_Controller_Table[ctrl_minor].int_driven == TRUE)
1214        {
1215            int_st = malloc(sizeof(ata_int_st_t));
1216            if (int_st == NULL)
1217            {
1218                free(buffer);
1219                rtems_task_delete(ata_task_id);
1220                rtems_message_queue_delete(ata_queue_id);
1221                rtems_disk_io_done();
1222                return RTEMS_NO_MEMORY;
[a3d3d9a]1223            }
[109fc26]1224
1225            int_st->ctrl_minor = ctrl_minor;
[d5ed9e1]1226#if defined(ATA_USE_OLD_EXCEPTIONS)
[109fc26]1227            status = rtems_interrupt_catch(
[a3d3d9a]1228                         ata_interrupt_handler,
1229                         IDE_Controller_Table[ctrl_minor].int_vec,
[109fc26]1230                         &old_isr);
[d5ed9e1]1231#else
1232            /*
1233             * FIXME: check existing entries. if they use the same
1234             * IRQ name, then append int_st to respective chain
1235             * otherwise, use new ata_irq_chain entry
1236             */
1237            ata_irq_chain_use = -1;
1238            for (i = 0;
1239                 ((i < ata_irq_chain_cnt) &&
1240                  (ata_irq_chain_use < 0));i++) {
1241              if (ata_irq_chain[i].name ==
1242                  IDE_Controller_Table[ctrl_minor].int_vec) {
1243                ata_irq_chain_use = i;
1244              }
1245            }
1246            if (ata_irq_chain_use < 0) {
1247              /*
1248               * no match found, try to use new channel entry
1249               */
1250              if (ata_irq_chain_cnt < ATA_IRQ_CHAIN_MAX_CNT) {
1251                ata_irq_chain_use = ata_irq_chain_cnt++;
1252
1253                ata_irq_chain[ata_irq_chain_use].name =
1254                  IDE_Controller_Table[ctrl_minor].int_vec;
1255                ata_irq_data.name   =
1256                  IDE_Controller_Table[ctrl_minor].int_vec;
1257                ata_irq_data.hdl    = ata_interrupt_handler;
[f610e83f]1258                ata_irq_data.handle = (rtems_irq_hdl_param) ctrl_minor;
[d5ed9e1]1259
1260                status = ((0 == BSP_install_rtems_irq_handler(&ata_irq_data))
1261                          ? RTEMS_INVALID_NUMBER
1262                          : RTEMS_SUCCESSFUL);
1263              }
1264              else {
1265                status = RTEMS_TOO_MANY;
1266              }
1267            }
1268#endif
[109fc26]1269            if (status != RTEMS_SUCCESSFUL)
1270            {
1271                free(int_st);
1272                free(buffer);
1273                rtems_task_delete(ata_task_id);
1274                rtems_message_queue_delete(ata_queue_id);
1275                rtems_disk_io_done();
1276                return status;
[a3d3d9a]1277            }
[d5ed9e1]1278#if defined(ATA_USE_OLD_EXCEPTIONS)
[b9c38ed]1279            rtems_chain_append(
[109fc26]1280                &ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec],
1281                &int_st->link);
[d5ed9e1]1282#else
[b9c38ed]1283            rtems_chain_append(
[d5ed9e1]1284                &(ata_irq_chain[ata_irq_chain_use].irq_chain),
1285                &int_st->link);
1286#endif
[109fc26]1287
1288            /* disable interrupts */
[a3d3d9a]1289            ide_controller_write_register(ctrl_minor,
1290                                          IDE_REGISTER_DEVICE_CONTROL_OFFSET,
[109fc26]1291                                          IDE_REGISTER_DEVICE_CONTROL_nIEN);
1292        }
1293
1294        /*
1295         * Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is
1296         * there any ATA device on the controller.
1297         */
1298        memset(&areq, 0, sizeof(ata_req_t));
1299        areq.type = ATA_COMMAND_TYPE_NON_DATA;
1300        areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
[a3d3d9a]1301        areq.regs.regs[IDE_REGISTER_COMMAND] =
[109fc26]1302                                  ATA_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC;
1303        areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);
1304
[3735f08]1305        areq.breq = (rtems_blkdev_request *)&breq;
[109fc26]1306
[a3d3d9a]1307        /*
1308         * Process the request. Special processing of requests on
1309         * initialization phase is needed because at this moment there
[109fc26]1310         * is no multitasking enviroment
1311         */
1312        ata_process_request_on_init_phase(ctrl_minor, &areq);
1313
1314        /*
1315         * check status of I/O operation
1316         */
1317        if (breq.req.status != RTEMS_SUCCESSFUL)
1318            continue;
[a3d3d9a]1319
1320        /* disassemble returned diagnostic codes */
[109fc26]1321        if (breq.req.error == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT)
1322        {
1323            ATA_DEV_INFO(ctrl_minor, 0).present = 1;
[a3d3d9a]1324            ATA_DEV_INFO(ctrl_minor,1).present = 1;
[109fc26]1325        }
1326        else if (breq.req.error == ATA_DEV0_PASSED_DEV1_FAILED)
1327        {
1328            ATA_DEV_INFO(ctrl_minor,0).present = 1;
1329            ATA_DEV_INFO(ctrl_minor,1).present = 0;
1330        }
1331        else if (breq.req.error < ATA_DEV1_PASSED_DEV0_FAILED)
1332        {
1333            ATA_DEV_INFO(ctrl_minor,0).present = 0;
1334            ATA_DEV_INFO(ctrl_minor,1).present = 1;
1335        }
1336        else
1337        {
1338            ATA_DEV_INFO(ctrl_minor, 0).present = 0;
1339            ATA_DEV_INFO(ctrl_minor, 1).present = 0;
1340        }
1341
1342        /* refine the returned codes */
1343        if (ATA_DEV_INFO(ctrl_minor, 1).present != 0)
1344        {
1345            ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec);
1346            if (ec & ATA_DEV1_PASSED_DEV0_FAILED)
1347                ATA_DEV_INFO(ctrl_minor, 1).present = 1;
1348            else
1349                ATA_DEV_INFO(ctrl_minor, 1).present = 0;
1350        }
1351
1352        /* for each found ATA device obtain it configuration */
1353        for (dev = 0; dev < 2; dev++)
1354        if (ATA_DEV_INFO(ctrl_minor, dev).present)
1355        {
1356            /*
[a3d3d9a]1357             * Issue DEVICE IDENTIFY ATA command and get device
1358             * configuration
[109fc26]1359             */
1360            memset(&areq, 0, sizeof(ata_req_t));
1361            areq.type = ATA_COMMAND_TYPE_PIO_IN;
1362            areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
[a3d3d9a]1363            areq.regs.regs[IDE_REGISTER_COMMAND] =
[109fc26]1364                                              ATA_COMMAND_IDENTIFY_DEVICE;
1365            areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS);
[3735f08]1366            areq.breq = (rtems_blkdev_request *)&breq;
[a3d3d9a]1367
[109fc26]1368            areq.cnt = breq.req.count;
1369
1370            areq.regs.regs[IDE_REGISTER_DEVICE_HEAD] |=
1371                                    (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS);
1372
[a3d3d9a]1373            /*
1374             * Process the request. Special processing of requests on
1375             * initialization phase is needed because at this moment there
[109fc26]1376             * is no multitasking enviroment
1377             */
1378            ata_process_request_on_init_phase(ctrl_minor, &areq);
1379
1380            /* check status of I/O operation */
1381            if (breq.req.status != RTEMS_SUCCESSFUL)
1382                continue;
1383
1384            /*
[a3d3d9a]1385             * Parse returned device configuration and fill in ATA internal
[109fc26]1386             * device info structure
1387             */
[a3d3d9a]1388            ATA_DEV_INFO(ctrl_minor, dev).cylinders =
[109fc26]1389                CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_CLNDS]);
[a3d3d9a]1390            ATA_DEV_INFO(ctrl_minor, dev).heads =
[109fc26]1391                CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_HEADS]);
[a3d3d9a]1392            ATA_DEV_INFO(ctrl_minor, dev).sectors =
[109fc26]1393                CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_SECS]);
[a3d3d9a]1394            ATA_DEV_INFO(ctrl_minor, dev).lba_sectors =
1395                (CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS0]) << 16) +
[109fc26]1396                 CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS1]);
[a3d3d9a]1397            ATA_DEV_INFO(ctrl_minor, dev).lba_avaible =
[109fc26]1398                (CF_LE_W(buffer[ATA_IDENT_WORD_CAPABILITIES]) >> 9) & 0x1;
[a3d3d9a]1399            ATA_DEV_INFO(ctrl_minor, dev).max_multiple =
[509fec9c]1400                (uint8_t) (CF_LE_W(buffer[ATA_IDENT_WORD_RW_MULT]));
[a3d3d9a]1401            ATA_DEV_INFO(ctrl_minor, dev).current_multiple =
1402                (CF_LE_W(buffer[ATA_IDENT_WORD_MULT_SECS]) & 0x100) ?
[509fec9c]1403                (uint8_t)(CF_LE_W(buffer[ATA_IDENT_WORD_MULT_SECS])) :
[109fc26]1404                 0;
1405
[a3d3d9a]1406            if ((CF_LE_W(buffer[ATA_IDENT_WORD_FIELD_VALIDITY]) &
[109fc26]1407                 ATA_IDENT_BIT_VALID) == 0) {
1408              /* no "supported modes" info -> use default */
1409              ATA_DEV_INFO(ctrl_minor, dev).mode_active = ATA_MODES_PIO3;
1410            }
1411            else {
[bf474880]1412              ATA_DEV_INFO(ctrl_minor, dev).modes_available =
[109fc26]1413                ((CF_LE_W(buffer[64]) & 0x1) ? ATA_MODES_PIO3 : 0) |
1414                ((CF_LE_W(buffer[64]) & 0x2) ? ATA_MODES_PIO4 : 0) |
1415                ((CF_LE_W(buffer[63]) & 0x1) ? ATA_MODES_DMA0 : 0) |
[a3d3d9a]1416                ((CF_LE_W(buffer[63]) & 0x2) ?
[109fc26]1417                 ATA_MODES_DMA0 | ATA_MODES_DMA1 : 0) |
[a3d3d9a]1418                ((CF_LE_W(buffer[63]) & 0x4) ?
[109fc26]1419                 ATA_MODES_DMA0 | ATA_MODES_DMA1 | ATA_MODES_DMA2 : 0);
[bf474880]1420              if (ATA_DEV_INFO(ctrl_minor, dev).modes_available == 0)
[109fc26]1421                continue;
[a3d3d9a]1422              /*
[109fc26]1423               * choose most appropriate ATA device data I/O speed supported
1424               * by the controller
1425               */
1426              status = ide_controller_config_io_speed(
[a3d3d9a]1427                ctrl_minor,
[bf474880]1428                ATA_DEV_INFO(ctrl_minor, dev).modes_available);
[109fc26]1429              if (status != RTEMS_SUCCESSFUL)
1430                continue;
[a3d3d9a]1431            }
[109fc26]1432            /*
1433             * Ok, let register new ATA device in the system
1434             */
1435            ata_devs[ata_devs_number].ctrl_minor = ctrl_minor;
1436            ata_devs[ata_devs_number].device = dev;
1437
[c54764f9]1438            /* The space leaves a hole for the character. */
1439            strcpy(name, "/dev/hd ");
1440            name[7] = 'a' + 2 * ctrl_minor + dev;
1441
[109fc26]1442            device = rtems_filesystem_make_dev_t(
[a3d3d9a]1443                         major,
1444                         (ata_devs_number *
[109fc26]1445                          ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE));
1446
[a3d3d9a]1447            status = rtems_disk_create_phys(device, ATA_SECTOR_SIZE,
1448                ATA_DEV_INFO(ctrl_minor, dev).lba_avaible ?
1449                ATA_DEV_INFO(ctrl_minor, dev).lba_sectors :
[109fc26]1450                (ATA_DEV_INFO(ctrl_minor, dev).heads *
1451                 ATA_DEV_INFO(ctrl_minor, dev).cylinders *
1452                 ATA_DEV_INFO(ctrl_minor, dev).sectors),
[3735f08]1453                (rtems_block_device_ioctl) ata_ioctl, name);
[109fc26]1454            if (status != RTEMS_SUCCESSFUL)
1455            {
1456                ata_devs[ata_devs_number].device = ATA_UNDEFINED_VALUE;
1457                continue;
[a3d3d9a]1458            }
[109fc26]1459            ata_devs_number++;
1460        }
1461        if (IDE_Controller_Table[ctrl_minor].int_driven == TRUE)
[a3d3d9a]1462        {
1463            ide_controller_write_register(ctrl_minor,
1464                                          IDE_REGISTER_DEVICE_CONTROL_OFFSET,
[109fc26]1465                                          0x00);
1466        }
1467    }
1468
1469    free(buffer);
1470    ata_initialized = TRUE;
1471    return RTEMS_SUCCESSFUL;
1472}
1473
[a3d3d9a]1474/* ata_process_request_on_init_phase --
1475 *     Process the ATA request during system initialization. Request
[109fc26]1476 *     processing is syncronous and doesn't use multiprocessing enviroment.
[a3d3d9a]1477 *
[109fc26]1478 * PARAMETERS:
1479 *     ctrl_minor - controller identifier
1480 *     areq       - ATA request
1481 *
1482 * RETURNS:
[a3d3d9a]1483 *     NONE
[109fc26]1484 */
1485static void
1486ata_process_request_on_init_phase(rtems_device_minor_number  ctrl_minor,
1487                                  ata_req_t                 *areq)
1488{
[ee4f57d]1489    uint16_t           byte;/* emphasize that only 8 low bits is meaningful */
1490    uint8_t            i, dev;
1491    uint16_t           val, val1;
[a3d3d9a]1492    uint16_t           data_bs; /* the number of 512 bytes sectors into one
1493                                 * data block
[109fc26]1494                                 */
[89d19033]1495        unsigned           retries;
[109fc26]1496    assert(areq);
[a3d3d9a]1497
1498    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
[109fc26]1499           IDE_REGISTER_DEVICE_HEAD_DEV;
1500
[a3d3d9a]1501    data_bs = ATA_DEV_INFO(ctrl_minor, dev).current_multiple ?
1502              ATA_DEV_INFO(ctrl_minor, dev).current_multiple : 1;
1503
1504    ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD,
[109fc26]1505                                  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]);
[a3d3d9a]1506
[89d19033]1507        retries = 0;
[109fc26]1508    do {
1509        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
[89d19033]1510        /* If device (on INIT, i.e. it should be idle) is neither
1511         * busy nor ready something's fishy, i.e., there is probably
1512         * no device present.
1513         * I'd like to do a proper timeout but don't know of a portable
1514         * timeout routine (w/o using multitasking / rtems_task_wake_after())
1515         */
1516        if ( ! (byte & (IDE_REGISTER_STATUS_BSY | IDE_REGISTER_STATUS_DRDY)))
1517            retries++;
1518        else
1519            retries=0;
1520        if ( 10000 == retries ) {
1521            /* probably no drive connected */
1522            areq->breq->status = RTEMS_UNSATISFIED;
1523            areq->breq->error = RTEMS_IO_ERROR;
1524            return;
1525        }
[a3d3d9a]1526    } while ((byte & IDE_REGISTER_STATUS_BSY) ||
[109fc26]1527             (!(byte & IDE_REGISTER_STATUS_DRDY)));
1528
1529    for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++)
1530    {
[ee4f57d]1531        uint32_t   reg = (1 << i);
[109fc26]1532        if (areq->regs.to_write & reg)
[a3d3d9a]1533            ide_controller_write_register(ctrl_minor, i,
[109fc26]1534                                          areq->regs.regs[i]);
1535    }
1536
1537    do {
1538        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
1539    } while (byte & IDE_REGISTER_STATUS_BSY);
1540
1541    ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val);
1542    ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &val1);
1543
1544    if (val & IDE_REGISTER_STATUS_ERR)
1545    {
1546        areq->breq->status = RTEMS_UNSATISFIED;
1547        areq->breq->error = RTEMS_IO_ERROR;
1548        return;
1549    }
[a3d3d9a]1550
[109fc26]1551    switch(areq->type)
1552    {
1553        case ATA_COMMAND_TYPE_PIO_IN:
1554            ide_controller_read_data_block(
[a3d3d9a]1555                ctrl_minor,
[109fc26]1556                MIN(data_bs, areq->cnt) * ATA_SECTOR_SIZE,
1557                areq->breq->bufs, &areq->cbuf,
1558                &areq->pos);
[a3d3d9a]1559
[109fc26]1560            areq->cnt -= MIN(data_bs, areq->cnt);
1561            if (areq->cnt == 0)
1562            {
1563                areq->breq->status = RTEMS_SUCCESSFUL;
1564            }
[a3d3d9a]1565            else
[109fc26]1566            {
[a3d3d9a]1567                /*
1568                 * this shouldn't happend on the initialization
1569                 * phase!
[109fc26]1570                 */
[a3d3d9a]1571                rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
[109fc26]1572            }
1573            break;
[a3d3d9a]1574
[109fc26]1575        case ATA_COMMAND_TYPE_NON_DATA:
1576            areq->breq->status = RTEMS_SUCCESSFUL;
1577            areq->breq->error = val1;
1578            break;
[a3d3d9a]1579
[109fc26]1580        default:
[d5ed9e1]1581#ifdef DEBUG
[109fc26]1582            printf("ata_queue_task: non-supported command type\n");
[d5ed9e1]1583#endif
[109fc26]1584            areq->breq->status = RTEMS_UNSATISFIED;
1585            areq->breq->error = RTEMS_NOT_IMPLEMENTED;
[a3d3d9a]1586            break;
[109fc26]1587    }
1588}
Note: See TracBrowser for help on using the repository browser.