1 //==========================================================================
3 // v85x_edb_v850_disk.c
5 // Elatec v850 development board disk driver
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 2003 Savin Zlobec.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // -------------------------------------------
37 //####ECOSGPLCOPYRIGHTEND####
38 //==========================================================================
39 //#####DESCRIPTIONBEGIN####
45 //####DESCRIPTIONEND####
47 //==========================================================================
49 #include <pkgconf/devs_disk_v85x_edb_v850.h>
51 #include <cyg/infra/cyg_type.h>
52 #include <cyg/infra/cyg_ass.h>
53 #include <cyg/infra/diag.h>
54 #include <cyg/hal/hal_arch.h>
55 #include <cyg/hal/hal_io.h>
56 #include <cyg/hal/drv_api.h>
57 #include <cyg/io/io.h>
58 #include <cyg/io/devtab.h>
59 #include <cyg/io/disk.h>
63 // ----------------------------------------------------------------------------
68 # define D(_args_) diag_printf _args_
73 // ----------------------------------------------------------------------------
75 #include <cyg/hal/v850_common.h>
77 static volatile unsigned char* P10 = (volatile unsigned char*)V850_REG_P10;
78 static volatile unsigned char* PM10 = (volatile unsigned char*)V850_REG_PM10;
79 static volatile unsigned char* PU10 = (volatile unsigned char*)V850_REG_PU10;
81 #define CF_BASE 0x00380000
83 #define CF_HW_INIT() \
90 #define CF_HW_RESET() \
94 for (i = 0; i < 500000; i++); \
96 for (i = 0; i < 500000; i++); \
99 #define CF_HW_BUSY_WAIT() \
101 while (0 == (*P10 & (1<<4))); \
104 // ----------------------------------------------------------------------------
107 volatile cyg_uint16 *base;
110 // ----------------------------------------------------------------------------
112 static cyg_bool cf_disk_init(struct cyg_devtab_entry *tab);
114 static Cyg_ErrNo cf_disk_read(disk_channel *chan,
117 cyg_uint32 block_num);
120 static Cyg_ErrNo cf_disk_write(disk_channel *chan,
123 cyg_uint32 block_num);
125 static Cyg_ErrNo cf_disk_get_config(disk_channel *chan,
130 static Cyg_ErrNo cf_disk_set_config(disk_channel *chan,
135 static Cyg_ErrNo cf_disk_lookup(struct cyg_devtab_entry **tab,
136 struct cyg_devtab_entry *sub_tab,
139 static DISK_FUNS(cf_disk_funs,
146 // ----------------------------------------------------------------------------
148 #define CF_DISK_INSTANCE(_number_,_base_,_mbr_supp_,_name_) \
149 static cf_disk_info_t cf_disk_info##_number_ = { \
150 base: (volatile cyg_uint16 *)_base_, \
152 DISK_CHANNEL(cf_disk_channel##_number_, \
154 cf_disk_info##_number_, \
158 BLOCK_DEVTAB_ENTRY(cf_disk_io##_number_, \
161 &cyg_io_disk_devio, \
164 &cf_disk_channel##_number_ \
167 // ----------------------------------------------------------------------------
169 #ifdef CYGVAR_DEVS_DISK_V85X_EDB_V850_DISK0
170 CF_DISK_INSTANCE(0, CF_BASE, true, CYGDAT_IO_DISK_V85X_EDB_V850_DISK0_NAME);
173 // ----------------------------------------------------------------------------
175 static __inline__ cyg_uint8
176 get_status(volatile cyg_uint16 *base)
179 HAL_READ_UINT16(base + 7, val);
180 return (val & 0x00FF);
183 static __inline__ cyg_uint8
184 get_error(volatile cyg_uint16 *base)
187 HAL_READ_UINT16(base + 6, val);
188 return ((val >> 8) & 0x00FF);
191 static __inline__ void
192 set_dctrl(volatile cyg_uint16 *base, cyg_uint8 dbits)
194 cyg_uint16 val = dbits;
195 HAL_WRITE_UINT16(base + 7, val);
199 exe_cmd(volatile cyg_uint16 *base,
210 lba0_7 = lba_addr & 0xFF;
211 lba8_23 = (lba_addr >> 8) & 0xFFFF;
212 lba24_27 = (lba_addr >> 24) & 0x0F;
214 // drive and LBA addressing mode flag
215 if (0 == drive) drv = 0x40;
220 HAL_WRITE_UINT16(base + 1, sec_cnt | (lba0_7 << 8));
221 HAL_WRITE_UINT16(base + 2, lba8_23);
222 HAL_WRITE_UINT16(base + 3, lba24_27 | drv | (cmd << 8));
226 return (0 == (get_status(base) & CF_SREG_ERR));
230 read_data(volatile cyg_uint16 *base,
234 cyg_uint16 *bufp = (cyg_uint16 *)buf;
239 for (i = 0; i < 512; i += 2)
242 HAL_READ_UINT16(base + 4, data);
243 if (i < len) *bufp++ = data;
250 write_data(volatile cyg_uint16 *base,
254 cyg_uint16 *bufp = (cyg_uint16 * const)buf;
259 for (i = 0; i < 512; i += 2)
263 if (i < len) data = *bufp++;
266 HAL_WRITE_UINT16(base + 4, data);
273 id_strcpy(char *dest, cyg_uint16 *src, cyg_uint16 size)
277 for (i = 0; i < size; i+=2)
279 *dest++ = (char)(*src >> 8);
280 *dest++ = (char)(*src & 0x00FF);
286 // ----------------------------------------------------------------------------
289 cf_disk_init(struct cyg_devtab_entry *tab)
291 disk_channel *chan = (disk_channel *) tab->priv;
292 cf_disk_info_t *info = (cf_disk_info_t *) chan->dev_priv;
293 cf_ata_identify_data_t *ata_id;
294 cyg_uint8 id_buf[sizeof(cf_ata_identify_data_t)];
295 cyg_disk_identify_t ident;
300 D(("CF(%p) hw init\n", info->base));
305 D(("CF(%p) identify drive\n", info->base));
307 if (!exe_cmd(info->base, CF_ATA_IDENTIFY_DRIVE_CMD, 0, 0, 0))
309 D(("CF(%p) error (%x)\n", info->base, get_error(info->base)));
312 read_data(info->base, id_buf, sizeof(cf_ata_identify_data_t));
314 ata_id = (cf_ata_identify_data_t *)id_buf;
316 D(("CF(%p) general conf = %x\n", info->base, ata_id->general_conf));
318 if (0x848A != ata_id->general_conf)
321 id_strcpy(ident.serial, ata_id->serial, 20);
322 id_strcpy(ident.firmware_rev, ata_id->firmware_rev, 8);
323 id_strcpy(ident.model_num, ata_id->model_num, 40);
325 ident.cylinders_num = ata_id->num_cylinders;
326 ident.heads_num = ata_id->num_heads;
327 ident.sectors_num = ata_id->num_sectors;
328 ident.lba_sectors_num = ata_id->lba_total_sectors[1] << 16 |
329 ata_id->lba_total_sectors[0];
331 if (!(chan->callbacks->disk_init)(tab))
334 if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident))
341 cf_disk_lookup(struct cyg_devtab_entry **tab,
342 struct cyg_devtab_entry *sub_tab,
345 disk_channel *chan = (disk_channel *) (*tab)->priv;
346 return (chan->callbacks->disk_lookup)(tab, sub_tab, name);
350 cf_disk_read(disk_channel *chan,
353 cyg_uint32 block_num)
355 cf_disk_info_t *info = (cf_disk_info_t *)chan->dev_priv;
357 D(("CF(%p) read block %d\n", info->base, block_num));
359 if (!exe_cmd(info->base, CF_ATA_READ_SECTORS_CMD, 0, block_num, 1))
361 D(("CF(%p) error (%x)\n", info->base, get_error(info->base)));
364 read_data(info->base, buf, len);
370 cf_disk_write(disk_channel *chan,
373 cyg_uint32 block_num)
375 cf_disk_info_t *info = (cf_disk_info_t *)chan->dev_priv;
377 D(("CF(%p) write block %d\n", info->base, block_num));
379 if (!exe_cmd(info->base, CF_ATA_WRITE_SECTORS_CMD, 0, block_num, 1))
381 D(("CF(%p) error (%x)\n", info->base, get_error(info->base)));
384 write_data(info->base, buf, len);
390 cf_disk_get_config(disk_channel *chan,
399 cf_disk_set_config(disk_channel *chan,
407 // ----------------------------------------------------------------------------
408 // EOF v85x_edb_v850_disk.c