source: rtems/c/src/libchip/ide/ata.c @ 5c587596

4.104.11
Last change on this file since 5c587596 was 5c587596, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Jan 19, 2010 at 9:10:03 AM

libblock API update

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