From: Stefan E. <se...@us...> - 2002-05-03 10:04:29
|
Update of /cvsroot/blob/blob/src/lib In directory usw-pr-cvs1:/tmp/cvs-serv10534 Added Files: cf.c Log Message: - this code supplies CF access through generic io. - first stage of evolution, WIP, YMMV .... - missing: - proper wrapping with config options (autoconf/automake). - this code uses PCMCIA, IDE and gereric_io libs - test --- NEW FILE: cf.c --- /********************************************************************** * cf.c: compact flash IDE access * * Copyright (C) 2002, Stefan Eletzhofer <ste...@el...> * * This program 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 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: cf.c,v 1.1 2002/05/03 10:04:23 seletz Exp $ * */ /********************************************************************** * Includes */ #ifdef HAVE_CONFIG_H # include <blob/config.h> #endif #include <blob/types.h> #include <blob/errno.h> #include <blob/util.h> #include <blob/time.h> #include <blob/command.h> #include <blob/init.h> #include <blob/generic_io.h> #include <blob/pcmcia.h> #include <blob/ide.h> #include <blob/cf.h> /********************************************************************** * defines */ #define CF_DEBUG 0 #if CF_DEBUG # define DBG( x, args... ) if ( cf_dbg>x ) printf( args ); #else # define DBG( x, args... ) #endif #define IDE_BLOCK_SIZE 512 /********************************************************************** * module globals */ #if CF_DEBUG static int cf_dbg = 1; #else static int cf_dbg = 0; #endif static char module_version[] = "$Id: cf.c,v 1.1 2002/05/03 10:04:23 seletz Exp $"; /* static atm. Do we need more than one CF card? */ static int cf_slot = 1; static u32 cf_slot_base = 0L; static u32 cf_slot_attr = 0L; static ide_drive_t drive; /********************************************************************** * static functions */ static int cf_io_conf( io_driver_t *io, void *conf ); static int cf_io_read( unsigned char *dest, unsigned char *src, size_t amount, io_driver_t *io ); static int cf_io_write( unsigned char *dest, unsigned char *src, size_t amount, io_driver_t *io ); /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ /* set debug level */ void cf_dbg_set( int lvl ) { cf_dbg = lvl; } /***************************************************************** * cf_init - initialize CF card plugged in slot <slot> */ int cf_init( int slot ) { int ret = 0; u16 cfg_reg; u8 cfgvalue; u8 value; ret = pcmcia_init(); if ( ret != 0 ) return -EINVAL; if ( cf_dbg > 10 ) { pcmcia_dbg_set( 5 ); ide_dbg_set( 5 ); } ret = pcmcia_slot_detect( slot ); if ( !ret ) return -EINVAL; printf( "cf: slot %d detected\n", slot ); ret = pcmcia_slot_enable( slot ); if ( ret ) return -EINVAL; ret = pcmcia_slot_address_get( slot, &cf_slot_base, &cf_slot_attr ); if ( ret ) return -EINVAL; ret = pcmcia_slot_reset( slot ); if ( ret ) return -EINVAL; ret = pcmcia_cis_parse( slot ); if ( ret ) return -EINVAL; ret = pcmcia_slot_cfg_reg_get( slot, &cfg_reg ); if ( ret ) return -EINVAL; DBG( 2, "cf: slot %d config register: 0x%03x\n", slot, cfg_reg ); pcmcia_slot_attr_read( slot, CF_REG_CFG, &cfgvalue ); DBG( 2, "slot %d config register: 0x%02x = 0x%02x\n", slot, CF_REG_CFG, cfgvalue ); pcmcia_slot_attr_read( slot, CF_REG_CFGSTAT, &value ); DBG( 2, "slot %d config status register: 0x%02x = 0x%02x\n", slot, CF_REG_CFGSTAT, value ); /* reset CF card */ pcmcia_slot_attr_write( slot, CF_REG_CFG, cfgvalue | CF_CFG_SRST ); msleep(1); pcmcia_slot_attr_write( slot, CF_REG_CFG, cfgvalue & (~CF_CFG_SRST) ); pcmcia_slot_attr_read( slot, CF_REG_CFG, &cfgvalue ); DBG( 2, "slot %d config register: 0x%02x = 0x%02x\n", slot, CF_REG_CFG, cfgvalue ); /* configure for true ide mode */ pcmcia_slot_attr_write( slot, CF_REG_CFG, cfgvalue | CF_CFG_IO_IDE0 ); pcmcia_slot_attr_read( slot, CF_REG_CFG, &cfgvalue ); DBG( 2, "slot %d config register: 0x%02x = 0x%02x\n", slot, CF_REG_CFG, cfgvalue ); pcmcia_slot_attr_read( slot, CF_REG_CFGSTAT, &value ); DBG( 2, "slot %d config status register: 0x%02x = 0x%02x\n", slot, CF_REG_CFGSTAT, value ); DBG( 2, "slot %d enabled\n", slot ); ret = ide_init( &drive, (u32)cf_slot_base ); if ( ret ) return -EINVAL; ret = ide_reset( &drive ); ret = ide_identify_drive( &drive ); if ( ret ) return -EINVAL; ret = ide_status_dump( &drive ); if ( ret ) return -EINVAL; ret = 0; DONE: if ( ret != 0 ) { printf( "cf: error (%d).\n", ret ); } return ret; } /********************************************************************** * CF io driver * - maps "adresses" to blocks of IDE_BLOCK_SIZE bytes. Reads * whole blocks, but copies only requested data. */ void cf_default_io_init( void ) { int ret; static io_driver_t cf_def_io; cf_dbg_set( 0 ); /* init default cf drv */ ret = cf_io_init( &cf_def_io, cf_slot ); if ( ret ) return; ret = io_register( &cf_def_io, "CF" ); if ( ret ) return; } __initlist(cf_default_io_init, INIT_LEVEL_OTHER_STUFF + 2); int cf_io_init( io_driver_t *io, int slot ) { DBG( 5, "%s: io=%p, slot=%p\n", __FUNCTION__, io, slot ); io->conf = cf_io_conf; io->read = cf_io_read; io->write = cf_io_write; io->private_data = (void *)NULL; /* filled by configure */ io->io_size = 0; /* filled for us by io_chain() */ io->child_io = NULL; return 0; } int cf_io_conf( io_driver_t *io, void *conf ) { if ( !io || !conf ) return -EINVAL; cf_slot = (int)conf; io->private_data = (void *)cf_slot; return cf_init( cf_slot ); } static int cf_io_read( unsigned char *dest, unsigned char *src, size_t amount, io_driver_t *io ) { int ret = 0; static unsigned char buffer[IDE_BLOCK_SIZE]; u32 start_block; u16 start_off; int block, to_copy; if ( !dest || !src ) return -EINVAL; /* starting block number */ start_block = (u32)src/IDE_BLOCK_SIZE; /* start offset (in-block-offset)*/ start_off = (u32)src - start_block*IDE_BLOCK_SIZE; DBG( 1, "%s: start_block=%d, start_off=%d, src=%p, dest=%p, amount=%d\n", __FUNCTION__, start_block, start_off, src, dest, amount ); block = start_block; while ( amount ) { /* read block into buffer */ ret = hd_read_mapped( &drive, block, buffer ); if ( ret != 0 ) return -EINVAL; if ( start_off ) { to_copy = IDE_BLOCK_SIZE - start_off; } else { to_copy = IDE_BLOCK_SIZE; } DBG( 15, "%s: block=%d, to_copy=%d, amount=%d\n", __FUNCTION__, block, to_copy, amount ); /* copy data */ memcpy( dest, buffer + start_off, to_copy ); if ( start_off ) { start_off=0; } dest += to_copy; amount -= to_copy; block += 1; } return 0; } static int cf_io_write( unsigned char *dest, unsigned char *src, size_t amount, io_driver_t *io ) { return -EINVAL; } |