ipaq_pcmcia.c
来自「eCos操作系统源码」· C语言 代码 · 共 272 行
C
272 行
//==========================================================================//// devs/pcmcia/ipaq/ipaq_pcmcia.c//// PCMCIA support (Card Services)////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002 Gary Thomas//// 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): gthomas// Contributors: gthomas// richard.panton@3glab.com// Date: 2001-02-24// Purpose: PCMCIA support// Description: ////####DESCRIPTIONEND####////==========================================================================#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/hal_sa11x0.h> // Board definitions#include <cyg/hal/ipaq.h>#ifdef CYGPKG_KERNELstatic cyg_interrupt cf_detect_interrupt;static cyg_handle_t cf_detect_interrupt_handle;static cyg_interrupt cf_irq_interrupt;static cyg_handle_t cf_irq_interrupt_handle;// This ISR is called when a CompactFlash board is insertedstatic intcf_detect_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs){ cyg_drv_interrupt_mask(SA1110_CF_DETECT); return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR}// This DSR handles the board insertionstatic voidcf_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_drv_interrupt_acknowledge(SA1110_CF_DETECT); cyg_drv_interrupt_unmask(SA1110_CF_DETECT);}// This ISR is called when the card interrupt occursstatic intcf_irq_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs){ cyg_drv_interrupt_mask(SA1110_CF_IRQ); return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR}// This DSR handles the card interruptstatic voidcf_irq_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ struct cf_slot *slot = (struct cf_slot *)data;#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) cyg_bool was_ctrlc_int;#endif // Clear interrupt [edge indication] cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) was_ctrlc_int = HAL_CTRLC_CHECK(vector, data); if (!was_ctrlc_int) // Fall through and run normal code#endif // Process interrupt (slot->irq_handler.handler)(vector, count, slot->irq_handler.param); // Allow interrupts to happen again cyg_drv_interrupt_unmask(SA1110_CF_IRQ);}#endifstatic voiddo_delay(int ticks){#ifdef CYGPKG_KERNEL cyg_thread_delay(ticks);#else CYGACC_CALL_IF_DELAY_US(10000*ticks);#endif}//// Fill in the details of a PCMCIA slot and initialize the device//voidcf_hwr_init(struct cf_slot *slot){ static int int_init = 0; unsigned long new_state = *SA11X0_GPIO_PIN_LEVEL; if (!int_init) { int_init = 1;#ifdef CYGPKG_KERNEL // Set up interrupts cyg_drv_interrupt_create(SA1110_CF_DETECT, 99, // Priority - what goes here? (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); cyg_drv_interrupt_create(SA1110_CF_IRQ, 99, // Priority - what goes here? (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_attach(cf_irq_interrupt_handle); cyg_drv_interrupt_unmask(SA1110_CF_IRQ); cyg_drv_interrupt_configure(SA1110_CF_IRQ, false, false); // Falling edge cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);#endif } slot->attr = (unsigned char *)0x28000000; slot->attr_length = 0x200; slot->io = (unsigned char *)0x20000000; slot->io_length = 0x04000000; slot->mem = (unsigned char *)0x2C000000; slot->mem_length = 0x04000000; slot->int_num = SA1110_CF_IRQ;#ifdef CYG_HAL_STARTUP_ROM // Disable CF bus & power (idle/off) ipaq_EGPIO( SA1110_EIO_OPT_PWR | SA1110_EIO_OPT | SA1110_EIO_CF_RESET, SA1110_EIO_OPT_PWR_ON | SA1110_EIO_OPT_ON | SA1110_EIO_CF_RESET_ENABLE );#endif if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) { if ((_ipaq_EGPIO & SA1110_EIO_OPT_PWR) == SA1110_EIO_OPT_PWR_ON) { // Assume that the ROM environment has turned the bus on slot->state = CF_SLOT_STATE_Ready; } else { slot->state = CF_SLOT_STATE_Inserted; } } else { slot->state = CF_SLOT_STATE_Empty; }}voidcf_hwr_poll(struct cf_slot *slot){ unsigned long new_state = *SA11X0_GPIO_PIN_LEVEL; if ((new_state & SA1110_GPIO_CF_DETECT) == SA1110_GPIO_CF_PRESENT) { slot->state = CF_SLOT_STATE_Inserted; } else { slot->state = CF_SLOT_STATE_Empty; }}//// Transition the card/slot to a new state// note: currently only supports transitions to Ready, Empty//voidcf_hwr_change_state(struct cf_slot *slot, int new_state){ int i, ptr, len; unsigned char buf[256]; if (new_state == CF_SLOT_STATE_Ready) { if (slot->state == CF_SLOT_STATE_Inserted) { ipaq_EGPIO( SA1110_EIO_OPT_PWR | SA1110_EIO_OPT | SA1110_EIO_CF_RESET, SA1110_EIO_OPT_PWR_ON | SA1110_EIO_OPT_ON | SA1110_EIO_CF_RESET_DISABLE); do_delay(30); // At least 300 ms slot->state = CF_SLOT_STATE_Powered; ipaq_EGPIO( SA1110_EIO_CF_RESET, SA1110_EIO_CF_RESET_ENABLE); *(volatile unsigned short *)IPAQ_CF_CTRL = IPAQ_CF_CTRL_V5_DISABLE | IPAQ_CF_CTRL_V3_ENABLE | IPAQ_CF_CTRL_RESET_ENABLE | IPAQ_CF_CTRL_APOE_ENABLE | IPAQ_CF_CTRL_SOE_ENABLE; do_delay(1); // At least 10 us slot->state = CF_SLOT_STATE_Reset; ipaq_EGPIO( SA1110_EIO_CF_RESET, SA1110_EIO_CF_RESET_DISABLE); do_delay(5); // At least 20 ms // This is necessary for the two slot sleeve and doesn't seem to // hurt on the single slot versions. Note: only 3.3V is ever used! *(volatile unsigned short *)IPAQ_CF_CTRL = IPAQ_CF_CTRL_V5_DISABLE | IPAQ_CF_CTRL_V3_ENABLE | IPAQ_CF_CTRL_RESET_DISABLE | IPAQ_CF_CTRL_APOE_ENABLE | IPAQ_CF_CTRL_SOE_ENABLE; do_delay(5); // At least 20 ms // Wait until the card is ready to talk for (i = 0; i < 10; i++) { ptr = 0; if (cf_get_CIS(slot, CF_CISTPL_VERS_1, buf, &len, &ptr)) { slot->state = CF_SLOT_STATE_Ready; break; } do_delay(10); } } }}//// Acknowledge interrupt (used in non-kernel environments)//voidcf_hwr_clear_interrupt(struct cf_slot *slot){ // Clear interrupt [edge indication] cyg_drv_interrupt_acknowledge(SA1110_CF_IRQ);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?