This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
Re: io-pcmcia patch
- From: Shaun Louie <sal at microplex dot com>
- To: eCos Patches <ecos-patches at sources dot redhat dot com>
- Date: Tue, 29 Apr 2008 15:21:52 -0600
- Subject: Re: io-pcmcia patch
- References: <47DF0763.4010109@microplex.com> <47E156FC.40302@mlbassoc.com>
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 *);