OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [io/] [pcmcia/] [v2_0/] [src/] [pcmcia.c] - Blame information for rev 665

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      io/pcmcia/pcmcia.c
4
//
5
//      PCMCIA support (Card Services)
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    gthomas
44
// Contributors: gthomas
45
// Date:         2000-07-06
46
// Purpose:      PCMCIA support
47
// Description: 
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/io_pcmcia.h>
54
 
55
#include <cyg/io/pcmcia.h>
56
#include <cyg/infra/diag.h>
57
 
58
#if CYGHWR_IO_PCMCIA_DEVICE == 0
59
#error Need hardware package for PCMCIA support
60
#endif
61
 
62
#define CF_NUM_SLOTS CYGHWR_IO_PCMCIA_DEVICE
63
static struct cf_slot cf_slots[CF_NUM_SLOTS];
64
 
65
// Implementation routines
66
void cf_hwr_init(struct cf_slot *slot);
67
void cf_hwr_change_state(struct cf_slot *slot, int desired_state);
68
void cf_hwr_clear_interrupt(struct cf_slot *slot);
69
 
70
bool
71
cf_get_CIS(struct cf_slot *slot, unsigned char id,
72
           unsigned char *buf, int *len, int *ptr)
73
{
74
    int i, size;
75
    unsigned char *cis = slot->attr;
76
    unsigned char *cis_end = cis + slot->attr_length;
77
    cis += *ptr;
78
    while (cis < cis_end) {
79
        if (*cis == 0xFF) {
80
            break;
81
        }
82
        if (*cis == id) {
83
            size = *(cis+2) + 2;
84
            for (i = 0;  i < size;  i++) {
85
                *buf++ = *cis;
86
                cis += 2;
87
            }
88
            *len = size;
89
            *ptr = (unsigned long)(cis - slot->attr);
90
            return true;
91
        } else {
92
            // Skip to next entry
93
            cis += (*(cis+2) * 2) + 4;
94
        }
95
    }
96
    return false;
97
}
98
 
99
void
100
cf_set_COR(struct cf_slot *slot, unsigned long cor, unsigned char val)
101
{
102
    volatile unsigned char *cfg = slot->attr;
103
    cfg[cor] = val;
104
}
105
 
106
static void
107
cf_parse_power_structure(unsigned char **buf)
108
{
109
    unsigned char *bp = *buf;
110
    unsigned char tpce_pd = *bp++;
111
    unsigned char settings;
112
    int indx;
113
    for (indx = 6;  indx >= 0;  indx--) {
114
        if (tpce_pd & (1<<indx)) {
115
            settings = *bp++;  // main value
116
            if (settings & 0x80) {
117
                bp++;  // extension byte - FIXME
118
            }
119
        }
120
    }
121
    *buf = bp;
122
}
123
 
124
static void
125
cf_parse_timing_structure(unsigned char **buf)
126
{
127
    unsigned char *bp = *buf;
128
    unsigned char tpce_td = *bp++;
129
    if ((tpce_td & 0x1C) != 0x1C) {
130
//        diag_printf("READY = %x.%x\n",(tpce_td & 0x1C)>>2, *bp); 
131
        bp++;
132
    }
133
    if ((tpce_td & 0x03) != 0x03) {
134
//        diag_printf("WAIT = %x.%x\n",(tpce_td & 0x03)>>0, *bp); 
135
        bp++;
136
    }
137
    *buf = bp;
138
}
139
 
140
static void
141
cf_parse_IO_space_structure(unsigned char **buf, struct cf_io_space *io_space)
142
{
143
    unsigned char *bp = *buf;
144
    unsigned char tpce_io = *bp++;
145
    unsigned char rd;
146
    unsigned long base = 0, length = 0;
147
    int i;
148
    io_space->mode = (tpce_io & 0x60) >> 5;
149
    if (tpce_io & 0x80) {
150
        rd = *bp++;
151
        io_space->num_addrs = (rd & 0x0F) + 1;
152
        for (i = 0;  i < io_space->num_addrs;  i++) {
153
            // Address
154
            switch ((rd & 0x30) >> 4) {
155
            case 0:
156
                break;  // Not present (shouldn't happen)
157
            case 1:
158
                base = *bp++;
159
                break;
160
            case 2:
161
                base = (bp[1] << 8) | bp[0];
162
                bp += 2;
163
                break;
164
            case 3:
165
                base = (bp[3] << 24) | (bp[2] << 16) | (bp[1] << 8) | bp[0];
166
                bp += 4;
167
                break;
168
            }
169
            io_space->base[i] = base;
170
            // Length
171
            switch ((rd & 0xC0) >> 6) {
172
            case 0:
173
                break;  // Not present (shouldn't happen)
174
            case 1:
175
                length = *bp++;
176
                break;
177
            case 2:
178
                length = (bp[1] << 8) | bp[0];
179
                bp += 2;
180
                break;
181
            case 3:
182
                length = (bp[3] << 24) | (bp[2] << 16) | (bp[1] << 8) | bp[0];
183
                bp += 4;
184
                break;
185
            }
186
            length++;
187
            io_space->size[i] = length;
188
//            diag_printf("IO addr %d - base: %x, length: %x\n", i, base, length);
189
        }
190
    }
191
    *buf = bp;
192
}
193
 
