This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: io-pcmcia patch


Gary Thomas wrote:
Shaun Louie wrote:
Hi,

This patch adds the cf_remove_handler() function (counterpart to cf_register_handler). It also adds calls to cf_hwr_interrupt_enable() and cf_hwr_interrupt_disable(). Since these are new functions to be provided by the driver, some empty functions will need to be added in any existing drivers (e.g. devs/pcmcia/arm/cerf). I can provide a patch if you like, but I won't be able to test. I'll be providing a PCMCIA driver for the PowerPC MPC8xx shortly.

This (and the MPC8xx driver) overall look OK, but we'll need a few things before much more can be done with them.

* You need a copyright assignment (unless I missed it)
Please see http://ecos.sourceware.org/assign.html
I sent the email request to the FSF (assign@gnu.org) today finally. We're working towards getting the company I work for, Microplex Systems, covered by the assignment...
* The MPC8xx driver is too platform specific. We try to
split drivers into architecture (or CPU family) + target.
In this case, I think that all of the details like where the
window is mapped, what I/O pins are used for VSn, etc,
should be in a target [include] file, not coded directly
within the MPC8xx driver.
... in the meantime, the attached patch file should address the issues mentioned above. I added a section at the top of pcmcia_mpc8xx.h that describes what needs to be provided by the target.

Shaun


