URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [disk/] [v85x/] [edb_v850/] [current/] [src/] [v85x_edb_v850_disk.c] - Rev 839
Go to most recent revision | Compare with Previous | Blame | View Log
//========================================================================== // // v85x_edb_v850_disk.c // // Elatec v850 development board disk driver // //========================================================================== // ####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 2003, 2006 Free Software Foundation, 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., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 v2. // // This exception does not invalidate any other reasons why a work based // on this file might be covered by the GNU General Public License. // ------------------------------------------- // ####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): savin // Contributors: // Date: 2003-08-21 // //####DESCRIPTIONEND#### // //========================================================================== #include <pkgconf/devs_disk_v85x_edb_v850.h> #include <cyg/infra/cyg_type.h> #include <cyg/infra/cyg_ass.h> #include <cyg/infra/diag.h> #include <cyg/hal/hal_arch.h> #include <cyg/hal/hal_io.h> #include <cyg/hal/drv_api.h> #include <cyg/io/io.h> #include <cyg/io/devtab.h> #include <cyg/io/disk.h> #include <cf_ata.h> // ---------------------------------------------------------------------------- //#define DEBUG 1 #ifdef DEBUG # define D(_args_) diag_printf _args_ #else # define D(_args_) #endif // ---------------------------------------------------------------------------- #include <cyg/hal/v850_common.h> static volatile unsigned char* P10 = (volatile unsigned char*)V850_REG_P10; static volatile unsigned char* PM10 = (volatile unsigned char*)V850_REG_PM10; static volatile unsigned char* PU10 = (volatile unsigned char*)V850_REG_PU10; #define CF_BASE 0x00380000 #define CF_HW_INIT() \ do { \ *PU10 |= (1<<4); \ *PM10 |= (1<<4); \ *PM10 &= ~2; \ } while (0) #define CF_HW_RESET() \ do { \ int i; \ *P10 |= 2; \ for (i = 0; i < 500000; i++); \ *P10 &= ~2; \ for (i = 0; i < 500000; i++); \ } while (0) #define CF_HW_BUSY_WAIT() \ do { \ while (0 == (*P10 & (1<<4))); \ } while (0) // ---------------------------------------------------------------------------- typedef struct { volatile cyg_uint16 *base; } cf_disk_info_t; // ---------------------------------------------------------------------------- static cyg_bool cf_disk_init(struct cyg_devtab_entry *tab); static Cyg_ErrNo cf_disk_read(disk_channel *chan, void *buf, cyg_uint32 len, cyg_uint32 block_num); static Cyg_ErrNo cf_disk_write(disk_channel *chan, const void *buf, cyg_uint32 len, cyg_uint32 block_num); static Cyg_ErrNo cf_disk_get_config(disk_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len); static Cyg_ErrNo cf_disk_set_config(disk_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len); static Cyg_ErrNo cf_disk_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name); DISK_FUNS(cf_disk_funs, cf_disk_read, cf_disk_write, cf_disk_get_config, cf_disk_set_config ); // ---------------------------------------------------------------------------- // No h/w controller structure is needed, but the address of the // second argument is taken anyway. DISK_CONTROLLER(cf_disk_controller, cf_disk_controller); #define CF_DISK_INSTANCE(_number_,_base_,_mbr_supp_,_name_) \ static cf_disk_info_t cf_disk_info##_number_ = { \ base: (volatile cyg_uint16 *)_base_, \ }; \ DISK_CHANNEL(cf_disk_channel##_number_, \ cf_disk_funs, \ cf_disk_info##_number_, \ cf_disk_controller, \ _mbr_supp_, \ 4 \ ); \ BLOCK_DEVTAB_ENTRY(cf_disk_io##_number_, \ _name_, \ 0, \ &cyg_io_disk_devio, \ cf_disk_init, \ cf_disk_lookup, \ &cf_disk_channel##_number_ \ ); // ---------------------------------------------------------------------------- #ifdef CYGVAR_DEVS_DISK_V85X_EDB_V850_DISK0 CF_DISK_INSTANCE(0, CF_BASE, true, CYGDAT_IO_DISK_V85X_EDB_V850_DISK0_NAME); #endif // ---------------------------------------------------------------------------- static __inline__ cyg_uint8 get_status(volatile cyg_uint16 *base) { cyg_uint16 val; HAL_READ_UINT16(base + 7, val); return (val & 0x00FF); } static __inline__ cyg_uint8 get_error(volatile cyg_uint16 *base) { cyg_uint16 val; HAL_READ_UINT16(base + 6, val); return ((val >> 8) & 0x00FF); } static __inline__ void set_dctrl(volatile cyg_uint16 *base, cyg_uint8 dbits) { cyg_uint16 val = dbits; HAL_WRITE_UINT16(base + 7, val); } static cyg_bool exe_cmd(volatile cyg_uint16 *base, cyg_uint8 cmd, cyg_uint8 drive, cyg_uint32 lba_addr, cyg_uint8 sec_cnt) { cyg_uint8 lba0_7; cyg_uint16 lba8_23; cyg_uint8 lba24_27; cyg_uint8 drv; lba0_7 = lba_addr & 0xFF; lba8_23 = (lba_addr >> 8) & 0xFFFF; lba24_27 = (lba_addr >> 24) & 0x0F; // drive and LBA addressing mode flag if (0 == drive) drv = 0x40; else drv = 0x50; CF_HW_BUSY_WAIT(); HAL_WRITE_UINT16(base + 1, sec_cnt | (lba0_7 << 8)); HAL_WRITE_UINT16(base + 2, lba8_23); HAL_WRITE_UINT16(base + 3, lba24_27 | drv | (cmd << 8)); CF_HW_BUSY_WAIT(); return (0 == (get_status(base) & CF_SREG_ERR)); } static void read_data(volatile cyg_uint16 *base, void *buf, cyg_uint16 len) { cyg_uint16 *bufp = (cyg_uint16 *)buf; int i; CF_HW_BUSY_WAIT(); for (i = 0; i < 512; i += 2) { cyg_uint16 data; HAL_READ_UINT16(base + 4, data); if (i < len) *bufp++ = data; } CF_HW_BUSY_WAIT(); } static void write_data(volatile cyg_uint16 *base, const void *buf, cyg_uint16 len) { cyg_uint16 *bufp = (cyg_uint16 * const)buf; int i; CF_HW_BUSY_WAIT(); for (i = 0; i < 512; i += 2) { cyg_uint16 data; if (i < len) data = *bufp++; else data = 0x0000; HAL_WRITE_UINT16(base + 4, data); } CF_HW_BUSY_WAIT(); } static void id_strcpy(char *dest, cyg_uint16 *src, cyg_uint16 size) { int i; for (i = 0; i < size; i+=2) { *dest++ = (char)(*src >> 8); *dest++ = (char)(*src & 0x00FF); src++; } *dest = '\0'; } // ---------------------------------------------------------------------------- static cyg_bool cf_disk_init(struct cyg_devtab_entry *tab) { disk_channel *chan = (disk_channel *) tab->priv; cf_disk_info_t *info = (cf_disk_info_t *) chan->dev_priv; cf_ata_identify_data_t *ata_id; cyg_uint8 id_buf[sizeof(cf_ata_identify_data_t)]; cyg_disk_identify_t ident; if (chan->init) return true; D(("CF(%p) hw init\n", info->base)); CF_HW_INIT(); CF_HW_RESET(); D(("CF(%p) identify drive\n", info->base)); if (!exe_cmd(info->base, CF_ATA_IDENTIFY_DRIVE_CMD, 0, 0, 0)) { D(("CF(%p) error (%x)\n", info->base, get_error(info->base))); return false; } read_data(info->base, id_buf, sizeof(cf_ata_identify_data_t)); ata_id = (cf_ata_identify_data_t *)id_buf; D(("CF(%p) general conf = %x\n", info->base, ata_id->general_conf)); if (0x848A != ata_id->general_conf) return false; id_strcpy(ident.serial, ata_id->serial, 20); id_strcpy(ident.firmware_rev, ata_id->firmware_rev, 8); id_strcpy(ident.model_num, ata_id->model_num, 40); ident.cylinders_num = ata_id->num_cylinders; ident.heads_num = ata_id->num_heads; ident.sectors_num = ata_id->num_sectors; ident.lba_sectors_num = ata_id->lba_total_sectors[1] << 16 | ata_id->lba_total_sectors[0]; ident.phys_block_size = 1; ident.max_transfer = 512; if (!(chan->callbacks->disk_init)(tab)) return false; if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident)) return false; return true; } static Cyg_ErrNo cf_disk_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name) { disk_channel *chan = (disk_channel *) (*tab)->priv; return (chan->callbacks->disk_lookup)(tab, sub_tab, name); } static Cyg_ErrNo cf_disk_read(disk_channel *chan, void *buf, cyg_uint32 len, cyg_uint32 block_num) { cf_disk_info_t *info = (cf_disk_info_t *)chan->dev_priv; D(("CF(%p) read block %d\n", info->base, block_num)); if (!exe_cmd(info->base, CF_ATA_READ_SECTORS_CMD, 0, block_num, 1)) { D(("CF(%p) error (%x)\n", info->base, get_error(info->base))); return -EIO; } read_data(info->base, buf, len); return ENOERR; } static Cyg_ErrNo cf_disk_write(disk_channel *chan, const void *buf, cyg_uint32 len, cyg_uint32 block_num) { cf_disk_info_t *info = (cf_disk_info_t *)chan->dev_priv; D(("CF(%p) write block %d\n", info->base, block_num)); if (!exe_cmd(info->base, CF_ATA_WRITE_SECTORS_CMD, 0, block_num, 1)) { D(("CF(%p) error (%x)\n", info->base, get_error(info->base))); return -EIO; } write_data(info->base, buf, len); return ENOERR; } static Cyg_ErrNo cf_disk_get_config(disk_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) { return -EINVAL; } static Cyg_ErrNo cf_disk_set_config(disk_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) { return -EINVAL; } // ---------------------------------------------------------------------------- // EOF v85x_edb_v850_disk.c
Go to most recent revision | Compare with Previous | Blame | View Log