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

4.115
Last change on this file since 5d64fef2 was 5d64fef2, checked in by Sebastian Huber <sebastian.huber@…>, on 12/05/11 at 09:21:11

2011-12-05 Sebastian Huber <sebastian.huber@…>

PR 1975/misc

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