diff -r -U 5 -N -x CVS -x '*~' -x '.#~' ecos.20080311/packages/devs/pcmcia/powerpc/mpc8xx/current/cdl/pcmcia_mpc8xx.cdl ecos.20080311.pcmcia-mpc8xx/packages/devs/pcmcia/powerpc/mpc8xx/current/cdl/pcmcia_mpc8xx.cdl
--- ecos.20080311/packages/devs/pcmcia/powerpc/mpc8xx/current/cdl/pcmcia_mpc8xx.cdl	1969-12-31 18:00:00.000000000 -0600
+++ ecos.20080311.pcmcia-mpc8xx/packages/devs/pcmcia/powerpc/mpc8xx/current/cdl/pcmcia_mpc8xx.cdl	2008-04-29 11:17:35.000000000 -0600
@@ -0,0 +1,66 @@
+# ====================================================================
+#
+#      PowerPC MPC8XX PCMCIA support
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):        Shaun Louie
+# Contributors:
+# Date:             2008-04-29
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_PCMCIA_MPC8XX {
+    display         "PowerPC MPC8XX PCMCIA support"
+    implements      CYGHWR_IO_PCMCIA_DEVICE
+    parent          CYGPKG_IO_PCMCIA
+    active_if       CYGPKG_IO_PCMCIA
+    active_if       CYGPKG_HAL_POWERPC_MPC8xx
+    include_dir     .
+    include_files   ; # none _exported_ whatsoever
+    description     "PCMCIA (Compact Flash) device support for owerPC MPC8XX"
+    compile         pcmcia_mpc8xx.c
+
+    cdl_option CYGPKG_DEVS_PCMCIA_MPC8XX_DETECT {
+        display         "Enable Detect Card Interrupt"
+        flavor          bool
+        calculated      0
+        description     "This option is currently not supported by the driver."
+    }
+}
diff -r -U 5 -N -x CVS -x '*~' -x '.#~' ecos.20080311/packages/devs/pcmcia/powerpc/mpc8xx/current/ChangeLog ecos.20080311.pcmcia-mpc8xx/packages/devs/pcmcia/powerpc/mpc8xx/current/ChangeLog
--- ecos.20080311/packages/devs/pcmcia/powerpc/mpc8xx/current/ChangeLog	1969-12-31 18:00:00.000000000 -0600
+++ ecos.20080311.pcmcia-mpc8xx/packages/devs/pcmcia/powerpc/mpc8xx/current/ChangeLog	2008-04-29 11:11:36.000000000 -0600
@@ -0,0 +1,41 @@
+2008-04-29  Shaun Louie  <sal@microplex.com>
+
+    * cdl/pcmcia_mpc8xx.cdl:
+    * src/pcmcia_mpc8xx.c:
+    * src/pcmcia_mpc8xx.h:
+    Initial check-in of the PCMCIA device driver for the PowerPC MPC8xx.
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
diff -r -U 5 -N -x CVS -x '*~' -x '.#~' ecos.20080311/packages/devs/pcmcia/powerpc/mpc8xx/current/src/pcmcia_mpc8xx.c ecos.20080311.pcmcia-mpc8xx/packages/devs/pcmcia/powerpc/mpc8xx/current/src/pcmcia_mpc8xx.c
--- ecos.20080311/packages/devs/pcmcia/powerpc/mpc8xx/current/src/pcmcia_mpc8xx.c	1969-12-31 18:00:00.000000000 -0600
+++ ecos.20080311.pcmcia-mpc8xx/packages/devs/pcmcia/powerpc/mpc8xx/current/src/pcmcia_mpc8xx.c	2008-04-29 11:17:22.000000000 -0600
@@ -0,0 +1,911 @@
+//==========================================================================
+//
+//      PowerPC MPC8XX PCMCIA support
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):       slouie
+// Contributors:    slouie
+// Date:            2008-04-29
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <string.h>
+
+#include <pkgconf/io_pcmcia.h>
+
+#include <cyg/hal/hal_io.h> // IO macros
+#include <cyg/hal/hal_arch.h> // Register state info
+#include <cyg/hal/hal_intr.h> // HAL interrupt macros
+#include <cyg/hal/drv_api.h>
+
+#ifdef CYGPKG_KERNEL
+#include <pkgconf/kernel.h> // Configuration header
+#include <cyg/kernel/kapi.h>
+#endif
+#include <cyg/hal/hal_if.h>
+
+#include <cyg/io/pcmcia.h>
+#include <cyg/infra/diag.h>
+
+#include <cyg/hal/ppc8xx.h>
+#include "pcmcia_mpc8xx.h"
+
+#ifdef CYGPKG_KERNEL
+# ifdef CYGPKG_DEVS_PCMCIA_MPC8XX_DETECT
+static cyg_interrupt cf_detect_interrupt;
+static cyg_handle_t cf_detect_interrupt_handle;
+static int cf_detect_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs);
+static void cf_detect_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+# endif
+static cyg_interrupt cf_irq_interrupt;
+static cyg_handle_t cf_irq_interrupt_handle;
+static int cf_irq_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs);
+static void cf_irq_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+#endif
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_init
+ *  DESCRIPTION
+ *      Fill in the details of a PCMCIA slot and initialize the device
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      void
+ *---------------------------------------------------------------
+ */
+void
+cf_hwr_init(struct cf_slot * slot)
+{
+    static int                  int_init = 0;
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+    int                         i;
+
+    pcmcia_custom_init(slot);
+    HAL_DELAY_US(PCMCIA_POWER_OFF_DELAY);
+
+    /* Disable all PCMCIA interrupts. */
+    pcmciaRegPtr->per.reg = 0;
+    /* Clear all PCMCIA interrupt flags. */
+    pcmciaRegPtr->pscr.reg = 0xffffffff;
+    /* Invalidate all PCMCIA address spaces. */
+    for (i = 0; i < 8; i++) {
+        pcmciaRegPtr->pir.array[i].por = 0;
+    }
+    /*
+     * Configure the CPM interrupt level, and disable the output
+     * enable pin.  Note, both slots will use the same interrupt
+     * level.
+     */
+    pcmciaRegPtr->pgcr.reg.A = PCMCIA_PGCR_INTR_LVL(PCMCIA_INTERRUPT) | PCMCIA_PGCR_OE;
+    pcmciaRegPtr->pgcr.reg.B = PCMCIA_PGCR_INTR_LVL(PCMCIA_INTERRUPT) | PCMCIA_PGCR_OE;
+
+    /* Do a hard reset */
+    if ( ! cf_hwr_reset_hard(slot) ) {
+        slot->state = CF_SLOT_STATE_Empty;
+        return;
+    }
+
+    /* Initialiaze the interrupt service routine. */
+    if (!int_init) {
+        int_init = 1;
+#ifdef CYGPKG_KERNEL
+        // Set up interrupts
+# ifdef CYGPKG_DEVS_PCMCIA_MPC8XX_DETECT
+        cyg_drv_interrupt_create(SA1110_CF_DETECT,
+                                 CYGARC_SIU_PRIORITY_HIGH,
+                                 (cyg_addrword_t)slot, /* Data item passed to interrupt handler */
+                                 (cyg_ISR_t *)cf_detect_isr,
+                                 (cyg_DSR_t *)cf_detect_dsr,
+                                 &cf_detect_interrupt_handle,
+                                 &cf_detect_interrupt);
+        cyg_drv_interrupt_attach(cf_detect_interrupt_handle);
+        cyg_drv_interrupt_configure(SA1110_CF_DETECT, true, true); /* Detect either edge */
+        cyg_drv_interrupt_acknowledge(SA1110_CF_DETECT);
+        cyg_drv_interrupt_unmask(SA1110_CF_DETECT);
+# endif /* CYGPKG_DEVS_PCMCIA_MPC8XX_DETECT */
+
+        cyg_drv_interrupt_create(PCMCIA_SIU_INTR,
+                                 CYGARC_SIU_PRIORITY_HIGH,
+                                 (cyg_addrword_t)slot, /* Data item passed to interrupt handler */
+                                 (cyg_ISR_t *)cf_irq_isr,
+                                 (cyg_DSR_t *)cf_irq_dsr,
+                                 &cf_irq_interrupt_handle,
+                                 &cf_irq_interrupt);
+        //cyg_drv_interrupt_configure(PCMCIA_SIU_INTR, false, false); /* Falling edge */
+        cyg_drv_interrupt_attach(cf_irq_interrupt_handle);
+        cyg_drv_interrupt_acknowledge(PCMCIA_SIU_INTR);
+        cyg_drv_interrupt_unmask(PCMCIA_SIU_INTR);
+#endif /* CYGPKG_KERNEL */
+    }
+    slot->int_num = PCMCIA_SIU_INTR;
+
+    /* Attempt to switch to the ready state */
+    if ( ! cf_hwr_change_state(slot, CF_SLOT_STATE_Ready) ) {
+        slot->state = CF_SLOT_STATE_Empty;
+        return;
+    }
+} /* cf_hwr_init */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_poll
+ *  DESCRIPTION
+ *
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      void
+ *---------------------------------------------------------------
+ */
+void
+cf_hwr_poll(struct cf_slot *slot)
+{
+    if (cf_hwr_card_inserted(slot)) {
+        if (1) {
+            slot->state = CF_SLOT_STATE_Ready;
+        }
+        else {
+            slot->state = CF_SLOT_STATE_Inserted;
+        }
+    }
+    else {
+        slot->state = CF_SLOT_STATE_Empty;
+    }
+} /* cf_hwr_poll */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_change_state
+ *  DESCRIPTION
+ *      Transition the card/slot to a new state
+ *      Currently only supports transition from Inserted to Ready
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *      new_state               ; new device state
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+cf_hwr_change_state(struct cf_slot *slot, int new_state)
+{
+    switch (slot->state) {
+        case CF_SLOT_STATE_Inserted:
+            if (new_state == CF_SLOT_STATE_Ready) {
+                /* Transition from Inserted to Ready */
+                /* Do a soft reset */
+                if ( ! cf_hwr_reset_soft(slot) ) {
+                    return false;
+                }
+                slot->state = CF_SLOT_STATE_Ready;
+                return true;
+            }
+            else {
+                return false;
+            }
+
+        default:
+            return false;
+    } /* switch */
+} /* cf_hwr_change_state */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_reset_hard
+ *  DESCRIPTION
+ *
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+cf_hwr_reset_hard(struct cf_slot * slot)
+{
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+    unsigned char               tupleBuf[MAX_TUPLE_SZ];
+    unsigned char *             tupleBufPtr;
+    unsigned char               cardType;
+
+#if 0 /* Disabled, since it's not required for now. */
+    /* Disable slot's interrupts. */
+    pcmciaRegPtr->per.slot[slot->index] = 0x0000;
+    /* Clear slot's interrupt flags. */
+    pcmciaRegPtr->pscr.slot[slot->index] = 0xffff;
+    /* Invalidate slot's address spaces. */
+    pcmciaRegPtr->pir.slot[slot->index].comm.por = 0x00000000;
+    pcmciaRegPtr->pir.slot[slot->index].attr.por = 0x00000000;
+    pcmciaRegPtr->pir.slot[slot->index].io.por = 0x00000000;
+#endif
+    /* Disable card's output enable pin */
+    pcmciaRegPtr->pgcr.slot[slot->index] |= PCMCIA_PGCR_OE;
+
+    pcmcia_custom_off(slot);
+    HAL_DELAY_US(PCMCIA_POWER_OFF_DELAY);
+
+    /* Enable card's output enable pin */
+    pcmciaRegPtr->pgcr.slot[slot->index] &= ~PCMCIA_PGCR_OE;
+    /* Is a card inserted. */
+    if ( ! cf_hwr_card_inserted(slot) ) {
+        /* No card, so disable card's output enable pin */
+        pcmciaRegPtr->pgcr.slot[slot->index] |= PCMCIA_PGCR_OE;
+        slot->state = CF_SLOT_STATE_Empty;
+        return false;
+    }
+    slot->state = CF_SLOT_STATE_Inserted;
+
+    /* Power-up card to a voltage determind by the voltage-select pins. */
+    pcmcia_custom_on(slot, _pcmcia_get_vs(slot));
+    HAL_DELAY_US(PCMCIA_POWER_ON_DELAY);
+
+    /* Give card a hard reset to make sure it fires-up. */
+    pcmciaRegPtr->pgcr.slot[slot->index] |= PCMCIA_PGCR_RESET;
+    HAL_DELAY_US(PCMCIA_HARD_RESET_PULSE);
+    pcmciaRegPtr->pgcr.slot[slot->index] &= ~PCMCIA_PGCR_RESET;
+    HAL_DELAY_US(PCMCIA_HARD_RESET_DELAY);
+
+    /* Initialize memory mapping for the PCMCIA channel. */
+    if ( ! _pcmcia_memmap_init(slot) ) {
+        pcmcia_custom_off(slot);
+        HAL_DELAY_US(PCMCIA_POWER_OFF_DELAY);
+        return false;
+    }
+
+    /* Find out what card is at this PCMCIA channel */
+    tupleBufPtr = tupleBuf;
+    if ( ! _pcmcia_get_cis_tuple(slot, CF_CISTPL_FUNCID, tupleBufPtr) ) {
+        pcmcia_custom_off(slot);
+        HAL_DELAY_US(PCMCIA_POWER_OFF_DELAY);
+        return false;
+    }
+    cardType = *(tupleBufPtr + 2);
+    if (cardType == CF_SLOT_TYPE_UNKNOWN) {
+        pcmcia_custom_off(slot);
+        HAL_DELAY_US(PCMCIA_POWER_OFF_DELAY);
+        return false;
+    }
+    return true;
+} /* cf_hwr_reset_hard */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_reset_soft
+ *  DESCRIPTION
+ *
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+cf_hwr_reset_soft(struct cf_slot * slot)
+{
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+    unsigned int                confBaseAddr;
+
+    if ( ! _pcmcia_conf_baseaddr(slot, &confBaseAddr) ) {
+        pcmcia_custom_off(slot);
+        HAL_DELAY_US(PCMCIA_POWER_OFF_DELAY);
+        return false;
+    }
+    cf_set_COR(slot, confBaseAddr, CF_COR_SOFT_RESET);
+    HAL_DELAY_US(PCMCIA_SOFT_RESET_PULSE);
+    cf_set_COR(slot, confBaseAddr, (unsigned char)~CF_COR_SOFT_RESET);
+    HAL_DELAY_US(PCMCIA_SOFT_RESET_DELAY);
+    /* Clear all slot's interrupt flags. */
+    pcmciaRegPtr->pscr.slot[slot->index] = 0xffff;
+    return true;
+} /* cf_hwr_reset_soft */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_interrupt_enable
+ *  DESCRIPTION
+ *      Enable Pcmcia IRQ interrupt for a given slot.
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      none
+ *---------------------------------------------------------------
+ */
+void
+cf_hwr_interrupt_enable(struct cf_slot * slot)
+{
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+
+    if (slot->int_disable_nest_lvl) {
+        slot->int_disable_nest_lvl--;
+    }
+    if (slot->int_disable_nest_lvl == 0) {
+        /* Enable falling edge IRQ interrupt. */
+        pcmciaRegPtr->per.slot[slot->index] |= PCMCIA_IRQ_F;
+    }
+} /* cf_hwr_interrupt_enable */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_interrupt_disable
+ *  DESCRIPTION
+ *      Disable Pcmcia IRQ interrupt for a given slot.
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      none
+ *---------------------------------------------------------------
+ */
+void
+cf_hwr_interrupt_disable(struct cf_slot * slot)
+{
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+
+    if (slot->int_disable_nest_lvl == 0) {
+        /* Disable falling edge IRQ interrupt. */
+        pcmciaRegPtr->per.slot[slot->index] &= ~PCMCIA_IRQ_F;
+    }
+    slot->int_disable_nest_lvl++;
+} /* cf_hwr_interrupt_disable */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_clear_interrupt
+ *  DESCRIPTION
+ *      Acknowledge interrupt (used in non-kernel environments)
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      void
+ *---------------------------------------------------------------
+ */
+void
+cf_hwr_clear_interrupt(struct cf_slot *slot)
+{
+    cyg_drv_interrupt_acknowledge(PCMCIA_SIU_INTR);
+} /* cf_hwr_clear_interrupt */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_hwr_card_inserted
+ *  DESCRIPTION
+ *      Tests the harware to determine if a card is inserted
+ *      into a given slot.
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+cf_hwr_card_inserted(struct cf_slot *slot)
+{
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+
+    return ( (pcmciaRegPtr->pipr.slot[slot->index] & (PCMCIA_CD1 | PCMCIA_CD2)) == 0 );
+} /* cf_hwr_card_inserted */
+
+#ifdef CYGPKG_KERNEL
+# ifdef CYGPKG_DEVS_PCMCIA_MPC8XX_DETECT
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_detect_isr
+ *  DESCRIPTION
+ *      This ISR is called when a CompactFlash board is inserted
+ *  PARAMETERS
+ *      vector
+ *      data
+ *      regs
+ *  RETURNS
+ *      int
+ *---------------------------------------------------------------
+ */
+static int
+cf_detect_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters * regs)
+{
+    cyg_interrupt_mask(SA1110_CF_DETECT);
+    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
+} /* cf_detect_isr */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_detect_dsr
+ *  DESCRIPTION
+ *      This DSR handles the board insertion
+ *  PARAMETERS
+ *      vector
+ *      count
+ *      data
+ *  RETURNS
+ *      void
+ *---------------------------------------------------------------
+ */
+static void
+cf_detect_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    unsigned long               new_state = *SA11X0_GPIO_PIN_LEVEL;
+    struct cf_slot *            slot = (struct cf_slot *)data;
+
+    if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) {
+        slot->state = CF_SLOT_STATE_Inserted;
+    }
+    else {
+        slot->state = CF_SLOT_STATE_Removed;  // Implies powered up, etc.
+    }
+    cyg_interrupt_acknowledge(SA1110_CF_DETECT);
+    cyg_interrupt_unmask(SA1110_CF_DETECT);
+} /* cf_detect_dsr */
+# endif /* CYGPKG_DEVS_PCMCIA_MPC8XX_DETECT */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_irq_isr
+ *  DESCRIPTION
+ *      This ISR is called when the card interrupt occurs
+ *  PARAMETERS
+ *      vector
+ *      data
+ *      regs
+ *  RETURNS
+ *      int
+ *---------------------------------------------------------------
+ */
+static int
+cf_irq_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters * regs)
+{
+    cyg_drv_interrupt_mask(PCMCIA_SIU_INTR);
+    return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);  // Run the DSR
+} /* cf_irq_isr */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      cf_irq_dsr
+ *  DESCRIPTION
+ *      This DSR handles the card interrupt
+ *  PARAMETERS
+ *      vector
+ *      count
+ *      data
+ *  RETURNS
+ *      void
+ *---------------------------------------------------------------
+ */
+static void
+cf_irq_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    struct cf_slot *            slot = (struct cf_slot *)data;
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+
+    /* Test for falling edge on IRQ. */
+    if ( ! (pcmciaRegPtr->pscr.slot[slot->index] & PCMCIA_IRQ_F) ) {
+        goto Exit;
+    }
+    /* Clear interrupt flag (write '1' to clear). */
+    pcmciaRegPtr->pscr.slot[slot->index] = PCMCIA_IRQ_F;
+    /* Check for an interrupt handler function */
+    if (slot->irq_handler.handler) {
+        slot->irq_handler.handler(vector, count, slot->irq_handler.param);
+    }
+  Exit:
+    cyg_drv_interrupt_acknowledge(vector);
+    cyg_drv_interrupt_unmask(vector);
+} /* cf_irq_dsr */
+#endif /* CYGPKG_KERNEL */
+
+/*=========================================================================
+ * PCMCIA HELPER FUNCTIONS
+ *=======================================================================*/
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      _pcmcia_get_vs
+ *  DESCRIPTION
+ *      Returns the slot's voltage sense value.
+ *
+ *      Voltage sense pin value table.
+ *      -----+-----+-------------------------------
+ *       VS1 | VS2 | Description
+ *      -----+-----+-------------------------------
+ *        0  |  0  | X.XV, else 3.3V, else none
+ *        0  |  1  | 3.3V, else none
+ *        1  |  0  | X.XV, else none
+ *        1  |  1  | 5V, else none
+ *      -----+-----+-------------------------------
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+unsigned int
+_pcmcia_get_vs(struct cf_slot * slot)
+{
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+    unsigned int                vselect;
+
+    vselect = pcmciaRegPtr->pipr.slot[slot->index] & (PCMCIA_VS1 | PCMCIA_VS2);
+    switch (vselect) {
+        case PCMCIA_VS2:
+            return 3;
+
+        case PCMCIA_VS1 | PCMCIA_VS2:
+            return 5;
+
+        default:
+            return 0;
+    } /* switch */
+} /* _pcmcia_get_vs */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      _pcmcia_get_por_bsize
+ *  DESCRIPTION
+ *
+ *  PARAMETERS
+ *
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+_pcmcia_get_por_bsize(unsigned int windowsz, unsigned int * bsizep)
+{
+    int                         i;
+
+    for (i=0; i<PCMCIA_POR_BSIZE_TBL_LEN; i++) {
+        if (_pcmciaPorBsizeTbl[i].windowsz == windowsz) {
+            *bsizep = _pcmciaPorBsizeTbl[i].bsize;
+            return true;
+        }
+    }
+    return false;
+} /* _pcmcia_get_por_bsize */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      _pcmcia_memmap_init
+ *  DESCRIPTION
+ *      Initialize PCMCIA memory/IO address space.
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+_pcmcia_memmap_init(struct cf_slot * slot)
+{
+    unsigned int                ioStartAddr; /* io space start address. */
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+    unsigned int                offset = 0;
+    unsigned int                bsize;
+
+    if (slot->index != 0) {
+        /* The starting addresses are only defined for the first slot */
+        return false;
+    }
+
+    /* PCMCIA_A_COMM_MEM */
+    slot->mem = (unsigned char *)(PCMCIA_MPC8XX_MEMORY_START + offset);
+    slot->mem_length = PCMCIA_MPC8XX_WINSZ_COMMON;
+    offset += PCMCIA_MPC8XX_WINSZ_COMMON;
+    if ( ! _pcmcia_get_por_bsize(PCMCIA_MPC8XX_WINSZ_COMMON, &bsize) ) {
+        return false;
+    }
+    pcmciaRegPtr->pir.slot[slot->index].comm.por = PCMCIA_POR_SLOT_A;
+    pcmciaRegPtr->pir.slot[slot->index].comm.pbr = (unsigned int)slot->mem;
+    pcmciaRegPtr->pir.slot[slot->index].comm.por |=
+        PCMCIA_POR_COMM_MEM |
+        PCMCIA_POR_PV |
+        PCMCIA_POR_PSHT(PCMCIA_DFLT_HOLD_TIME) |
+        PCMCIA_POR_PSST(PCMCIA_DFLT_SETUP_TIME) |
+        PCMCIA_POR_PSL(PCMCIA_DFLT_LEN_TIME) |
+        PCMCIA_POR_BSIZE(bsize);
+
+    /* PCMCIA_A_ATTR_MEM */
+    slot->attr = (unsigned char *)(PCMCIA_MPC8XX_MEMORY_START + offset);
+    slot->attr_length = PCMCIA_MPC8XX_WINSZ_ATTR;
+    offset += PCMCIA_MPC8XX_WINSZ_ATTR;
+    if ( ! _pcmcia_get_por_bsize(PCMCIA_MPC8XX_WINSZ_ATTR, &bsize) ) {
+        return false;
+    }
+    pcmciaRegPtr->pir.slot[slot->index].attr.por = PCMCIA_POR_SLOT_A;
+    pcmciaRegPtr->pir.slot[slot->index].attr.pbr = (unsigned int)slot->attr;
+    pcmciaRegPtr->pir.slot[slot->index].attr.por |=
+        PCMCIA_POR_ATTR_MEM |
+        PCMCIA_POR_PV |
+        PCMCIA_POR_PSHT(PCMCIA_DFLT_HOLD_TIME) |
+        PCMCIA_POR_PSST(PCMCIA_DFLT_SETUP_TIME) |
+        PCMCIA_POR_PSL(PCMCIA_DFLT_LEN_TIME) |
+        PCMCIA_POR_BSIZE(bsize);
+
+    /* PCMCIA_A_IO_SPACE */
+    slot->io = (unsigned char *)(PCMCIA_MPC8XX_MEMORY_START + offset);
+    slot->io_length = PCMCIA_MPC8XX_WINSZ_IO;
+    offset += PCMCIA_MPC8XX_WINSZ_IO;
+    if ( ! _pcmcia_get_por_bsize(PCMCIA_MPC8XX_WINSZ_IO, &bsize) ) {
+        return false;
+    }
+    pcmciaRegPtr->pir.slot[slot->index].io.por = PCMCIA_POR_SLOT_A;
+    pcmciaRegPtr->pir.slot[slot->index].io.pbr = (unsigned int)slot->io;
+    pcmciaRegPtr->pir.slot[slot->index].io.por |=
+        PCMCIA_POR_IO_SPACE |
+        PCMCIA_POR_PV |
+        PCMCIA_POR_PSHT(PCMCIA_DFLT_HOLD_TIME) |
+        PCMCIA_POR_PSST(PCMCIA_DFLT_SETUP_TIME) |
+        PCMCIA_POR_PSL(PCMCIA_DFLT_LEN_TIME) |
+        PCMCIA_POR_BSIZE(bsize);
+
+    /* Do some funny stuff with the IO space */
+    if ( ! _pcmcia_get_startioaddr(slot, &ioStartAddr) ) {
+        return false;
+    }
+    slot->io = (unsigned char *)(ioStartAddr + (unsigned int)slot->io);
+    return true;
+} /* _pcmcia_memmap_init */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      _pcmcia_conf_baseaddr
+ *  DESCRIPTION
+ *      Find PCMCIA configuration base address from
+ *      Card Information Structure.
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *      confBaseAddrPtr         ; pointer to configuration base address.
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+_pcmcia_conf_baseaddr(struct cf_slot * slot, unsigned int * confBaseAddrPtr)
+{
+    unsigned char               tpccRasz; /* size of fields type */
+    unsigned short              byteCnt; /* remain address byte count */
+    /* local buffer to store tuple content */
+    unsigned char               tupleBuf[MAX_TUPLE_SZ];
+    unsigned char *             tupleBufPtr;
+
+    /* First, find the CISTPL_CONFIG tuple. */
+    tupleBufPtr = tupleBuf;
+    if ( ! _pcmcia_get_cis_tuple(slot, CF_CISTPL_CONFIG, tupleBuf) ) {
+        return 0;
+    }
+    tupleBufPtr = tupleBuf;
+    tupleBufPtr += 2;
+    tpccRasz = (*tupleBufPtr & TPCC_RASZ_MASK) + 1;
+    tpccRasz = (tpccRasz > 4) ? 4 : tpccRasz;
+    tupleBufPtr += 2;
+    /* Read confBaseAddr starting from tupleBufPtr */
+    *confBaseAddrPtr = 0;
+    byteCnt = tpccRasz;
+    while ( byteCnt-- ) {
+        *confBaseAddrPtr |= (unsigned int)(*tupleBufPtr++ << (8 * (tpccRasz - byteCnt - 1)));
+    }
+    return 1;
+} /* _pcmcia_conf_baseaddr */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      _pcmcia_get_startioaddr
+ *  DESCRIPTION
+ *      Obtain start I/O address from PCMCIA card.
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *      startIoAddrPtr          ; pointer to start of I/O address block.
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+_pcmcia_get_startioaddr(struct cf_slot * slot, unsigned int * startIoAddrPtr)
+{
+    unsigned char               tmpCisByte;         /* temperary CIS byte */
+    unsigned char               byteCnt;            /* byte counter */
+    unsigned char               ioAddrSz;           /* I/O address size */
+    unsigned char               fsByte;             /* feature selection byte */
+    /* local buffer to store tuple content */
+    unsigned char               tupleBuf[MAX_TUPLE_SZ];
+    unsigned char *             tupleBufPtr;        /* ptr to tuple buffer pointer */
+    unsigned char               bitMask;
+    unsigned char               ioAddrLines;
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+
+    /*
+     * Since the tuple has been copied to local memory, the content of the
+     * the tuple is continuous.
+     */
+    tupleBufPtr = (unsigned char *)tupleBuf;
+    if ( ! _pcmcia_get_cis_tuple(slot, CF_CISTPL_CFTABLE_ENTRY, (unsigned char *)tupleBuf) ) {
+        return 0;
+    }
+    tupleBufPtr += 2;
+    /* Check to see if an interface configuration byte follows. */
+    if ( *tupleBufPtr++ & TPCE_IF_MASK ) {
+        tupleBufPtr++;
+    }
+    /* Get the feature selection byte */
+    fsByte = *tupleBufPtr;
+    /* Return error if I/O space description structure is not present. */
+    if ( !(fsByte & TPCE_FS_IO_MASK) ) {
+        return 0;
+    }
+    byteCnt = fsByte & TPCE_FS_PD_MASK;
+    /* Parsing the TPCE_FS_PD if it exists */
+    tupleBufPtr++;
+    while ( byteCnt-- ) {
+        tmpCisByte = *tupleBufPtr++;
+
+#if 0 /* only for debugging */
+        if ( byteCnt == 0) {
+            int                 vcc;
+
+            if ( tmpCisByte & TPCE_VC_NOM ) {
+                if ( *tupleBufPtr & 0x35 ) {
+                    /* 3V */
+                    vcc = 3;
+                }
+                else {
+                    /* 5V */
+                    vcc = 5;
+                }
+            }
+            else {
+                vcc = 5;
+            }
+        }
+#endif
+
+        for ( bitMask = 1 ; bitMask < 0x80; bitMask <<= 1 ) {
+            if ( tmpCisByte & bitMask ) {
+                if ( *tupleBufPtr++ & TPCE_FS_PD_EXT ) {
+                    tupleBufPtr++;
+                }
+            }
+        } /* for */
+    } /* while */
+
+    tmpCisByte = *tupleBufPtr;
+    /* Check to see if timing structure is present. */
+    if ( fsByte & TPCE_FS_TI_MASK ) {
+        tupleBufPtr++;
+        if ( (tmpCisByte & TPCE_TD_WAITSCALE_MASK )
+            != TPCE_TD_WAITSCALE_UNUSED ) {
+            tupleBufPtr++;
+        }
+        if ( (tmpCisByte & TPCE_TD_REBU_MASK )
+            != TPCE_TD_REBU_UNUSED ) {
+            tupleBufPtr++;
+        }
+        if ( (tmpCisByte & TPCE_TD_RESERVED_MASK )
+            != TPCE_TD_RESERVED_UNUSED ) {
+            tupleBufPtr++;
+        }
+        tmpCisByte = *tupleBufPtr;
+    }
+    /* Determine I/O bus size needed by card. */
+    if ( tmpCisByte & TPCE_IO_BUS16 ){
+        /*
+         * Card wants 16 bit I/O cycles, so set the PCMCIA interface
+         * to 16 bit I/O.
+         */
+        pcmciaRegPtr->pir.slot[slot->index].io.por |= PCMCIA_POR_PS16;
+    }
+    if ( !(tmpCisByte & TPCE_IO_RANGE ) ){
+        ioAddrLines = (tmpCisByte & IO_ADDR_LINES_MASK);
+        /* Make sure *startIoAddrPtr > 0x100 */
+        ioAddrLines = (ioAddrLines > 10)? ioAddrLines : 10;
+        /* I/O addr lines 27-31 are reserved. Some Agere (Orinoco,Lucent) cards
+           are using them nevertheless. Tests show the following to fix that. */
+        if ( ioAddrLines < 27) {
+            *startIoAddrPtr = 1 << ioAddrLines;
+        }
+        else {
+            *startIoAddrPtr = 0;
+        }
+        return 1;
+    }
+    /* Assuming 1 range, so one start I/O address for now. */
+    tupleBufPtr++;
+    /* Obtain length and size fields byte */
+    tmpCisByte = *tupleBufPtr;
+    ioAddrSz = (tmpCisByte & 0x30) >> 4;
+    if ( ioAddrSz == 0 ) {
+        return 0;
+    }
+    if (ioAddrSz == 3 ) {
+        ioAddrSz = 4;
+    }
+    byteCnt = ioAddrSz;
+    *startIoAddrPtr = 0;
+    tupleBufPtr++;
+    while ( byteCnt-- ) {
+        *startIoAddrPtr |= (unsigned int)*tupleBufPtr++ << (8 * (ioAddrSz - byteCnt -  1));
+    }
+    return 1;
+} /* _pcmcia_get_startioaddr */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      _pcmcia_get_cis_tuple
+ *  DESCRIPTION
+ *      Find the specified tuple in the CIS of the PCMCIA channel
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *      tplCode                 ; tuple code
+ *      tupleBufPtr             ; pointer to tuple buffer
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+_pcmcia_get_cis_tuple(struct cf_slot * slot, unsigned char tplCode,
+        unsigned char * tupleBufPtr)
+{
+    int                         offset;
+    int                         len;
+
+    offset = 0;
+    return cf_get_CIS(slot, tplCode, tupleBufPtr, &len, &offset);
+} /* _pcmcia_get_cis_tuple */
+
+/*FUNCTION:------------------------------------------------------
+ *  NAME
+ *      pcmcia_poll_irq
+ *  DESCRIPTION
+ *
+ *  PARAMETERS
+ *      slot                    ; pointer to pcmcia object
+ *  RETURNS
+ *      bool
+ *---------------------------------------------------------------
+ */
+bool
+pcmcia_poll_irq(struct cf_slot * slot)
+{
+    PcmciaRegisterT *           pcmciaRegPtr = (PcmciaRegisterT *)PPC_PCMCIA_BASE;
+
+    /* Test for falling edge on IRQ. */
+    if (pcmciaRegPtr->pscr.slot[slot->index] & PCMCIA_IRQ_F) {
+        pcmciaRegPtr->pscr.slot[slot->index] = PCMCIA_IRQ_F;
+        return 1;
+    }
+    return 0;
+} /* pcmcia_poll_irq */
diff -r -U 5 -N -x CVS -x '*~' -x '.#~' ecos.20080311/packages/devs/pcmcia/powerpc/mpc8xx/current/src/pcmcia_mpc8xx.h ecos.20080311.pcmcia-mpc8xx/packages/devs/pcmcia/powerpc/mpc8xx/current/src/pcmcia_mpc8xx.h
--- ecos.20080311/packages/devs/pcmcia/powerpc/mpc8xx/current/src/pcmcia_mpc8xx.h	1969-12-31 18:00:00.000000000 -0600
+++ ecos.20080311.pcmcia-mpc8xx/packages/devs/pcmcia/powerpc/mpc8xx/current/src/pcmcia_mpc8xx.h	2008-04-29 11:17:28.000000000 -0600
@@ -0,0 +1,312 @@
+//==========================================================================
+//
+//      PowerPC MPC8XX PCMCIA support
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):       slouie
+// Contributors:    slouie
+// Date:            2008-04-29
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+/*===========================================================
+ * Dependencies
+ *=========================================================*/
+#include <pkgconf/hal.h> /* For IMMR base */
+#include <pkgconf/devs_pcmcia_mpc8xx.h>
+
+/*===========================================================
+ * Custom Hardware Setup (defined in target include file - i.e. plf_regs.h)
+ *=========================================================*/
+/*
+ * #define PCMCIA_MPC8XX_MEMORY_START       0xE0000000
+ * #define PCMCIA_MPC8XX_WINSZ_COMMON       (64 * 1024 * 1024)
+ * #define PCMCIA_MPC8XX_WINSZ_ATTR         (64 * 1024 * 1024)
+ * #define PCMCIA_MPC8XX_WINSZ_IO           (64 * 1024 * 1024)
+ */
+/*
+ * Function to initialize hardware
+ */
+void pcmcia_custom_init(struct cf_slot *);
+/*
+ * Function to power on PCMCIA device. vselect will be the desired
+ * voltage (e.g. 3 or 5).
+ */
+void pcmcia_custom_on(struct cf_slot *, unsigned int vselect);
+/*
+ * Function to power off PCMCIA device.
+ */
+void pcmcia_custom_off(struct cf_slot *);
+
+/*===========================================================
+ * Definitions
+ *=========================================================*/
+/* Binary to gray-code */
+#define binary2gray(b)                      ((b) ^ ((b) >> 1))
+
+/* Card Configuration and Status Register (CCSR) */
+#define PCMCIA_CCSR_IO_IS_8                 0x20  /*host can only make 8bit IO cycles. */
+#define PCMCIA_CCSR_AUDIO                   0x08  /*Pin BVD2 is used for audio data. */
+#define PCMCIA_CCSR_PWRDWN                  0x04  /*Request card to Power down. */
+
+/*===========================================================
+ * PORx register bits.
+ *=========================================================*/
+#define PCMCIA_POR_BSIZE(S)                 ((S) << 27) /* Bank size = (2 pwr S). */
+#define PCMCIA_POR_PSHT(HT)                 ((HT) << 16)  /* Strobe Hold time. */
+#define PCMCIA_POR_PSST(ST)                 ((ST) << 12)  /* Setup time. */
+#define PCMCIA_POR_PSL(L)                   ((L) << 7)    /* Strobe length. */
+#define PCMCIA_POR_PS8                      0x00000000    /* 8 bit port size. */
+#define PCMCIA_POR_PS16                     0x00000040    /* 16 bit port size. */
+#define PCMCIA_POR_COMM_MEM                 (0 << 3)
+#define PCMCIA_POR_ATTR_MEM                 (2 << 3)
+#define PCMCIA_POR_IO_SPACE                 (3 << 3)
+#define PCMCIA_POR_DMA_REGION               (4 << 3)
+#define PCMCIA_POR_SLOT_A                   0x00000000    /* This region accesses slot A. */
+#define PCMCIA_POR_SLOT_B                   0x00000004    /* This region accesses slot B. */
+#define PCMCIA_POR_WP                       0x00000002    /* Write protect. */
+#define PCMCIA_POR_PV                       0x00000001    /* Valid region. */
+
+/* Default PCMCIA timing (in bus-clocks). */
+#define PCMCIA_DFLT_SETUP_TIME              2
+#define PCMCIA_DFLT_LEN_TIME                5
+#define PCMCIA_DFLT_HOLD_TIME               2
+
+/*
+ * We need this table because the PPC has a weird way of setting a PCMCIA
+ * memory window size :-/.
+ */
+typedef struct {
+    unsigned int        windowsz;
+    unsigned int        bsize;
+} PcmciaPorBsizeTblT;
+
+static PcmciaPorBsizeTblT _pcmciaPorBsizeTbl[] = {
+    {               1, binary2gray(0)},
+    {               2, binary2gray(1)},
+    {               4, binary2gray(2)},
+    {               8, binary2gray(3)},
+    {              16, binary2gray(4)},
+    {              32, binary2gray(5)},
+    {              64, binary2gray(6)},
+    {             128, binary2gray(7)},
+    {             256, binary2gray(8)},
+    {             512, binary2gray(9)},
+    {        1 * 1024, binary2gray(10)},
+    {        2 * 1024, binary2gray(11)},
+    {        4 * 1024, binary2gray(12)},
+    {        8 * 1024, binary2gray(13)},
+    {       16 * 1024, binary2gray(14)},
+    {       32 * 1024, binary2gray(15)},
+    {       64 * 1024, binary2gray(16)},
+    {      128 * 1024, binary2gray(17)},
+    {      256 * 1024, binary2gray(18)},
+    {      512 * 1024, binary2gray(19)},
+    { 1 * 1024 * 1024, binary2gray(20)},
+    { 2 * 1024 * 1024, binary2gray(21)},
+    { 4 * 1024 * 1024, binary2gray(22)},
+    { 8 * 1024 * 1024, binary2gray(23)},
+    {16 * 1024 * 1024, binary2gray(24)},
+    {32 * 1024 * 1024, binary2gray(25)},
+    {64 * 1024 * 1024, binary2gray(26)},
+};
+#define PCMCIA_POR_BSIZE_TBL_LEN    (sizeof(_pcmciaPorBsizeTbl) / sizeof(PcmciaPorBsizeTblT))
+
+/*===========================================================
+ * PIPR, PSCR and PER register bits. (half)
+ *=========================================================*/
+#define PCMCIA_VS1                          0x8000
+#define PCMCIA_VS2                          0x4000
+#define PCMCIA_WP                           0x2000
+#define PCMCIA_CD2                          0x1000
+#define PCMCIA_CD1                          0x0800
+#define PCMCIA_BVD2                         0x0400
+#define PCMCIA_BVD1                         0x0200
+#define PCMCIA_RDY                          0x0100
+#define PCMCIA_IRQ                          0x0100
+/* PSCR and PER specific. */
+#define PCMCIA_IRQ_L                        0x0080  /* Low level on IRQ */
+#define PCMCIA_IRQ_H                        0x0040  /* High level on IRQ */
+#define PCMCIA_IRQ_R                        0x0020  /* Rising edge on IRQ */
+#define PCMCIA_IRQ_F                        0x0010  /* Falling edge on IRQ */
+
+/*===========================================================
+ * PGCR-A and PGCR-B register bits
+ *=========================================================*/
+#define PCMCIA_PGCR_DREQ                    0x00008000
+#define PCMCIA_PGCR_OE                      0x00000080
+#define PCMCIA_PGCR_RESET                   0x00000040
+
+/*===========================================================
+ * Delay constants
+ *=========================================================*/
+#define PCMCIA_POWER_OFF_DELAY              1000000 /* 1s delay after power-off (discharge)*/
+#define PCMCIA_POWER_ON_DELAY               500000  /* 500ms delay after power-on.     */
+#define PCMCIA_HARD_RESET_PULSE             100000  /* 100ms PCMCIA Hard Reset pulse. */
+#define PCMCIA_HARD_RESET_DELAY             500000  /* 500ms delay after Hard Reset.  */
+#define PCMCIA_SOFT_RESET_PULSE             100000  /* 100ms PCMCIA Soft Reset pulse. */
+#define PCMCIA_SOFT_RESET_DELAY             500000  /* 500ms delay after Soft Reset.  */
+
+/*===========================================================
+ * Interrupts
+ *=========================================================*/
+/* Define the interrupt signal to use. */
+#define PCMCIA_SIU_INTR                     CYGNUM_HAL_INTERRUPT_SIU_LVL2
+#define PCMCIA_INTERRUPT                    2
+/* To be set in PGCRx as well.  PGCRA = IMMR + 0x0e0 */
+#define PCMCIA_PGCR_INTR_LVL(L)             (0x80000000 >> (L))
+
+/*===========================================================
+ * Card Information Structure Tuple Code
+ *=========================================================*/
+/* Maximium tuple size */
+#define MAX_TUPLE_SZ                        256
+
+/* configuration tuple size of fields byte masks */
+#define TPCC_RASZ_MASK                      0x03
+#define TPCC_RMSZ_MASK                      0x3C
+#define TPCC_RFSZ_MASK                      0xC0
+
+#define TPCE_IF_MASK                        0x80
+#define TPCE_FS_IO_MASK                     0x08
+#define TPCE_FS_PD_MASK                     0x03
+#define TPCE_FS_PD_EXT                      0x80
+#define TPCE_FS_TI_MASK                     0x04
+
+#define TPCE_TD_WAITSCALE_MASK              0x03
+#define TPCE_TD_WAITSCALE_UNUSED            0x03
+#define TPCE_TD_REBU_MASK                   0x1C
+#define TPCE_TD_REBU_UNUSED                 0x1C
+#define TPCE_TD_RESERVED_MASK               0xE0
+#define TPCE_TD_RESERVED_UNUSED             0xE0
+
+#define TPCE_IO_RANGE                       0x80
+#define TPCE_IO_BUS16                       0x40
+#define TPCE_IO_BUS8                        0x20
+#define IO_ADDR_LINES_MASK                  0x1F
+
+#define TPCE_VC_NOM                         0x01
+
+/*===========================================================
+ * PPC PCMCIA internal registers and bits.
+ *=========================================================*/
+#define PPC_PCMCIA_BASE                     (CYGARC_REG_IMM_BASE + 0x00000080)
+
+volatile typedef struct {
+    unsigned int        pbr;    /* PCMCIA interface base register */
+    unsigned int        por;    /* PCMCIA interface option register */
+} __attribute__ ((packed)) PBR_POR;
+
+volatile typedef struct {
+    unsigned int        pbr0;   /* PCMCIA interface base register0   */
+    unsigned int        por0;   /* PCMCIA interface option register0 */
+    unsigned int        pbr1;   /*               .                   */
+    unsigned int        por1;   /*               .                   */
+    unsigned int        pbr2;   /*               .                   */
+    unsigned int        por2;   /*               .                   */
+    unsigned int        pbr3;   /*               .                   */
+    unsigned int        por3;   /*               .                   */
+    unsigned int        pbr4;   /*               .                   */
+    unsigned int        por4;   /*               .                   */
+    unsigned int        pbr5;   /*               .                   */
+    unsigned int        por5;   /*               .                   */
+    unsigned int        pbr6;   /*               .                   */
+    unsigned int        por6;   /*               .                   */
+    unsigned int        pbr7;   /* PCMCIA interface base register7   */
+    unsigned int        por7;   /* PCMCIA interface option register7 */
+} __attribute__ ((packed)) ALL_PBR_POR;
+
+volatile typedef struct {
+    PBR_POR             comm;   /* PCMCIA PBR & POR registers for common memory. */
+    PBR_POR             attr;   /* PCMCIA PBR & POR registers for attrib memory. */
+    PBR_POR             io;     /* PCMCIA PBR & POR registers for I/O space. */
+    PBR_POR             spare;  /* Spare PCMCIA PBR & POR registers. */
+} __attribute__ ((packed)) SLOT_PBR_POR;
+
+volatile typedef struct {
+    union {
+      /* All PCMCIA PBR and POR registers by index */
+      PBR_POR           array[8];
+      /* PCMCIA PBR and POR registers per slot. */
+      SLOT_PBR_POR      slot[2];
+    } pir;
+    unsigned char       reserved1[32];
+    union {
+      struct {
+        unsigned int    A;  /* PCMCIA-A interface general control. */
+        unsigned int    B;  /* PCMCIA-B interface general control. */
+      } reg;
+      unsigned int      slot[2]; /* Selects register by slot index. */
+    } pgcr;
+    union {
+      unsigned int      reg;
+      unsigned short    slot[2]; /* Selects regsiter word by slot index. */
+    } pscr;
+    unsigned char       reserved2[4];
+    union {
+      unsigned int      reg;     /* PCMCIA interface input pins register. */
+      unsigned short    slot[2]; /* Selects register word by slot index. */
+    } pipr;
+    unsigned char       reserved3[4];
+    union {
+      unsigned int      reg;     /* PCMCIA interrupt enable register. */
+      unsigned short    slot[2]; /* Selects regstr word by slot index. */
+    } per;
+} __attribute__ ((packed)) PcmciaRegisterT;
+
+/*===========================================================
+ * Function Declarations
+ *=========================================================*/
+unsigned int    _pcmcia_get_vs(struct cf_slot * slot);
+bool            _pcmcia_get_por_bsize(unsigned int windowsz, unsigned int * bsizep);
+bool            _pcmcia_memmap_init(struct cf_slot *);
+bool            _pcmcia_conf_baseaddr(struct cf_slot *, unsigned int *);
+bool            _pcmcia_get_startioaddr(struct cf_slot *, unsigned int *);
+unsigned char   _pcmcia_card_detect(struct cf_slot *);
+bool            _pcmcia_get_cis_tuple(struct cf_slot *, unsigned char, unsigned char *);
+
+void            cf_hwr_init(struct cf_slot *);
+bool            cf_hwr_change_state(struct cf_slot *, int);
+void            cf_hwr_poll(struct cf_slot *);
+void            cf_hwr_clear_interrupt(struct cf_slot *);
+bool            cf_hwr_card_inserted(struct cf_slot *);
+
+bool            cf_hwr_reset_hard(struct cf_slot *);
+bool            cf_hwr_reset_soft(struct cf_slot *);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]