source: rtems/c/src/libchip/ide/ata.c @ fae3ab43

4.104.11
Last change on this file since fae3ab43 was fae3ab43, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 7, 2010 at 3:04:07 PM

2010-04-07 Joel Sherrill <joel.sherrill@…>

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