source: rtems/c/src/libchip/ide/ata.c @ 9f0a68c

4.115
Last change on this file since 9f0a68c was 9f0a68c, checked in by Sebastian Huber <sebastian.huber@…>, on 10/31/12 at 10:54:39

libblock: Block device transfer request API change

Add and use rtems_blkdev_request_done(). Block device transfer requests
must signal the completion status now with rtems_blkdev_request_done().
The return value of the block device IO control will be ignored for
transfer requests.

The first parameter of rtems_blkdev_request_cb is now the transfer
request structure.

Renamed rtems_blkdev_request::req_done to rtems_blkdev_request::done to
break third party drivers at compile time, otherwise this API change
would result in runtime errors.

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