source: rtems/c/src/libchip/ide/ata.c @ 64734fc

4.104.11
Last change on this file since 64734fc was 1e0a551, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Dec 18, 2009 at 3:59:30 PM

Update for block device API change

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