194
bool
195
cf_parse_cftable(unsigned char *buf, int len, struct cf_cftable *cftable)
196
{
197
    unsigned char tpce_indx, tpce_fs;
198
    if (*buf++ != CF_CISTPL_CFTABLE_ENTRY) {
199
        diag_printf("%s - called with invalid CIS: %x\n", __FUNCTION__, *--buf);
200
        return false;
201
    }
202
    buf++;  // Skip length/link
203
    tpce_indx = *buf++;
204
    cftable->cor = tpce_indx & 0x3F;
205
    if (tpce_indx & 0x80) {
206
        cftable->interface = *buf++;
207
    }
208
    cftable->feature_select = tpce_fs = *buf++;
209
    if (tpce_fs & 0x01) {
210
        cf_parse_power_structure(&buf);
211
    }
212
    if (tpce_fs & 0x02) {
213
        cf_parse_power_structure(&buf);
214
    }
215
    if (tpce_fs & 0x04) {
216
        cf_parse_timing_structure(&buf);
217
    }
218
    if (tpce_fs & 0x08) {
219
        cf_parse_IO_space_structure(&buf, &cftable->io_space);
220
    }
221
    return true;
222
}
223
 
224
bool
225
cf_parse_config(unsigned char *buf, int len, struct cf_config *config)
226
{
227
    unsigned char tpcc_sz;
228
    int i;
229
    if (*buf++ != CF_CISTPL_CONFIG) {
230
        diag_printf("%s - called with invalid CIS: %x\n", __FUNCTION__, *--buf);
231
        return false;
232
    }
233
    buf++;  // Skip length/link
234
    tpcc_sz = *buf++;
235
    buf++;  // Skip 'last' pointer
236
    config->base = 0;
237
    for (i = (tpcc_sz & 0x03);  i >= 0;  i--) {
238
        config->base = (config->base << 8) | buf[i];
239
    }
240
    buf += (tpcc_sz & 0x03) + 1;
241
    config->mask_length = ((tpcc_sz & 0x3C) >> 2) + 1;
242
    for (i = 0;  i < config->mask_length;  i++) {
243
        config->mask[i] = *buf++;
244
    }
245
    return true;
246
}
247
 
248
//
249
// Return a pointer to the slot descriptor for a given slot
250
//
251
struct cf_slot *
252
cf_get_slot(int indx)
253
{
254
    if ((indx >= 0) && (indx < CF_NUM_SLOTS)) {
255
        return &cf_slots[indx];
256
    } else {
257
        diag_printf("PCMCIA: Invalid slot %d\n", indx);
258
        return (struct cf_slot *)0;
259
    }
260
}
261
 
262
//
263
// Initialize all PCMCIA (Compact Flash) slots
264
//
265
void
266
cf_init(void)
267
{
268
    int i;
269
    for (i = 0;  i < CF_NUM_SLOTS; i++) {
270
        cf_slots[i].index = i;
271
        cf_hwr_init(&cf_slots[i]);
272
    }
273
}
274
 
275
//
276
// Transition a card/slot
277
//
278
void
279
cf_change_state(struct cf_slot *slot, int desired_state)
280
{
281
    cf_hwr_change_state(slot, desired_state);
282
}
283
 
284
//
285
// Register an interrupt handler
286
//
287
void
288
cf_register_handler(struct cf_slot *slot,
289
                    void (*handler)(int, int, void *),
290
                    void *param)
291
{
292
    slot->irq_handler.handler = handler;
293
    slot->irq_handler.param = param;
294
}
295
 
296
//
297
// Allow interrupt function to acknowledge interrupt
298
//
299
void
300
cf_clear_interrupt(struct cf_slot *slot)
301
{
302
    cf_hwr_clear_interrupt(slot);
303
}
304
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.