source: rtems/c/src/libchip/ide/ata.c @ 0d3b27cd

4.104.11
Last change on this file since 0d3b27cd was 0d3b27cd, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 22, 2009 at 4:00:55 PM

2009-07-22 Joel Sherrill <joel.sherrill@…>

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