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

4.115
Last change on this file since f5194a9 was f5194a9, checked in by Sebastian Huber <sebastian.huber@…>, on 08/17/10 at 13:41:29

2010-08-17 Sebastian Huber <sebastian.huber@…>

  • libchip/ide/ata_internal.h, libchip/ide/ata.c: Moved code into separate functions. Added public ata_breq_init(), ata_identify_device(), and ata_process_request_on_init_phase() functions.
  • Property mode set to 100644
File size: 48.5 KB
Line 
1/*
2 * ata.c
3 *
4 * ATA RTEMS driver. ATA driver is hardware independant implementation of
5 * ATA-2 standart, 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, dev;
425    uint16_t         val;
426    ISR_Level        level;
427
428    /* if no requests to controller then do nothing */
429    if (rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs))
430        return;
431
432    /* get first request in the controller's queue */
433    _ISR_Disable(level);
434    areq = (ata_req_t *)(ata_ide_ctrls[ctrl_minor].reqs.first);
435    _ISR_Enable(level);
436
437    /* get ATA device identifier (0 or 1) */
438    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
439           IDE_REGISTER_DEVICE_HEAD_DEV;
440
441    /* execute device select protocol */
442    ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD,
443                                  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]);
444
445    do {
446        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
447    } while ((byte & IDE_REGISTER_STATUS_BSY) ||
448             (!(byte & IDE_REGISTER_STATUS_DRDY)));
449
450    /* fill in all  necessary registers on the controller */
451    for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++)
452    {
453        uint32_t   reg = (1 << i);
454        if (areq->regs.to_write & reg)
455            ide_controller_write_register(ctrl_minor, i, areq->regs.regs[i]);
456    }
457
458#if ATA_DEBUG
459    ata_printf("ata_process_request: type: %d\n", areq->type);
460#endif
461
462    /* continue to execute ATA protocols depending on type of request */
463    if (areq->type == ATA_COMMAND_TYPE_PIO_OUT)
464    {
465        do {
466            ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
467                                         &byte);
468        } while (byte & IDE_REGISTER_STATUS_BSY);
469
470        if (byte & IDE_REGISTER_STATUS_DRQ)
471        {
472            if (areq->cnt)
473            {
474              int ccbuf = areq->cbuf;
475              ide_controller_write_data_block(ctrl_minor,
476                                              areq->breq->bufs[0].length * areq->cnt,
477                                              areq->breq->bufs, &areq->cbuf,
478                                              &areq->pos);
479              ccbuf = areq->cbuf - ccbuf;
480              areq->cnt -= ccbuf;
481            }
482        }
483        else
484        {
485            if (IDE_Controller_Table[ctrl_minor].int_driven == false)
486            {
487                ide_controller_read_register(
488                    ctrl_minor,
489                    IDE_REGISTER_ALTERNATE_STATUS_OFFSET,
490                    &val);
491                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
492                                             &val);
493
494                ATA_SEND_EVT(msg, ATA_MSG_ERROR_EVT, ctrl_minor,
495                             RTEMS_IO_ERROR);
496            }
497        }
498    }
499
500    if (IDE_Controller_Table[ctrl_minor].int_driven == false)
501    {
502        do {
503            ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
504                                         &byte);
505        } while (byte & IDE_REGISTER_STATUS_BSY);
506
507        ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
508    }
509}
510
511/* ata_request_done --
512 *     Extract request from controller queue, execute callback if necessary
513 *     and process next request for the controller.
514 *
515 * PARAMETERS:
516 *     areq       - ATA request
517 *     ctrl_minor - controller identifier
518 *     status     - status with which request has been done
519 *     error      - error, if status != RTEMS_SUCCESSFUL
520 *
521 * RETURNS:
522 *     NONE
523 */
524static inline void
525ata_request_done(ata_req_t *areq, rtems_device_minor_number ctrl_minor,
526                 rtems_status_code status)
527{
528    assert(areq);
529
530#if ATA_DEBUG
531    ata_printf("ata_request_done: entry\n");
532#endif
533
534    ATA_EXEC_CALLBACK(areq, status);
535    rtems_chain_extract(&areq->link);
536
537    if (!rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs))
538    {
539        free(areq);
540        ata_process_request(ctrl_minor);
541        return;
542    }
543
544    free(areq);
545
546#if ATA_DEBUG
547    ata_printf("ata_request_done: exit\n");
548#endif
549}
550
551/* ata_non_data_request_done --
552 *     Set up request status and release request's semaphore.
553 *
554 * PARAMETERS:
555 *     areq       - ATA request
556 *     ctrl_minor - controller identifier
557 *     status     - status with which request has been done
558 *     error      - error, if status != RTEMS_SUCCESSFUL
559 *
560 * RETURNS:
561 *     NONE
562 */
563static inline void
564ata_non_data_request_done(ata_req_t *areq,
565                          rtems_device_minor_number ctrl_minor,
566                          rtems_status_code status, int info)
567{
568#if ATA_DEBUG
569    ata_printf("ata_non_data_request_done: entry\n");
570#endif
571
572    areq->status = status;
573    areq->info = info;
574    rtems_semaphore_release(areq->sema);
575}
576
577
578/* ata_add_to_controller_queue --
579 *     Add request to the controller's queue.
580 *
581 * PARAMETERS:
582 *     ctrl_minor - controller identifier
583 *     areq       - ATA request
584 *
585 * RETURNS:
586 *     NONE
587 */
588static void
589ata_add_to_controller_queue(rtems_device_minor_number  ctrl_minor,
590                            ata_req_t                 *areq)
591{
592    PREEMPTION_KEY(key);
593
594    DISABLE_PREEMPTION(key);
595
596    rtems_chain_append(&ata_ide_ctrls[ctrl_minor].reqs, &areq->link);
597    if (rtems_chain_has_only_one_node(&ata_ide_ctrls[ctrl_minor].reqs))
598    {
599
600        ata_queue_msg_t msg;
601
602#if ATA_DEBUG_DOES_NOT_WORK_WITH_QEMU
603        uint16_t      val;
604        /*
605         * read IDE_REGISTER_ALTERNATE_STATUS instead IDE_REGISTER_STATUS
606         * to prevent clearing of pending interrupt
607         */
608        ide_controller_read_register(ctrl_minor,
609                                     IDE_REGISTER_ALTERNATE_STATUS,
610                                     &val);
611        if (val & IDE_REGISTER_STATUS_BSY)
612            return;
613#endif
614        ATA_SEND_EVT(msg, ATA_MSG_PROCESS_NEXT_EVT, ctrl_minor, 0);
615    }
616
617    ENABLE_PREEMPTION(key);
618}
619
620
621/* ata_interrupt_handler --
622 *     ATA driver interrrupt handler. If interrrupt happend it mapped it to
623 *     controller (controllerS, if a number of controllers share one int line)
624 *     and generates ATA event(s).
625 *
626 * PARAMETERS:
627 *     vec - interrupt vector
628 *
629 * RETURNS:
630 *     NONE
631 */
632#if defined(CPU_SIMPLE_VECTORED_INTERRUPTS)
633rtems_isr
634ata_interrupt_handler(rtems_vector_number vec)
635{
636    rtems_chain_node *the_node = ((rtems_chain_control *)(&ata_int_vec[vec]))->first;
637    ata_queue_msg_t  msg;
638    uint16_t         byte; /* emphasize that only 8 low bits is meaningful */
639
640    for ( ; !rtems_chain_is_tail(&ata_int_vec[vec], the_node) ; )
641    {
642        /* if (1) - is temporary hack - currently I don't know how to identify
643         * controller which asserted interrupt if few controllers share one
644         * interrupt line
645         */
646        if (1)
647        {
648            msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor;
649            ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS,
650                                         &byte);
651            ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0);
652        }
653        the_node = the_node->next;
654    }
655}
656#else
657void ata_interrupt_handler(rtems_irq_hdl_param handle)
658{
659  int ata_irq_chain_index = (int) handle;
660    rtems_chain_node *the_node =
661      ata_irq_chain[ata_irq_chain_index].irq_chain.last;
662    ata_queue_msg_t  msg;
663    uint16_t       byte; /* emphasize that only 8 low bits is meaningful */
664
665
666    for ( ; !rtems_chain_is_tail(&ata_irq_chain[ata_irq_chain_index].irq_chain,
667                           the_node) ; )
668    {
669        /* if (1) - is temporary hack - currently I don't know how to identify
670         * controller which asserted interrupt if few controllers share one
671         * interrupt line
672         */
673        if (1)
674        {
675            msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor;
676            ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS,
677                                         &byte);
678            ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0);
679        }
680        the_node = the_node->next;
681    }
682}
683
684void ata_interrupt_on(const rtems_irq_connect_data *ptr)
685  {
686
687    /* enable ATA device interrupt */
688    ide_controller_write_register(0,
689                                  IDE_REGISTER_DEVICE_CONTROL_OFFSET,
690                                  0x00
691                                 );
692  }
693
694
695void ata_interrupt_off(const rtems_irq_connect_data *ptr)
696  {
697
698    /* disable ATA device interrupt */
699    ide_controller_write_register(0,
700                                  IDE_REGISTER_DEVICE_CONTROL_OFFSET,
701                                  IDE_REGISTER_DEVICE_CONTROL_nIEN
702                                 );
703  }
704
705
706int ata_interrupt_isOn(const rtems_irq_connect_data *ptr)
707  {
708  uint16_t byte; /* emphasize that only 8 low bits is meaningful */
709
710    /* return int. status od ATA device */
711    ide_controller_read_register(0,
712                                IDE_REGISTER_DEVICE_CONTROL_OFFSET,
713                                &byte
714                                );
715
716    return !(byte & IDE_REGISTER_DEVICE_CONTROL_nIEN);
717  }
718
719
720static rtems_irq_connect_data ata_irq_data =
721  {
722
723    0, /* filled out before use... */
724    ata_interrupt_handler,/* filled out before use... */
725    NULL,
726    ata_interrupt_on,
727    ata_interrupt_off,
728    ata_interrupt_isOn
729  };
730#endif
731
732/* ata_pio_in_protocol --
733 *     ATA PIO_IN protocol implementation, see specification
734 *
735 * PARAMETERS:
736 *     ctrl_minor - controller identifier
737 *     areq       - ATA request
738 *
739 * RETURNS:
740 *     NONE
741 */
742static inline void
743ata_pio_in_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq)
744{
745    uint16_t        val;
746    uint8_t         dev;
747    ata_queue_msg_t msg;
748
749    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
750           IDE_REGISTER_DEVICE_HEAD_DEV;
751
752    if (areq->cnt)
753    {
754      int ccbuf = areq->cbuf;
755      ide_controller_read_data_block(ctrl_minor,
756                                     areq->breq->bufs[0].length * areq->cnt,
757                                     areq->breq->bufs, &areq->cbuf, &areq->pos);
758      ccbuf = areq->cbuf - ccbuf;
759      areq->cnt -= ccbuf;
760    }
761
762    if (areq->cnt == 0)
763    {
764        ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL);
765    }
766    else if (IDE_Controller_Table[ctrl_minor].int_driven == false)
767    {
768        do {
769           ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val);
770        } while (val & IDE_REGISTER_STATUS_BSY);
771
772        ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
773    }
774}
775
776/* ata_pio_out_protocol --
777 *     ATA PIO_OUT protocol implementation, see specification
778 *
779 * PARAMETERS:
780 *     ctrl_minor - controller identifier
781 *     areq       - ATA request
782 *
783 * RETURNS:
784 *     NONE
785 */
786static inline void
787ata_pio_out_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq)
788{
789    uint16_t        val;
790    uint8_t         dev;
791    ata_queue_msg_t msg;
792
793#if ATA_DEBUG
794    ata_printf("ata_pio_out_protocol:\n");
795#endif
796
797    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
798           IDE_REGISTER_DEVICE_HEAD_DEV;
799
800    if (areq->cnt == 0)
801    {
802        ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL);
803    }
804    else
805    {
806        if (areq->cnt)
807        {
808          int ccbuf = areq->cbuf;
809          ide_controller_write_data_block(ctrl_minor,
810                                          areq->breq->bufs[0].length * areq->cnt,
811                                          areq->breq->bufs, &areq->cbuf,
812                                          &areq->pos);
813          ccbuf = areq->cbuf - ccbuf;
814          areq->cnt -= ccbuf;
815        }
816        if (IDE_Controller_Table[ctrl_minor].int_driven == false)
817        {
818            do {
819                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
820                                             &val);
821            } while (val & IDE_REGISTER_STATUS_BSY);
822
823            ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0);
824        }
825  }
826}
827
828/* ata_queue_task --
829 *     Task which manages ATA driver events queue.
830 *
831 * PARAMETERS:
832 *     arg - ignored
833 *
834 * RETURNS:
835 *     NONE
836 *
837 * NOTES:
838 *     should be non-preemptive
839 */
840static rtems_task
841ata_queue_task(rtems_task_argument arg)
842{
843    ata_queue_msg_t            msg;
844    size_t                     size;
845    ata_req_t                 *areq;
846    rtems_device_minor_number  ctrl_minor;
847    uint16_t                   val;
848    uint16_t                   val1;
849    rtems_status_code          rc;
850    ISR_Level                  level;
851
852    PREEMPTION_KEY(key);
853
854    DISABLE_PREEMPTION(key);
855
856    while (1)
857    {
858        ENABLE_PREEMPTION(key);
859
860        /* get event which has happend */
861        rc = rtems_message_queue_receive(ata_queue_id, &msg, &size, RTEMS_WAIT,
862                                         RTEMS_NO_TIMEOUT);
863        if (rc != RTEMS_SUCCESSFUL)
864            rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
865
866        /* get controller on which event has happend */
867        ctrl_minor = msg.ctrl_minor;
868
869        DISABLE_PREEMPTION(key);
870
871        /* get current request to the controller */
872        _ISR_Disable(level);
873        areq = (ata_req_t *)(ata_ide_ctrls[ctrl_minor].reqs.first);
874        _ISR_Enable(level);
875
876        switch(msg.type)
877        {
878            case ATA_MSG_PROCESS_NEXT_EVT:
879                /* process next request in the controller queue */
880                ata_process_request(ctrl_minor);
881                break;
882
883            case ATA_MSG_SUCCESS_EVT:
884                /*
885                 * finish processing of current request with successful
886                 * status and start processing of the next request in the
887                 * controller queue
888                 */
889                ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL);
890                break;
891
892            case ATA_MSG_ERROR_EVT:
893                /*
894                 * finish processing of current request with error
895                 * status and start processing of the next request in the
896                 * controller queue
897                 */
898                ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
899                break;
900
901            case ATA_MSG_GEN_EVT:
902                /*
903                 * continue processing of the current request to the
904                 * controller according to current request state and
905                 * ATA protocol
906                 */
907                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
908                                           &val);
909                /* process error case */
910                if (val & IDE_REGISTER_STATUS_ERR)
911                {
912                    ide_controller_read_register(ctrl_minor,
913                                                 IDE_REGISTER_ERROR,
914                                                 &val);
915                    if (val & (IDE_REGISTER_ERROR_UNC |
916                               IDE_REGISTER_ERROR_ICRC |
917                               IDE_REGISTER_ERROR_IDNF |
918                               IDE_REGISTER_ERROR_NM |
919                               IDE_REGISTER_ERROR_MED))
920                    {
921                        if (areq->type == ATA_COMMAND_TYPE_NON_DATA)
922                            ata_non_data_request_done(areq, ctrl_minor,
923                                                      RTEMS_UNSATISFIED,
924                                                      RTEMS_IO_ERROR);
925                        else
926                            ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
927                        break;
928                    }
929                }
930
931                switch(areq->type)
932                {
933                    case ATA_COMMAND_TYPE_PIO_IN:
934                        ata_pio_in_protocol(ctrl_minor, areq);
935                        break;
936
937                    case ATA_COMMAND_TYPE_PIO_OUT:
938                        ata_pio_out_protocol(ctrl_minor, areq);
939                        break;
940
941                    case ATA_COMMAND_TYPE_NON_DATA:
942                        ide_controller_read_register(ctrl_minor,
943                                                      IDE_REGISTER_ERROR,
944                                                     &val1);
945                        ata_non_data_request_done(areq, ctrl_minor,
946                                                  RTEMS_SUCCESSFUL,
947                                                  val1);
948                        break;
949
950                    default:
951#if ATA_DEBUG
952                        ata_printf("ata_queue_task: non-supported command type\n");
953#endif
954                        ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
955                        break;
956                }
957                break;
958
959            default:
960#if ATA_DEBUG
961                ata_printf("ata_queue_task: internal error\n");
962                rtems_task_delete (RTEMS_SELF);
963#endif
964                rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
965                break;
966        }
967    }
968}
969
970/* ata_ioctl --
971 *     ATA driver ioctl interface.
972 *
973 * PARAMETERS:
974 *     device - device identifier
975 *     cmd    - command
976 *     argp   - arguments
977 *
978 * RETURNS:
979 *     depend on 'cmd'
980 */
981static int
982ata_ioctl(rtems_disk_device *dd, uint32_t cmd, void *argp)
983{
984    dev_t                     device = rtems_disk_get_device_identifier(dd);
985    rtems_status_code         status;
986    rtems_device_minor_number rel_minor;
987
988    rel_minor = (rtems_filesystem_dev_minor_t(device)) /
989                ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE;
990
991    /*
992     * in most cases this means that device 'device' is not an registred ATA
993     * device
994     */
995    if (ata_devs[rel_minor].device == ATA_UNDEFINED_VALUE)
996    {
997        errno = ENODEV;
998        return -1;
999    }
1000
1001    switch (cmd)
1002    {
1003        case RTEMS_BLKIO_REQUEST:
1004            status = ata_io_data_request(device, (rtems_blkdev_request *)argp);
1005            break;
1006
1007        case ATAIO_SET_MULTIPLE_MODE:
1008            status = ata_non_data_request(device, cmd, argp);
1009            break;
1010
1011        case RTEMS_BLKIO_CAPABILITIES:
1012            *((uint32_t*) argp)  = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
1013            status = RTEMS_SUCCESSFUL;
1014            break;
1015
1016        default:
1017            return rtems_blkdev_ioctl (dd, cmd, argp);
1018            break;
1019    }
1020
1021    if (status != RTEMS_SUCCESSFUL)
1022    {
1023        errno = EIO;
1024        return -1;
1025    }
1026    return 0;
1027}
1028
1029static void ata_execute_device_diagnostic(
1030  rtems_device_minor_number ctrl_minor,
1031  uint16_t *sector_buffer
1032)
1033{
1034#if ATA_EXEC_DEVICE_DIAGNOSTIC
1035  ata_req_t areq;
1036  blkdev_request1 breq;
1037
1038  ata_breq_init(&breq, sector_buffer);
1039
1040  /*
1041   * Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is
1042   * there any ATA device on the controller.
1043   *
1044   * This command may fail and it assumes we have a master device and may
1045   * be a slave device. I think the identify command will handle
1046   * detection better than this method.
1047   */
1048  memset(&areq, 0, sizeof(ata_req_t));
1049  areq.type = ATA_COMMAND_TYPE_NON_DATA;
1050  areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
1051  areq.regs.regs[IDE_REGISTER_COMMAND] =
1052                            ATA_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC;
1053  areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);
1054
1055  areq.breq = (rtems_blkdev_request *)&breq;
1056
1057  /*
1058   * Process the request. Special processing of requests on
1059   * initialization phase is needed because at this moment there
1060   * is no multitasking enviroment
1061   */
1062  ata_process_request_on_init_phase(ctrl_minor, &areq);
1063
1064  /*
1065   * check status of I/O operation
1066   */
1067  if (breq.req.status == RTEMS_SUCCESSFUL)
1068  {
1069    /* disassemble returned diagnostic codes */
1070    if (areq.info == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT)
1071    {
1072      printk("ATA: ctrl:%d: primary, secondary\n", ctrl_minor);
1073      ATA_DEV_INFO(ctrl_minor,0).present = true;
1074      ATA_DEV_INFO(ctrl_minor,1).present = true;
1075    }
1076    else if (areq.info == ATA_DEV0_PASSED_DEV1_FAILED)
1077    {
1078      printk("ATA: ctrl:%d: primary\n", ctrl_minor);
1079      ATA_DEV_INFO(ctrl_minor,0).present = true;
1080      ATA_DEV_INFO(ctrl_minor,1).present = false;
1081    }
1082    else if (areq.info < ATA_DEV1_PASSED_DEV0_FAILED)
1083    {
1084      printk("ATA: ctrl:%d: secondary\n", ctrl_minor);
1085      ATA_DEV_INFO(ctrl_minor,0).present = false;
1086      ATA_DEV_INFO(ctrl_minor,1).present = true;
1087    }
1088    else
1089    {
1090      printk("ATA: ctrl:%d: none\n", ctrl_minor);
1091      ATA_DEV_INFO(ctrl_minor, 0).present = false;
1092      ATA_DEV_INFO(ctrl_minor, 1).present = false;
1093    }
1094
1095    /* refine the returned codes */
1096    if (ATA_DEV_INFO(ctrl_minor, 1).present)
1097    {
1098      uint16_t ec = 0;
1099      ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec);
1100      if (ec & ATA_DEV1_PASSED_DEV0_FAILED)
1101      {
1102        printk("ATA: ctrl:%d: secondary inforced\n", ctrl_minor);
1103        ATA_DEV_INFO(ctrl_minor, 1).present = true;
1104      }
1105      else
1106      {
1107        printk("ATA: ctrl:%d: secondary removed\n", ctrl_minor);
1108        ATA_DEV_INFO(ctrl_minor, 1).present = false;
1109      }
1110    }
1111  }
1112  else
1113#endif
1114  {
1115    ATA_DEV_INFO(ctrl_minor, 0).present = true;
1116    ATA_DEV_INFO(ctrl_minor,1).present = true;
1117  }
1118}
1119
1120/*
1121 * ata_initialize --
1122 *     Initializes all ATA devices found on initialized IDE controllers.
1123 *
1124 * PARAMETERS:
1125 *     major - device major number
1126 *     minor - device minor number
1127 *     args   - arguments
1128 *
1129 * RETURNS:
1130 *     RTEMS_SUCCESSFUL on success, or error code if
1131 *     error occured
1132 */
1133rtems_device_driver
1134rtems_ata_initialize(rtems_device_major_number major,
1135                     rtems_device_minor_number minor_arg,
1136                     void *args)
1137{
1138    uint32_t           ctrl_minor;
1139    rtems_status_code  status;
1140    uint16_t          *buffer;
1141    int                i, dev = 0;
1142    char               name[ATA_MAX_NAME_LENGTH];
1143    dev_t              device;
1144    ata_int_st_t      *int_st;
1145
1146#if defined(CPU_SIMPLE_VECTORED_INTERRUPTS)
1147    rtems_isr_entry    old_isr;
1148#else
1149    int ata_irq_chain_use;
1150#endif
1151
1152    if (ata_initialized)
1153        return RTEMS_SUCCESSFUL;
1154
1155    /* initialization of disk devices library */
1156    status = rtems_disk_io_initialize();
1157    if (status != RTEMS_SUCCESSFUL)
1158        return status;
1159
1160#ifdef SAFE
1161#ifdef SAFE_MUTEX
1162    status = rtems_semaphore_create (rtems_build_name ('A', 'T', 'A', 'L'),
1163                                     1, RTEMS_ATA_LOCK_ATTRIBS, 0,
1164                                     &ata_lock);
1165    if (status != RTEMS_SUCCESSFUL)
1166        return status;
1167#endif
1168#endif
1169
1170    /* create queue for asynchronous requests handling */
1171    status = rtems_message_queue_create(
1172                 rtems_build_name('A', 'T', 'A', 'Q'),
1173                 ATA_DRIVER_MESSAGE_QUEUE_SIZE,
1174                 sizeof(ata_queue_msg_t),
1175                 RTEMS_FIFO | RTEMS_LOCAL,
1176                 &ata_queue_id);
1177    if (status != RTEMS_SUCCESSFUL)
1178    {
1179        rtems_disk_io_done();
1180        return status;
1181    }
1182
1183    /*
1184     * create ATA driver task, see comments for task implementation for
1185     * details
1186     */
1187    status = rtems_task_create(
1188                 rtems_build_name ('A', 'T', 'A', 'T'),
1189                 ((rtems_ata_driver_task_priority > 0)
1190                  ? rtems_ata_driver_task_priority
1191                  : ATA_DRIVER_TASK_DEFAULT_PRIORITY),
1192                 ATA_DRIVER_TASK_STACK_SIZE,
1193                 RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
1194                 RTEMS_INTERRUPT_LEVEL(0),
1195                 RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
1196                 &ata_task_id);
1197    if (status != RTEMS_SUCCESSFUL)
1198    {
1199        rtems_message_queue_delete(ata_queue_id);
1200        rtems_disk_io_done();
1201        return status;
1202    }
1203
1204    /*
1205     * start ATA driver task. Actually the task will not start immediately -
1206     * it will start only after multitasking support will be started
1207     */
1208    status = rtems_task_start(ata_task_id, ata_queue_task, 0);
1209    if (status != RTEMS_SUCCESSFUL)
1210    {
1211        rtems_task_delete(ata_task_id);
1212        rtems_message_queue_delete(ata_queue_id);
1213        rtems_disk_io_done();
1214        return status;
1215    }
1216
1217    buffer = (uint16_t*)malloc(ATA_SECTOR_SIZE);
1218    if (buffer == NULL)
1219    {
1220        rtems_task_delete(ata_task_id);
1221        rtems_message_queue_delete(ata_queue_id);
1222        rtems_disk_io_done();
1223        return RTEMS_NO_MEMORY;
1224    }
1225
1226    ata_devs_number = 0;
1227
1228    for (i = 0; i < (2 * IDE_CTRL_MAX_MINOR_NUMBER); i++)
1229        ata_devs[i].device = ATA_UNDEFINED_VALUE;
1230
1231#if defined(CPU_SIMPLE_VECTORED_INTERRUPTS)
1232    /* prepare ATA driver for handling  interrupt driven devices */
1233    for (i = 0; i < ATA_MAX_RTEMS_INT_VEC_NUMBER; i++)
1234        rtems_chain_initialize_empty(&ata_int_vec[i]);
1235#else
1236    for (i = 0; i < ATA_IRQ_CHAIN_MAX_CNT; i++) {
1237      rtems_chain_initialize_empty(&(ata_irq_chain[i].irq_chain));
1238    }
1239#endif
1240
1241    /*
1242     * during ATA driver initialization EXECUTE DEVICE DIAGNOSTIC and
1243     * IDENTIFY DEVICE ATA command should be issued; for these purposes ATA
1244     * requests should be formed; ATA requests contain block device request,
1245     * so form block device request first
1246     */
1247
1248    /*
1249     * for each presented IDE controller execute EXECUTE DEVICE DIAGNOSTIC
1250     * ATA command; for each found device execute IDENTIFY DEVICE ATA
1251     * command
1252     */
1253    for (ctrl_minor = 0; ctrl_minor < IDE_Controller_Count; ctrl_minor++)
1254    if (IDE_Controller_Table[ctrl_minor].status == IDE_CTRL_INITIALIZED)
1255    {
1256        rtems_chain_initialize_empty(&ata_ide_ctrls[ctrl_minor].reqs);
1257
1258        if (IDE_Controller_Table[ctrl_minor].int_driven == true)
1259        {
1260            int_st = malloc(sizeof(ata_int_st_t));
1261            if (int_st == NULL)
1262            {
1263                free(buffer);
1264                rtems_task_delete(ata_task_id);
1265                rtems_message_queue_delete(ata_queue_id);
1266                rtems_disk_io_done();
1267                return RTEMS_NO_MEMORY;
1268            }
1269
1270            int_st->ctrl_minor = ctrl_minor;
1271#if defined(CPU_SIMPLE_VECTORED_INTERRUPTS)
1272            status = rtems_interrupt_catch(
1273                         ata_interrupt_handler,
1274                         IDE_Controller_Table[ctrl_minor].int_vec,
1275                         &old_isr);
1276#else
1277            /*
1278             * FIXME: check existing entries. if they use the same
1279             * IRQ name, then append int_st to respective chain
1280             * otherwise, use new ata_irq_chain entry
1281             */
1282            ata_irq_chain_use = -1;
1283            for (i = 0;
1284                 ((i < ata_irq_chain_cnt) &&
1285                  (ata_irq_chain_use < 0));i++) {
1286              if (ata_irq_chain[i].name ==
1287                  IDE_Controller_Table[ctrl_minor].int_vec) {
1288                ata_irq_chain_use = i;
1289              }
1290            }
1291            if (ata_irq_chain_use < 0) {
1292              /*
1293               * no match found, try to use new channel entry
1294               */
1295              if (ata_irq_chain_cnt < ATA_IRQ_CHAIN_MAX_CNT) {
1296                ata_irq_chain_use = ata_irq_chain_cnt++;
1297
1298                ata_irq_chain[ata_irq_chain_use].name =
1299                  IDE_Controller_Table[ctrl_minor].int_vec;
1300                ata_irq_data.name   =
1301                  IDE_Controller_Table[ctrl_minor].int_vec;
1302                ata_irq_data.hdl    = ata_interrupt_handler;
1303                ata_irq_data.handle = (rtems_irq_hdl_param) ctrl_minor;
1304
1305                status = ((0 == BSP_install_rtems_irq_handler(&ata_irq_data))
1306                          ? RTEMS_INVALID_NUMBER
1307                          : RTEMS_SUCCESSFUL);
1308              }
1309              else {
1310                status = RTEMS_TOO_MANY;
1311              }
1312            }
1313#endif
1314            if (status != RTEMS_SUCCESSFUL)
1315            {
1316                free(int_st);
1317                free(buffer);
1318                rtems_task_delete(ata_task_id);
1319                rtems_message_queue_delete(ata_queue_id);
1320                rtems_disk_io_done();
1321                return status;
1322            }
1323#if defined(CPU_SIMPLE_VECTORED_INTERRUPTS)
1324            rtems_chain_append(
1325                &ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec],
1326                &int_st->link);
1327#else
1328            rtems_chain_append(
1329                &(ata_irq_chain[ata_irq_chain_use].irq_chain),
1330                &int_st->link);
1331#endif
1332
1333            /* disable interrupts */
1334            ide_controller_write_register(ctrl_minor,
1335                                          IDE_REGISTER_DEVICE_CONTROL_OFFSET,
1336                                          IDE_REGISTER_DEVICE_CONTROL_nIEN);
1337        }
1338
1339        ata_execute_device_diagnostic(ctrl_minor, buffer);
1340
1341        /* for each found ATA device obtain it configuration */
1342        for (dev = 0; dev < 2; dev++)
1343        if (ATA_DEV_INFO(ctrl_minor, dev).present)
1344        {
1345            status = ata_identify_device(
1346               ctrl_minor,
1347               dev,
1348               buffer,
1349               &ATA_DEV_INFO(ctrl_minor, dev));
1350            if (status != RTEMS_SUCCESSFUL)
1351               continue;
1352
1353            /*
1354             * choose most appropriate ATA device data I/O speed supported
1355             * by the controller
1356             */
1357            status = ide_controller_config_io_speed(
1358               ctrl_minor,
1359               ATA_DEV_INFO(ctrl_minor, dev).modes_available);
1360            if (status != RTEMS_SUCCESSFUL)
1361               continue;
1362
1363            /*
1364             * Ok, let register new ATA device in the system
1365             */
1366            ata_devs[ata_devs_number].ctrl_minor = ctrl_minor;
1367            ata_devs[ata_devs_number].device = dev;
1368
1369            /* The space leaves a hole for the character. */
1370            strcpy(name, "/dev/hd ");
1371            name[7] = 'a' + 2 * ctrl_minor + dev;
1372
1373            device = rtems_filesystem_make_dev_t(
1374                         major,
1375                         (ata_devs_number *
1376                          ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE));
1377            status = rtems_disk_create_phys(device, ATA_SECTOR_SIZE,
1378                ATA_DEV_INFO(ctrl_minor, dev).lba_avaible ?
1379                ATA_DEV_INFO(ctrl_minor, dev).lba_sectors :
1380                (ATA_DEV_INFO(ctrl_minor, dev).heads *
1381                 ATA_DEV_INFO(ctrl_minor, dev).cylinders *
1382                 ATA_DEV_INFO(ctrl_minor, dev).sectors),
1383                ata_ioctl, NULL, name);
1384            if (status != RTEMS_SUCCESSFUL)
1385            {
1386                ata_devs[ata_devs_number].device = ATA_UNDEFINED_VALUE;
1387                continue;
1388            }
1389            ata_devs_number++;
1390        }
1391        if (IDE_Controller_Table[ctrl_minor].int_driven == true)
1392        {
1393            ide_controller_write_register(ctrl_minor,
1394                                          IDE_REGISTER_DEVICE_CONTROL_OFFSET,
1395                                          0x00);
1396        }
1397    }
1398
1399    free(buffer);
1400    ata_initialized = true;
1401    return RTEMS_SUCCESSFUL;
1402}
1403
1404/* ata_process_request_on_init_phase --
1405 *     Process the ATA request during system initialization. Request
1406 *     processing is syncronous and doesn't use multiprocessing enviroment.
1407 *
1408 * PARAMETERS:
1409 *     ctrl_minor - controller identifier
1410 *     areq       - ATA request
1411 *
1412 * RETURNS:
1413 *     NONE
1414 */
1415void
1416ata_process_request_on_init_phase(rtems_device_minor_number  ctrl_minor,
1417                                  ata_req_t                 *areq)
1418{
1419    uint16_t           byte;/* emphasize that only 8 low bits is meaningful */
1420    uint8_t            i, dev;
1421    uint16_t           val, val1;
1422    volatile unsigned  retries;
1423
1424    assert(areq);
1425
1426    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
1427           IDE_REGISTER_DEVICE_HEAD_DEV;
1428
1429    ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD,
1430                                  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]);
1431
1432        retries = 0;
1433    do {
1434        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
1435        /* If device (on INIT, i.e. it should be idle) is neither
1436         * busy nor ready something's fishy, i.e., there is probably
1437         * no device present.
1438         * I'd like to do a proper timeout but don't know of a portable
1439         * timeout routine (w/o using multitasking / rtems_task_wake_after())
1440         */
1441        if ( ! (byte & (IDE_REGISTER_STATUS_BSY | IDE_REGISTER_STATUS_DRDY))) {
1442            retries++;
1443            if ( 10000 == retries ) {
1444              /* probably no drive connected */
1445              areq->breq->status = RTEMS_UNSATISFIED;
1446              return;
1447            }
1448        }
1449    } while ((byte & IDE_REGISTER_STATUS_BSY) ||
1450             (!(byte & IDE_REGISTER_STATUS_DRDY)));
1451
1452    for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++)
1453    {
1454        uint32_t   reg = (1 << i);
1455        if (areq->regs.to_write & reg)
1456            ide_controller_write_register(ctrl_minor, i,
1457                                          areq->regs.regs[i]);
1458    }
1459
1460    do {
1461        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
1462    } while (byte & IDE_REGISTER_STATUS_BSY);
1463
1464    ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val);
1465    ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &val1);
1466
1467    if (val & IDE_REGISTER_STATUS_ERR)
1468    {
1469        areq->breq->status = RTEMS_IO_ERROR;
1470        return;
1471    }
1472
1473    switch(areq->type)
1474    {
1475        case ATA_COMMAND_TYPE_PIO_IN:
1476            if (areq->cnt)
1477            {
1478              int ccbuf = areq->cbuf;
1479              ide_controller_read_data_block(ctrl_minor,
1480                                             areq->breq->bufs[0].length * areq->cnt,
1481                                             areq->breq->bufs, &areq->cbuf,
1482                                             &areq->pos);
1483              ccbuf = areq->cbuf - ccbuf;
1484              areq->cnt -= ccbuf;
1485            }
1486            if (areq->cnt == 0)
1487            {
1488                areq->breq->status = RTEMS_SUCCESSFUL;
1489            }
1490            else
1491            {
1492                /*
1493                 * this shouldn't happend on the initialization
1494                 * phase!
1495                 */
1496                rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
1497            }
1498            break;
1499
1500        case ATA_COMMAND_TYPE_NON_DATA:
1501            areq->breq->status = RTEMS_SUCCESSFUL;
1502            areq->info = val1;
1503            break;
1504
1505        default:
1506#if ATA_DEBUG
1507            ata_printf("ata_queue_task: non-supported command type\n");
1508#endif
1509            areq->breq->status = RTEMS_IO_ERROR;
1510            break;
1511    }
1512}
1513
1514void ata_breq_init(blkdev_request1 *breq, uint16_t *sector_buffer)
1515{
1516  memset(breq, 0, sizeof(*breq));
1517
1518  breq->req.done_arg = breq;
1519  breq->req.bufnum = 1;
1520  breq->req.bufs [0].length = ATA_SECTOR_SIZE;
1521  breq->req.bufs [0].buffer = sector_buffer;
1522}
1523
1524rtems_status_code ata_identify_device(
1525  rtems_device_minor_number ctrl_minor,
1526  int dev,
1527  uint16_t *sector_buffer,
1528  ata_dev_t *device_entry
1529)
1530{
1531  ata_req_t areq;
1532  blkdev_request1 breq;
1533
1534  ata_breq_init(&breq, sector_buffer);
1535
1536  /*
1537   * Issue DEVICE IDENTIFY ATA command and get device
1538   * configuration
1539   */
1540  memset(&areq, 0, sizeof(ata_req_t));
1541  areq.type = ATA_COMMAND_TYPE_PIO_IN;
1542  areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
1543  areq.regs.regs [IDE_REGISTER_COMMAND] = ATA_COMMAND_IDENTIFY_DEVICE;
1544  areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS);
1545  areq.breq = (rtems_blkdev_request *)&breq;
1546  areq.cnt = breq.req.bufnum;
1547  areq.regs.regs [IDE_REGISTER_DEVICE_HEAD] |=
1548    dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS;
1549
1550  /*
1551   * Process the request. Special processing of requests on
1552   * initialization phase is needed because at this moment there
1553   * is no multitasking enviroment
1554   */
1555  ata_process_request_on_init_phase(ctrl_minor, &areq);
1556
1557  /* check status of I/O operation */
1558  if (breq.req.status != RTEMS_SUCCESSFUL) {
1559    return RTEMS_IO_ERROR;
1560  }
1561
1562  /*
1563   * Parse returned device configuration and fill in ATA internal
1564   * device info structure
1565   */
1566  device_entry->cylinders =
1567      CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_CLNDS]);
1568  device_entry->heads =
1569      CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_HEADS]);
1570  device_entry->sectors =
1571      CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_SECS]);
1572  device_entry->lba_sectors =
1573      CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS1]);
1574  device_entry->lba_sectors <<= 16;
1575  device_entry->lba_sectors += CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS0]);
1576  device_entry->lba_avaible =
1577      (CF_LE_W(sector_buffer[ATA_IDENT_WORD_CAPABILITIES]) >> 9) & 0x1;
1578
1579  if ((CF_LE_W(sector_buffer[ATA_IDENT_WORD_FIELD_VALIDITY]) &
1580       ATA_IDENT_BIT_VALID) == 0) {
1581    /* no "supported modes" info -> use default */
1582    device_entry->mode_active = ATA_MODES_PIO3;
1583  } else {
1584    device_entry->modes_available =
1585      ((CF_LE_W(sector_buffer[64]) & 0x1) ? ATA_MODES_PIO3 : 0) |
1586      ((CF_LE_W(sector_buffer[64]) & 0x2) ? ATA_MODES_PIO4 : 0) |
1587      ((CF_LE_W(sector_buffer[63]) & 0x1) ? ATA_MODES_DMA0 : 0) |
1588      ((CF_LE_W(sector_buffer[63]) & 0x2) ?
1589       ATA_MODES_DMA0 | ATA_MODES_DMA1 : 0) |
1590      ((CF_LE_W(sector_buffer[63]) & 0x4) ?
1591       ATA_MODES_DMA0 | ATA_MODES_DMA1 | ATA_MODES_DMA2 : 0);
1592    if (device_entry->modes_available == 0) {
1593      return RTEMS_IO_ERROR;
1594    }
1595  }
1596
1597  return RTEMS_SUCCESSFUL;
1598}
Note: See TracBrowser for help on using the repository browser.