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.
12 // Copyright (C) 2006 eCosCentric Ltd.
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // -------------------------------------------
38 //####ECOSGPLCOPYRIGHTEND####
39 //==========================================================================
40 //#####DESCRIPTIONBEGIN####
46 //####DESCRIPTIONEND####
48 //==========================================================================
50 #include <pkgconf/devs_disk_v85x_edb_v850.h>
52 #include <cyg/infra/cyg_type.h>
53 #include <cyg/infra/cyg_ass.h>
54 #include <cyg/infra/diag.h>
55 #include <cyg/hal/hal_arch.h>
56 #include <cyg/hal/hal_io.h>
57 #include <cyg/hal/drv_api.h>
58 #include <cyg/io/io.h>
59 #include <cyg/io/devtab.h>
60 #include <cyg/io/disk.h>
64 // ----------------------------------------------------------------------------
69 # define D(_args_) diag_printf _args_
74 // ----------------------------------------------------------------------------
76 #include <cyg/hal/v850_common.h>
78 static volatile unsigned char* P10 = (volatile unsigned char*)V850_REG_P10;
79 static volatile unsigned char* PM10 = (volatile unsigned char*)V850_REG_PM10;
80 static volatile unsigned char* PU10 = (volatile unsigned char*)V850_REG_PU10;
82 #define CF_BASE 0x00380000
84 #define CF_HW_INIT() \
91 #define CF_HW_RESET() \
95 for (i = 0; i < 500000; i++); \
97 for (i = 0; i < 500000; i++); \
100 #define CF_HW_BUSY_WAIT() \
102 while (0 == (*P10 & (1<<4))); \
105 // ----------------------------------------------------------------------------
108 volatile cyg_uint16 *base;
111 // ----------------------------------------------------------------------------
113 static cyg_bool cf_disk_init(struct cyg_devtab_entry *tab);
115 static Cyg_ErrNo cf_disk_read(disk_channel *chan,
118 cyg_uint32 block_num);
121 static Cyg_ErrNo cf_disk_write(disk_channel *chan,
124 cyg_uint32 block_num);
126 static Cyg_ErrNo cf_disk_get_config(disk_channel *chan,
131 static Cyg_ErrNo cf_disk_set_config(disk_channel *chan,
136 static Cyg_ErrNo cf_disk_lookup(struct cyg_devtab_entry **tab,
137 struct cyg_devtab_entry *sub_tab,
140 DISK_FUNS(cf_disk_funs,
147 // ----------------------------------------------------------------------------
149 // No h/w controller structure is needed, but the address of the
150 // second argument is taken anyway.
151 DISK_CONTROLLER(cf_disk_controller, cf_disk_controller);
153 #define CF_DISK_INSTANCE(_number_,_base_,_mbr_supp_,_name_) \
154 static cf_disk_info_t cf_disk_info##_number_ = { \
155 base: (volatile cyg_uint16 *)_base_, \
157 DISK_CHANNEL(cf_disk_channel##_number_, \
159 cf_disk_info##_number_, \
160 cf_disk_controller, \
164 BLOCK_DEVTAB_ENTRY(cf_disk_io##_number_, \
167 &cyg_io_disk_devio, \
170 &cf_disk_channel##_number_ \
173 // ----------------------------------------------------------------------------
175 #ifdef CYGVAR_DEVS_DISK_V85X_EDB_V850_DISK0
176 CF_DISK_INSTANCE(0, CF_BASE, true, CYGDAT_IO_DISK_V85X_EDB_V850_DISK0_NAME);
179 // ----------------------------------------------------------------------------
181 static __inline__ cyg_uint8
182 get_status(volatile cyg_uint16 *base)
185 HAL_READ_UINT16(base + 7, val);
186 return (val & 0x00FF);
189 static __inline__ cyg_uint8
190 get_error(volatile cyg_uint16 *base)
193 HAL_READ_UINT16(base + 6, val);
194 return ((val >> 8) & 0x00FF);
197 static __inline__ void
198 set_dctrl(volatile cyg_uint16 *base, cyg_uint8 dbits)
200 cyg_uint16 val = dbits;
201 HAL_WRITE_UINT16(base + 7, val);
205 exe_cmd(volatile cyg_uint16 *base,
216 lba0_7 = lba_addr & 0xFF;
217 lba8_23 = (lba_addr >> 8) & 0xFFFF;
218 lba24_27 = (lba_addr >> 24) & 0x0F;
220 // drive and LBA addressing mode flag
221 if (0 == drive) drv = 0x40;
226 HAL_WRITE_UINT16(base + 1, sec_cnt | (lba0_7 << 8));
227 HAL_WRITE_UINT16(base + 2, lba8_23);
228 HAL_WRITE_UINT16(base + 3, lba24_27 | drv | (cmd << 8));
232 return (0 == (get_status(base) & CF_SREG_ERR));
236 read_data(volatile cyg_uint16 *base,
240 cyg_uint16 *bufp = (cyg_uint16 *)buf;
245 for (i = 0; i < 512; i += 2)
248 HAL_READ_UINT16(base + 4, data);
249 if (i < len) *bufp++ = data;
256 write_data(volatile cyg_uint16 *base,
260 cyg_uint16 *bufp = (cyg_uint16 * const)buf;
265 for (i = 0; i < 512; i += 2)
269 if (i < len) data = *bufp++;
272 HAL_WRITE_UINT16(base + 4, data);
279 id_strcpy(char *dest, cyg_uint16 *src, cyg_uint16 size)
283 for (i = 0; i < size; i+=2)
285 *dest++ = (char)(*src >> 8);
286 *dest++ = (char)(*src & 0x00FF);
292 // ----------------------------------------------------------------------------
295 cf_disk_init(struct cyg_devtab_entry *tab)
297 disk_channel *chan = (disk_channel *) tab->priv;
298 cf_disk_info_t *info = (cf_disk_info_t *) chan->dev_priv;
299 cf_ata_identify_data_t *ata_id;
300 cyg_uint8 id_buf[sizeof(cf_ata_identify_data_t)];
301 cyg_disk_identify_t ident;
306 D(("CF(%p) hw init\n", info->base));
311 D(("CF(%p) identify drive\n", info->base));
313 if (!exe_cmd(info->base, CF_ATA_IDENTIFY_DRIVE_CMD, 0, 0, 0))
315 D(("CF(%p) error (%x)\n", info->base, get_error(info->base)));
318 read_data(info->base, id_buf, sizeof(cf_ata_identify_data_t));
320 ata_id = (cf_ata_identify_data_t *)id_buf;
322 D(("CF(%p) general conf = %x\n", info->base, ata_id->general_conf));
324 if (0x848A != ata_id->general_conf)
327 id_strcpy(ident.serial, ata_id->serial, 20);
328 id_strcpy(ident.firmware_rev, ata_id->firmware_rev, 8);
329 id_strcpy(ident.model_num, ata_id->model_num, 40);
331 ident.cylinders_num = ata_id->num_cylinders;
332 ident.heads_num = ata_id->num_heads;
333 ident.sectors_num = ata_id->num_sectors;
334 ident.lba_sectors_num = ata_id->lba_total_sectors[1] << 16 |
335 ata_id->lba_total_sectors[0];
336 ident.phys_block_size = 1;
337 ident.max_transfer = 512;
338 if (!(chan->callbacks->disk_init)(tab))
341 if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident))
348 cf_disk_lookup(struct cyg_devtab_entry **tab,
349 struct cyg_devtab_entry *sub_tab,
352 disk_channel *chan = (disk_channel *) (*tab)->priv;
353 return (chan->callbacks->disk_lookup)(tab, sub_tab, name);
357 cf_disk_read(disk_channel *chan,
360 cyg_uint32 block_num)
362 cf_disk_info_t *info = (cf_disk_info_t *)chan->dev_priv;
364 D(("CF(%p) read block %d\n", info->base, block_num));
366 if (!exe_cmd(info->base, CF_ATA_READ_SECTORS_CMD, 0, block_num, 1))
368 D(("CF(%p) error (%x)\n", info->base, get_error(info->base)));
371 read_data(info->base, buf, len);
377 cf_disk_write(disk_channel *chan,
380 cyg_uint32 block_num)
382 cf_disk_info_t *info = (cf_disk_info_t *)chan->dev_priv;
384 D(("CF(%p) write block %d\n", info->base, block_num));
386 if (!exe_cmd(info->base, CF_ATA_WRITE_SECTORS_CMD, 0, block_num, 1))
388 D(("CF(%p) error (%x)\n", info->base, get_error(info->base)));
391 write_data(info->base, buf, len);
397 cf_disk_get_config(disk_channel *chan,
406 cf_disk_set_config(disk_channel *chan,
414 // ----------------------------------------------------------------------------
415 // EOF v85x_edb_v850_disk.c