1 //==========================================================================
5 // PCMCIA support (Card Services)
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.
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.
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
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.
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.
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.
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####
44 // Contributors: gthomas
46 // Purpose: PCMCIA support
49 //####DESCRIPTIONEND####
51 //==========================================================================
53 #include <pkgconf/io_pcmcia.h>
55 #include <cyg/io/pcmcia.h>
56 #include <cyg/infra/diag.h>
58 #if CYGHWR_IO_PCMCIA_DEVICE == 0
59 #error Need hardware package for PCMCIA support
62 #define CF_NUM_SLOTS CYGHWR_IO_PCMCIA_DEVICE
63 static struct cf_slot cf_slots[CF_NUM_SLOTS];
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);
71 cf_get_CIS(struct cf_slot *slot, unsigned char id,
72 unsigned char *buf, int *len, int *ptr)
75 unsigned char *cis = slot->attr;
76 unsigned char *cis_end = cis + slot->attr_length;
78 while (cis < cis_end) {
84 for (i = 0; i < size; i++) {
89 *ptr = (unsigned long)(cis - slot->attr);
93 cis += (*(cis+2) * 2) + 4;
100 cf_set_COR(struct cf_slot *slot, unsigned long cor, unsigned char val)
102 volatile unsigned char *cfg = slot->attr;
107 cf_parse_power_structure(unsigned char **buf)
109 unsigned char *bp = *buf;
110 unsigned char tpce_pd = *bp++;
111 unsigned char settings;
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
125 cf_parse_timing_structure(unsigned char **buf)
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);
133 if ((tpce_td & 0x03) != 0x03) {
134 // diag_printf("WAIT = %x.%x\n",(tpce_td & 0x03)>>0, *bp);
141 cf_parse_IO_space_structure(unsigned char **buf, struct cf_io_space *io_space)
143 unsigned char *bp = *buf;
144 unsigned char tpce_io = *bp++;
146 unsigned long base = 0, length = 0;
148 io_space->mode = (tpce_io & 0x60) >> 5;
149 if (tpce_io & 0x80) {
151 io_space->num_addrs = (rd & 0x0F) + 1;
152 for (i = 0; i < io_space->num_addrs; i++) {
154 switch ((rd & 0x30) >> 4) {
156 break; // Not present (shouldn't happen)
161 base = (bp[1] << 8) | bp[0];
165 base = (bp[3] << 24) | (bp[2] << 16) | (bp[1] << 8) | bp[0];
169 io_space->base[i] = base;
171 switch ((rd & 0xC0) >> 6) {
173 break; // Not present (shouldn't happen)
178 length = (bp[1] << 8) | bp[0];
182 length = (bp[3] << 24) | (bp[2] << 16) | (bp[1] << 8) | bp[0];
187 io_space->size[i] = length;
188 // diag_printf("IO addr %d - base: %x, length: %x\n", i, base, length);
195 cf_parse_cftable(unsigned char *buf, int len, struct cf_cftable *cftable)
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);
202 buf++; // Skip length/link
204 cftable->cor = tpce_indx & 0x3F;
205 if (tpce_indx & 0x80) {
206 cftable->interface = *buf++;
208 cftable->feature_select = tpce_fs = *buf++;
209 if (tpce_fs & 0x01) {
210 cf_parse_power_structure(&buf);
212 if (tpce_fs & 0x02) {
213 cf_parse_power_structure(&buf);
215 if (tpce_fs & 0x04) {
216 cf_parse_timing_structure(&buf);
218 if (tpce_fs & 0x08) {
219 cf_parse_IO_space_structure(&buf, &cftable->io_space);
225 cf_parse_config(unsigned char *buf, int len, struct cf_config *config)
227 unsigned char tpcc_sz;
229 if (*buf++ != CF_CISTPL_CONFIG) {
230 diag_printf("%s - called with invalid CIS: %x\n", __FUNCTION__, *--buf);
233 buf++; // Skip length/link
235 buf++; // Skip 'last' pointer
237 for (i = (tpcc_sz & 0x03); i >= 0; i--) {
238 config->base = (config->base << 8) | buf[i];
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++;
249 // Return a pointer to the slot descriptor for a given slot
252 cf_get_slot(int indx)
254 if ((indx >= 0) && (indx < CF_NUM_SLOTS)) {
255 return &cf_slots[indx];
257 diag_printf("PCMCIA: Invalid slot %d\n", indx);
258 return (struct cf_slot *)0;
263 // Initialize all PCMCIA (Compact Flash) slots
269 for (i = 0; i < CF_NUM_SLOTS; i++) {
270 cf_slots[i].index = i;
271 cf_hwr_init(&cf_slots[i]);
276 // Transition a card/slot
279 cf_change_state(struct cf_slot *slot, int desired_state)
281 cf_hwr_change_state(slot, desired_state);
285 // Register an interrupt handler
288 cf_register_handler(struct cf_slot *slot,
289 void (*handler)(int, int, void *),
292 slot->irq_handler.handler = handler;
293 slot->irq_handler.param = param;
297 // Allow interrupt function to acknowledge interrupt
300 cf_clear_interrupt(struct cf_slot *slot)
302 cf_hwr_clear_interrupt(slot);