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

4.104.115
Last change on this file since 5c587596 was 5c587596, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 01/19/10 at 09:10:03

libblock API update

  • Property mode set to 100644
File size: 49.4 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)
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);
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 info)
590{
591#if ATA_DEBUG
592    ata_printf("ata_non_data_request_done: entry\n");
593#endif
594
595    areq->status = status;
596    areq->info = info;
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);
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);
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                break;
914
915            case ATA_MSG_ERROR_EVT:
916                /*
917                 * finish processing of current request with error
918                 * status and start processing of the next request in the
919                 * controller queue
920                 */
921                ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
922                break;
923
924            case ATA_MSG_GEN_EVT:
925                /*
926                 * continue processing of the current request to the
927                 * controller according to current request state and
928                 * ATA protocol
929                 */
930                ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS,
931                                           &val);
932                /* process error case */
933                if (val & IDE_REGISTER_STATUS_ERR)
934                {
935                    ide_controller_read_register(ctrl_minor,
936                                                 IDE_REGISTER_ERROR,
937                                                 &val);
938                    if (val & (IDE_REGISTER_ERROR_UNC |
939                               IDE_REGISTER_ERROR_ICRC |
940                               IDE_REGISTER_ERROR_IDNF |
941                               IDE_REGISTER_ERROR_NM |
942                               IDE_REGISTER_ERROR_MED))
943                    {
944                        if (areq->type == ATA_COMMAND_TYPE_NON_DATA)
945                            ata_non_data_request_done(areq, ctrl_minor,
946                                                      RTEMS_UNSATISFIED,
947                                                      RTEMS_IO_ERROR);
948                        else
949                            ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
950                        break;
951                    }
952                }
953
954                switch(areq->type)
955                {
956                    case ATA_COMMAND_TYPE_PIO_IN:
957                        ata_pio_in_protocol(ctrl_minor, areq);
958                        break;
959
960                    case ATA_COMMAND_TYPE_PIO_OUT:
961                        ata_pio_out_protocol(ctrl_minor, areq);
962                        break;
963
964                    case ATA_COMMAND_TYPE_NON_DATA:
965                        ide_controller_read_register(ctrl_minor,
966                                                      IDE_REGISTER_ERROR,
967                                                     &val1);
968                        ata_non_data_request_done(areq, ctrl_minor,
969                                                  RTEMS_SUCCESSFUL,
970                                                  val1);
971                        break;
972
973                    default:
974#if ATA_DEBUG
975                        ata_printf("ata_queue_task: non-supported command type\n");
976#endif
977                        ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR);
978                        break;
979                }
980                break;
981
982            default:
983#if ATA_DEBUG
984                ata_printf("ata_queue_task: internal error\n");
985                rtems_task_delete (RTEMS_SELF);
986#endif
987                rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
988                break;
989        }
990    }
991}
992
993/* ata_ioctl --
994 *     ATA driver ioctl interface.
995 *
996 * PARAMETERS:
997 *     device - device identifier
998 *     cmd    - command
999 *     argp   - arguments
1000 *
1001 * RETURNS:
1002 *     depend on 'cmd'
1003 */
1004static int
1005ata_ioctl(rtems_disk_device *dd, uint32_t cmd, void *argp)
1006{
1007    dev_t                     device = rtems_disk_get_device_identifier(dd);
1008    rtems_status_code         status;
1009    rtems_device_minor_number rel_minor;
1010
1011    rel_minor = (rtems_filesystem_dev_minor_t(device)) /
1012                ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE;
1013
1014    /*
1015     * in most cases this means that device 'device' is not an registred ATA
1016     * device
1017     */
1018    if (ata_devs[rel_minor].device == ATA_UNDEFINED_VALUE)
1019    {
1020        errno = ENODEV;
1021        return -1;
1022    }
1023
1024    switch (cmd)
1025    {
1026        case RTEMS_BLKIO_REQUEST:
1027            status = ata_io_data_request(device, (rtems_blkdev_request *)argp);
1028            break;
1029
1030        case ATAIO_SET_MULTIPLE_MODE:
1031            status = ata_non_data_request(device, cmd, argp);
1032            break;
1033
1034        case RTEMS_BLKDEV_CAPABILITIES:
1035            *((uint32_t*) argp)  = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
1036            status = RTEMS_SUCCESSFUL;
1037            break;
1038
1039        default:
1040            return rtems_blkdev_ioctl (dd, cmd, argp);
1041            break;
1042    }
1043
1044    if (status != RTEMS_SUCCESSFUL)
1045    {
1046        errno = EIO;
1047        return -1;
1048    }
1049    return 0;
1050}
1051
1052/*
1053 * ata_initialize --
1054 *     Initializes all ATA devices found on initialized IDE controllers.
1055 *
1056 * PARAMETERS:
1057 *     major - device major number
1058 *     minor - device minor number
1059 *     args   - arguments
1060 *
1061 * RETURNS:
1062 *     RTEMS_SUCCESSFUL on success, or error code if
1063 *     error occured
1064 */
1065rtems_device_driver
1066rtems_ata_initialize(rtems_device_major_number major,
1067                     rtems_device_minor_number minor_arg,
1068                     void *args)
1069{
1070    uint32_t           ctrl_minor;
1071    rtems_status_code  status;
1072    ata_req_t          areq;
1073    blkdev_request1    breq;
1074    uint8_t            i, dev = 0;
1075    uint16_t          *buffer;
1076#if ATA_EXEC_DEVICE_DIAGNOSTIC
1077    uint16_t           ec;
1078#endif
1079    char               name[ATA_MAX_NAME_LENGTH];
1080    dev_t              device;
1081    ata_int_st_t      *int_st;
1082
1083#if defined(ATA_USE_OLD_EXCEPTIONS)
1084    rtems_isr_entry    old_isr;
1085#else
1086    int ata_irq_chain_use;
1087#endif
1088
1089    if (ata_initialized)
1090        return RTEMS_SUCCESSFUL;
1091
1092    /* initialization of disk devices library */
1093    status = rtems_disk_io_initialize();
1094    if (status != RTEMS_SUCCESSFUL)
1095        return status;
1096
1097#ifdef SAFE
1098#ifdef SAFE_MUTEX
1099    status = rtems_semaphore_create (rtems_build_name ('A', 'T', 'A', 'L'),
1100                                     1, RTEMS_ATA_LOCK_ATTRIBS, 0,
1101                                     &ata_lock);
1102    if (status != RTEMS_SUCCESSFUL)
1103        return status;
1104#endif
1105#endif
1106
1107    /* create queue for asynchronous requests handling */
1108    status = rtems_message_queue_create(
1109                 rtems_build_name('A', 'T', 'A', 'Q'),
1110                 ATA_DRIVER_MESSAGE_QUEUE_SIZE,
1111                 sizeof(ata_queue_msg_t),
1112                 RTEMS_FIFO | RTEMS_LOCAL,
1113                 &ata_queue_id);
1114    if (status != RTEMS_SUCCESSFUL)
1115    {
1116        rtems_disk_io_done();
1117        return status;
1118    }
1119
1120    /*
1121     * create ATA driver task, see comments for task implementation for
1122     * details
1123     */
1124    status = rtems_task_create(
1125                 rtems_build_name ('A', 'T', 'A', 'T'),
1126                 ((rtems_ata_driver_task_priority > 0)
1127                  ? rtems_ata_driver_task_priority
1128                  : ATA_DRIVER_TASK_DEFAULT_PRIORITY),
1129                 ATA_DRIVER_TASK_STACK_SIZE,
1130                 RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
1131                 RTEMS_INTERRUPT_LEVEL(0),
1132                 RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
1133                 &ata_task_id);
1134    if (status != RTEMS_SUCCESSFUL)
1135    {
1136        rtems_message_queue_delete(ata_queue_id);
1137        rtems_disk_io_done();
1138        return status;
1139    }
1140
1141    /*
1142     * start ATA driver task. Actually the task will not start immediately -
1143     * it will start only after multitasking support will be started
1144     */
1145    status = rtems_task_start(ata_task_id, ata_queue_task, 0);
1146    if (status != RTEMS_SUCCESSFUL)
1147    {
1148        rtems_task_delete(ata_task_id);
1149        rtems_message_queue_delete(ata_queue_id);
1150        rtems_disk_io_done();
1151        return status;
1152    }
1153
1154    buffer = (uint16_t*)malloc(ATA_SECTOR_SIZE);
1155    if (buffer == NULL)
1156    {
1157        rtems_task_delete(ata_task_id);
1158        rtems_message_queue_delete(ata_queue_id);
1159        rtems_disk_io_done();
1160        return RTEMS_NO_MEMORY;
1161    }
1162
1163    ata_devs_number = 0;
1164
1165    for (i = 0; i < (2 * IDE_CTRL_MAX_MINOR_NUMBER); i++)
1166        ata_devs[i].device = ATA_UNDEFINED_VALUE;
1167
1168#if defined(ATA_USE_OLD_EXCEPTIONS)
1169    /* prepare ATA driver for handling  interrupt driven devices */
1170    for (i = 0; i < ATA_MAX_RTEMS_INT_VEC_NUMBER; i++)
1171        rtems_chain_initialize_empty(&ata_int_vec[i]);
1172#else
1173    for (i = 0; i < ATA_IRQ_CHAIN_MAX_CNT; i++) {
1174      rtems_chain_initialize_empty(&(ata_irq_chain[i].irq_chain));
1175    }
1176#endif
1177
1178    /*
1179     * during ATA driver initialization EXECUTE DEVICE DIAGNOSTIC and
1180     * IDENTIFY DEVICE ATA command should be issued; for these purposes ATA
1181     * requests should be formed; ATA requests contain block device request,
1182     * so form block device request first
1183     */
1184    memset(&breq, 0, sizeof(blkdev_request1));
1185    breq.req.req_done = NULL;
1186    breq.req.done_arg = &breq;
1187    breq.req.bufnum = 1;
1188    breq.req.bufs[0].length = ATA_SECTOR_SIZE;
1189    breq.req.bufs[0].buffer = buffer;
1190
1191    /*
1192     * for each presented IDE controller execute EXECUTE DEVICE DIAGNOSTIC
1193     * ATA command; for each found device execute IDENTIFY DEVICE ATA
1194     * command
1195     */
1196    for (ctrl_minor = 0; ctrl_minor < IDE_Controller_Count; ctrl_minor++)
1197    if (IDE_Controller_Table[ctrl_minor].status == IDE_CTRL_INITIALIZED)
1198    {
1199        rtems_chain_initialize_empty(&ata_ide_ctrls[ctrl_minor].reqs);
1200
1201        if (IDE_Controller_Table[ctrl_minor].int_driven == true)
1202        {
1203            int_st = malloc(sizeof(ata_int_st_t));
1204            if (int_st == NULL)
1205            {
1206                free(buffer);
1207                rtems_task_delete(ata_task_id);
1208                rtems_message_queue_delete(ata_queue_id);
1209                rtems_disk_io_done();
1210                return RTEMS_NO_MEMORY;
1211            }
1212
1213            int_st->ctrl_minor = ctrl_minor;
1214#if defined(ATA_USE_OLD_EXCEPTIONS)
1215            status = rtems_interrupt_catch(
1216                         ata_interrupt_handler,
1217                         IDE_Controller_Table[ctrl_minor].int_vec,
1218                         &old_isr);
1219#else
1220            /*
1221             * FIXME: check existing entries. if they use the same
1222             * IRQ name, then append int_st to respective chain
1223             * otherwise, use new ata_irq_chain entry
1224             */
1225            ata_irq_chain_use = -1;
1226            for (i = 0;
1227                 ((i < ata_irq_chain_cnt) &&
1228                  (ata_irq_chain_use < 0));i++) {
1229              if (ata_irq_chain[i].name ==
1230                  IDE_Controller_Table[ctrl_minor].int_vec) {
1231                ata_irq_chain_use = i;
1232              }
1233            }
1234            if (ata_irq_chain_use < 0) {
1235              /*
1236               * no match found, try to use new channel entry
1237               */
1238              if (ata_irq_chain_cnt < ATA_IRQ_CHAIN_MAX_CNT) {
1239                ata_irq_chain_use = ata_irq_chain_cnt++;
1240
1241                ata_irq_chain[ata_irq_chain_use].name =
1242                  IDE_Controller_Table[ctrl_minor].int_vec;
1243                ata_irq_data.name   =
1244                  IDE_Controller_Table[ctrl_minor].int_vec;
1245                ata_irq_data.hdl    = ata_interrupt_handler;
1246                ata_irq_data.handle = (rtems_irq_hdl_param) ctrl_minor;
1247
1248                status = ((0 == BSP_install_rtems_irq_handler(&ata_irq_data))
1249                          ? RTEMS_INVALID_NUMBER
1250                          : RTEMS_SUCCESSFUL);
1251              }
1252              else {
1253                status = RTEMS_TOO_MANY;
1254              }
1255            }
1256#endif
1257            if (status != RTEMS_SUCCESSFUL)
1258            {
1259                free(int_st);
1260                free(buffer);
1261                rtems_task_delete(ata_task_id);
1262                rtems_message_queue_delete(ata_queue_id);
1263                rtems_disk_io_done();
1264                return status;
1265            }
1266#if defined(ATA_USE_OLD_EXCEPTIONS)
1267            rtems_chain_append(
1268                &ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec],
1269                &int_st->link);
1270#else
1271            rtems_chain_append(
1272                &(ata_irq_chain[ata_irq_chain_use].irq_chain),
1273                &int_st->link);
1274#endif
1275
1276            /* disable interrupts */
1277            ide_controller_write_register(ctrl_minor,
1278                                          IDE_REGISTER_DEVICE_CONTROL_OFFSET,
1279                                          IDE_REGISTER_DEVICE_CONTROL_nIEN);
1280        }
1281
1282#if ATA_EXEC_DEVICE_DIAGNOSTIC
1283        /*
1284         * Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is
1285         * there any ATA device on the controller.
1286         *
1287         * This command may fail and it assumes we have a master device and may
1288         * be a slave device. I think the identify command will handle
1289         * detection better than this method.
1290         */
1291        memset(&areq, 0, sizeof(ata_req_t));
1292        areq.type = ATA_COMMAND_TYPE_NON_DATA;
1293        areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
1294        areq.regs.regs[IDE_REGISTER_COMMAND] =
1295                                  ATA_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC;
1296        areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR);
1297
1298        areq.breq = (rtems_blkdev_request *)&breq;
1299
1300        /*
1301         * Process the request. Special processing of requests on
1302         * initialization phase is needed because at this moment there
1303         * is no multitasking enviroment
1304         */
1305        ata_process_request_on_init_phase(ctrl_minor, &areq);
1306
1307        /*
1308         * check status of I/O operation
1309         */
1310        if (breq.req.status == RTEMS_SUCCESSFUL)
1311        {
1312          /* disassemble returned diagnostic codes */
1313          if (areq.info == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT)
1314          {
1315            printk("ATA: ctrl:%d: primary, secondary\n", ctrl_minor);
1316            ATA_DEV_INFO(ctrl_minor,0).present = true;
1317            ATA_DEV_INFO(ctrl_minor,1).present = true;
1318          }
1319          else if (areq.info == ATA_DEV0_PASSED_DEV1_FAILED)
1320          {
1321            printk("ATA: ctrl:%d: primary\n", ctrl_minor);
1322            ATA_DEV_INFO(ctrl_minor,0).present = true;
1323            ATA_DEV_INFO(ctrl_minor,1).present = false;
1324          }
1325          else if (areq.info < ATA_DEV1_PASSED_DEV0_FAILED)
1326          {
1327            printk("ATA: ctrl:%d: secondary\n", ctrl_minor);
1328            ATA_DEV_INFO(ctrl_minor,0).present = false;
1329            ATA_DEV_INFO(ctrl_minor,1).present = true;
1330          }
1331          else
1332          {
1333            printk("ATA: ctrl:%d: none\n", ctrl_minor);
1334            ATA_DEV_INFO(ctrl_minor, 0).present = false;
1335            ATA_DEV_INFO(ctrl_minor, 1).present = false;
1336          }
1337
1338          /* refine the returned codes */
1339          if (ATA_DEV_INFO(ctrl_minor, 1).present)
1340          {
1341            ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec);
1342            if (ec & ATA_DEV1_PASSED_DEV0_FAILED)
1343            {
1344              printk("ATA: ctrl:%d: secondary inforced\n", ctrl_minor);
1345              ATA_DEV_INFO(ctrl_minor, 1).present = true;
1346            }
1347            else
1348            {
1349              printk("ATA: ctrl:%d: secondary removed\n", ctrl_minor);
1350              ATA_DEV_INFO(ctrl_minor, 1).present = false;
1351            }
1352          }
1353        }
1354        else
1355#endif
1356        {
1357          ATA_DEV_INFO(ctrl_minor, 0).present = true;
1358          ATA_DEV_INFO(ctrl_minor,1).present = true;
1359        }
1360
1361        /* for each found ATA device obtain it configuration */
1362        for (dev = 0; dev < 2; dev++)
1363        if (ATA_DEV_INFO(ctrl_minor, dev).present)
1364        {
1365            /*
1366             * Issue DEVICE IDENTIFY ATA command and get device
1367             * configuration
1368             */
1369            memset(&areq, 0, sizeof(ata_req_t));
1370            areq.type = ATA_COMMAND_TYPE_PIO_IN;
1371            areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND);
1372            areq.regs.regs[IDE_REGISTER_COMMAND] =
1373                                              ATA_COMMAND_IDENTIFY_DEVICE;
1374            areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS);
1375            areq.breq = (rtems_blkdev_request *)&breq;
1376
1377            areq.cnt = breq.req.bufnum;
1378
1379            areq.regs.regs[IDE_REGISTER_DEVICE_HEAD] |=
1380                                    (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS);
1381
1382            /*
1383             * Process the request. Special processing of requests on
1384             * initialization phase is needed because at this moment there
1385             * is no multitasking enviroment
1386             */
1387            ata_process_request_on_init_phase(ctrl_minor, &areq);
1388
1389            /* check status of I/O operation */
1390            if (breq.req.status != RTEMS_SUCCESSFUL)
1391                continue;
1392
1393            /*
1394             * Parse returned device configuration and fill in ATA internal
1395             * device info structure
1396             */
1397            ATA_DEV_INFO(ctrl_minor, dev).cylinders =
1398                CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_CLNDS]);
1399            ATA_DEV_INFO(ctrl_minor, dev).heads =
1400                CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_HEADS]);
1401            ATA_DEV_INFO(ctrl_minor, dev).sectors =
1402                CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_SECS]);
1403            ATA_DEV_INFO(ctrl_minor, dev).lba_sectors =
1404                CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS1]);
1405            ATA_DEV_INFO(ctrl_minor, dev).lba_sectors <<= 16;
1406            ATA_DEV_INFO(ctrl_minor, dev).lba_sectors += CF_LE_W(buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS0]);
1407            ATA_DEV_INFO(ctrl_minor, dev).lba_avaible =
1408                (CF_LE_W(buffer[ATA_IDENT_WORD_CAPABILITIES]) >> 9) & 0x1;
1409
1410            if ((CF_LE_W(buffer[ATA_IDENT_WORD_FIELD_VALIDITY]) &
1411                 ATA_IDENT_BIT_VALID) == 0) {
1412              /* no "supported modes" info -> use default */
1413              ATA_DEV_INFO(ctrl_minor, dev).mode_active = ATA_MODES_PIO3;
1414            }
1415            else {
1416              ATA_DEV_INFO(ctrl_minor, dev).modes_available =
1417                ((CF_LE_W(buffer[64]) & 0x1) ? ATA_MODES_PIO3 : 0) |
1418                ((CF_LE_W(buffer[64]) & 0x2) ? ATA_MODES_PIO4 : 0) |
1419                ((CF_LE_W(buffer[63]) & 0x1) ? ATA_MODES_DMA0 : 0) |
1420                ((CF_LE_W(buffer[63]) & 0x2) ?
1421                 ATA_MODES_DMA0 | ATA_MODES_DMA1 : 0) |
1422                ((CF_LE_W(buffer[63]) & 0x4) ?
1423                 ATA_MODES_DMA0 | ATA_MODES_DMA1 | ATA_MODES_DMA2 : 0);
1424              if (ATA_DEV_INFO(ctrl_minor, dev).modes_available == 0)
1425                continue;
1426              /*
1427               * choose most appropriate ATA device data I/O speed supported
1428               * by the controller
1429               */
1430              status = ide_controller_config_io_speed(
1431                ctrl_minor,
1432                ATA_DEV_INFO(ctrl_minor, dev).modes_available);
1433              if (status != RTEMS_SUCCESSFUL)
1434                continue;
1435            }
1436            /*
1437             * Ok, let register new ATA device in the system
1438             */
1439            ata_devs[ata_devs_number].ctrl_minor = ctrl_minor;
1440            ata_devs[ata_devs_number].device = dev;
1441
1442            /* The space leaves a hole for the character. */
1443            strcpy(name, "/dev/hd ");
1444            name[7] = 'a' + 2 * ctrl_minor + dev;
1445
1446            device = rtems_filesystem_make_dev_t(
1447                         major,
1448                         (ata_devs_number *
1449                          ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE));
1450            status = rtems_disk_create_phys(device, ATA_SECTOR_SIZE,
1451                ATA_DEV_INFO(ctrl_minor, dev).lba_avaible ?
1452                ATA_DEV_INFO(ctrl_minor, dev).lba_sectors :
1453                (ATA_DEV_INFO(ctrl_minor, dev).heads *
1454                 ATA_DEV_INFO(ctrl_minor, dev).cylinders *
1455                 ATA_DEV_INFO(ctrl_minor, dev).sectors),
1456                ata_ioctl, NULL, name);
1457            if (status != RTEMS_SUCCESSFUL)
1458            {
1459                ata_devs[ata_devs_number].device = ATA_UNDEFINED_VALUE;
1460                continue;
1461            }
1462            ata_devs_number++;
1463        }
1464        if (IDE_Controller_Table[ctrl_minor].int_driven == true)
1465        {
1466            ide_controller_write_register(ctrl_minor,
1467                                          IDE_REGISTER_DEVICE_CONTROL_OFFSET,
1468                                          0x00);
1469        }
1470    }
1471
1472    free(buffer);
1473    ata_initialized = true;
1474    return RTEMS_SUCCESSFUL;
1475}
1476
1477/* ata_process_request_on_init_phase --
1478 *     Process the ATA request during system initialization. Request
1479 *     processing is syncronous and doesn't use multiprocessing enviroment.
1480 *
1481 * PARAMETERS:
1482 *     ctrl_minor - controller identifier
1483 *     areq       - ATA request
1484 *
1485 * RETURNS:
1486 *     NONE
1487 */
1488static void
1489ata_process_request_on_init_phase(rtems_device_minor_number  ctrl_minor,
1490                                  ata_req_t                 *areq)
1491{
1492    uint16_t           byte;/* emphasize that only 8 low bits is meaningful */
1493    uint8_t            i, dev;
1494    uint16_t           val, val1;
1495    volatile unsigned  retries;
1496
1497    assert(areq);
1498
1499    dev =  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &
1500           IDE_REGISTER_DEVICE_HEAD_DEV;
1501
1502    ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD,
1503                                  areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]);
1504
1505        retries = 0;
1506    do {
1507        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
1508        /* If device (on INIT, i.e. it should be idle) is neither
1509         * busy nor ready something's fishy, i.e., there is probably
1510         * no device present.
1511         * I'd like to do a proper timeout but don't know of a portable
1512         * timeout routine (w/o using multitasking / rtems_task_wake_after())
1513         */
1514        if ( ! (byte & (IDE_REGISTER_STATUS_BSY | IDE_REGISTER_STATUS_DRDY))) {
1515            retries++;
1516            if ( 10000 == retries ) {
1517              /* probably no drive connected */
1518              areq->breq->status = RTEMS_UNSATISFIED;
1519              return;
1520            }
1521        }
1522    } while ((byte & IDE_REGISTER_STATUS_BSY) ||
1523             (!(byte & IDE_REGISTER_STATUS_DRDY)));
1524
1525    for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++)
1526    {
1527        uint32_t   reg = (1 << i);
1528        if (areq->regs.to_write & reg)
1529            ide_controller_write_register(ctrl_minor, i,
1530                                          areq->regs.regs[i]);
1531    }
1532
1533    do {
1534        ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte);
1535    } while (byte & IDE_REGISTER_STATUS_BSY);
1536
1537    ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val);
1538    ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &val1);
1539
1540    if (val & IDE_REGISTER_STATUS_ERR)
1541    {
1542        areq->breq->status = RTEMS_IO_ERROR;
1543        return;
1544    }
1545
1546    switch(areq->type)
1547    {
1548        case ATA_COMMAND_TYPE_PIO_IN:
1549            if (areq->cnt)
1550            {
1551              int ccbuf = areq->cbuf;
1552              ide_controller_read_data_block(ctrl_minor,
1553                                             areq->breq->bufs[0].length * areq->cnt,
1554                                             areq->breq->bufs, &areq->cbuf,
1555                                             &areq->pos);
1556              ccbuf = areq->cbuf - ccbuf;
1557              areq->cnt -= ccbuf;
1558            }
1559            if (areq->cnt == 0)
1560            {
1561                areq->breq->status = RTEMS_SUCCESSFUL;
1562            }
1563            else
1564            {
1565                /*
1566                 * this shouldn't happend on the initialization
1567                 * phase!
1568                 */
1569                rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
1570            }
1571            break;
1572
1573        case ATA_COMMAND_TYPE_NON_DATA:
1574            areq->breq->status = RTEMS_SUCCESSFUL;
1575            areq->info = val1;
1576            break;
1577
1578        default:
1579#if ATA_DEBUG
1580            ata_printf("ata_queue_task: non-supported command type\n");
1581#endif
1582            areq->breq->status = RTEMS_IO_ERROR;
1583            break;
1584    }
1585}
Note: See TracBrowser for help on using the repository browser.