]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/disk/synth/v2_0/src/synthdisk.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / disk / synth / v2_0 / src / synthdisk.c
1 //==========================================================================
2 //
3 //      synthdisk.c
4 //
5 //      Disk device driver for the synthetic target 
6 //
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) 2004, 2006 eCosCentric Limited
13 //
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.
17 //
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
21 // for more details.
22 //
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.
26 //
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.
33 //
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.
36 //
37 // -------------------------------------------
38 //####ECOSGPLCOPYRIGHTEND####
39 //==========================================================================
40 //#####DESCRIPTIONBEGIN####
41 //
42 // Author(s):    savin
43 // Contributors: 
44 // Date:         2003-06-18
45 //
46 //####DESCRIPTIONEND####
47 //
48 //==========================================================================
49
50 #include <pkgconf/devs_disk_ecosynth.h>
51
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>
61
62 #include <stdio.h> // sprintf
63
64 // ----------------------------------------------------------------------------
65
66 //#define DEBUG 1
67
68 // ----------------------------------------------------------------------------
69
70 typedef struct {
71     int        num;
72     cyg_uint32 cylinders_num;
73     cyg_uint32 heads_num;
74     cyg_uint32 sectors_num;
75     cyg_uint32 size;
76     int        filefd;
77     char       *filename;
78 } synth_disk_info_t;
79
80 typedef struct { int dummy; } synth_controller_t;
81
82 // ----------------------------------------------------------------------------
83
84 static cyg_bool synth_disk_init(struct cyg_devtab_entry *tab);
85
86 static Cyg_ErrNo synth_disk_read(disk_channel *chan, 
87                                  void         *buf,
88                                  cyg_uint32    len,
89                                  cyg_uint32    block_num);
90
91 static Cyg_ErrNo synth_disk_write(disk_channel *chan, 
92                                   const void   *buf,
93                                   cyg_uint32    len,
94                                   cyg_uint32    block_num);
95
96 static Cyg_ErrNo synth_disk_get_config(disk_channel *chan, 
97                                        cyg_uint32    key,
98                                        const void   *xbuf, 
99                                        cyg_uint32   *len);
100
101 static Cyg_ErrNo synth_disk_set_config(disk_channel *chan, 
102                                        cyg_uint32    key,
103                                        const void   *xbuf, 
104                                        cyg_uint32   *len);
105
106 static Cyg_ErrNo synth_disk_lookup(struct cyg_devtab_entry  **tab,
107                                    struct cyg_devtab_entry   *sub_tab,
108                                    const char                *name);
109
110 DISK_FUNS(synth_disk_funs, 
111           synth_disk_read, 
112           synth_disk_write, 
113           synth_disk_get_config,
114           synth_disk_set_config
115 );
116
117 // ----------------------------------------------------------------------------
118
119
120 #define SYNTH_DISK_INSTANCE(_number_,_mbr_supp_, _cyl_,_hpt_,_spt_)                             \
121 static synth_disk_info_t synth_disk_info##_number_ = {                                          \
122     num:           _number_,                                                                    \
123     cylinders_num: _cyl_,                                                                       \
124     heads_num:     _hpt_,                                                                       \
125     sectors_num:   _spt_,                                                                       \
126     size:          CYGNUM_IO_DISK_ECOSYNTH_DISK##_number_##_SIZE,                               \
127     filefd:        -1,                                                                          \
128     filename:      CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_FILENAME                            \
129 };                                                                                              \
130 static synth_controller_t synth_controller_##_number_;                                          \
131 DISK_CONTROLLER( synth_disk_controller_##_number_, synth_controller_##_number_ );               \
132 DISK_CHANNEL(synth_disk_channel##_number_,                                                      \
133                     synth_disk_funs,                                                            \
134                     synth_disk_info##_number_,                                                  \
135                     synth_disk_controller_##_number_,                                           \
136                     _mbr_supp_,                                                                 \
137                     4                                                                           \
138 );                                                                                              \
139 BLOCK_DEVTAB_ENTRY(synth_disk_io##_number_,                                                     \
140              CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_NAME,                                     \
141              0,                                                                                 \
142              &cyg_io_disk_devio,                                                                \
143              synth_disk_init,                                                                   \
144              synth_disk_lookup,                                                                 \
145              &synth_disk_channel##_number_                                                      \
146 );
147
148 // ----------------------------------------------------------------------------
149
150 #ifdef CYGVAR_DEVS_DISK_ECOSYNTH_DISK0
151 # ifndef CYGIMP_IO_DISK_ECOSYNTH_DISK0_MBR
152 SYNTH_DISK_INSTANCE(0, false, 0, 0, 0);
153 # else
154 SYNTH_DISK_INSTANCE(0, true, CYGIMP_IO_DISK_ECOSYNTH_DISK0_CYLINDERS,
155                              CYGIMP_IO_DISK_ECOSYNTH_DISK0_HEADS,
156                              CYGIMP_IO_DISK_ECOSYNTH_DISK0_SECTORS);
157 # endif
158 #endif
159
160 // ----------------------------------------------------------------------------
161
162 static cyg_bool 
163 synth_disk_init(struct cyg_devtab_entry *tab)
164 {
165     disk_channel      *chan       = (disk_channel *) tab->priv;
166     synth_disk_info_t *synth_info = (synth_disk_info_t *) chan->dev_priv;
167     bool result = true;
168
169     if (chan->init) 
170         return true;
171
172 #ifdef DEBUG
173     diag_printf("synth disk %d init size=%d\n", 
174                 synth_info->num, synth_info->size);
175 #endif
176    
177     synth_info->filefd = cyg_hal_sys_open(synth_info->filename, 
178             CYG_HAL_SYS_O_RDWR,
179             CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|CYG_HAL_SYS_S_IRWXO);
180
181     if (-ENOENT == synth_info->filefd)
182     {
183         synth_info->filefd = cyg_hal_sys_open(synth_info->filename, 
184             CYG_HAL_SYS_O_RDWR|CYG_HAL_SYS_O_CREAT, 0644);
185         
186         if (synth_info->filefd >= 0)
187         {
188             unsigned char b = 0x00;
189             int i;
190         
191             for (i = 0; i < synth_info->size; i++)
192                 cyg_hal_sys_write(synth_info->filefd, &b, 1);    
193         }
194     }
195
196     if (synth_info->filefd < 0)
197     {
198         CYG_ASSERT(false, "Can't open/create disk image file");
199         return false;
200     }
201    
202     if (result)
203     {
204  
205         if (!(chan->callbacks->disk_init)(tab))
206             return false;
207     }
208     return result;
209 }
210
211 // ----------------------------------------------------------------------------
212
213 static Cyg_ErrNo 
214 synth_disk_lookup(struct cyg_devtab_entry  **tab, 
215                   struct cyg_devtab_entry  *sub_tab,
216                   const char               *name)
217 {
218     Cyg_ErrNo res;
219     disk_channel *chan = (disk_channel *) (*tab)->priv;
220     synth_disk_info_t *synth_info = (synth_disk_info_t *) chan->dev_priv;
221     cyg_disk_identify_t ident;
222        
223     ident.serial[0]       = '\0';
224     ident.firmware_rev[0] = '\0';
225     ident.model_num[0]    = '\0';
226     ident.lba_sectors_num = synth_info->size / 512;
227     ident.cylinders_num   = synth_info->cylinders_num;
228     ident.heads_num       = synth_info->heads_num;
229     ident.sectors_num     = synth_info->sectors_num;
230     ident.phys_block_size = 1;
231     ident.max_transfer    = 2048;
232     
233     res = (chan->callbacks->disk_connected)(*tab, &ident);
234
235     if( res == ENOERR )    
236         res = (chan->callbacks->disk_lookup(tab, sub_tab, name));
237
238     return res;
239 }
240
241 // ----------------------------------------------------------------------------
242
243 static Cyg_ErrNo 
244 synth_disk_read(disk_channel *chan, 
245                 void         *buf,
246                 cyg_uint32    len,
247                 cyg_uint32    block_num)
248 {
249     synth_disk_info_t *synth_info = (synth_disk_info_t *)chan->dev_priv;
250
251 #ifdef DEBUG
252     diag_printf("synth disk read block %d\n", block_num);
253 #endif
254     
255     if (synth_info->filefd >= 0)
256     {
257         cyg_hal_sys_lseek(synth_info->filefd, 
258                           block_num * chan->info->block_size,
259                           CYG_HAL_SYS_SEEK_SET);
260         cyg_hal_sys_read(synth_info->filefd, buf, len*512);
261         return ENOERR;
262     }
263     return -EIO; 
264 }
265
266 // ----------------------------------------------------------------------------
267
268 static Cyg_ErrNo 
269 synth_disk_write(disk_channel *chan,
270                  const void   *buf,
271                  cyg_uint32    len,
272                  cyg_uint32    block_num)
273 {
274     synth_disk_info_t *synth_info = (synth_disk_info_t *)chan->dev_priv;
275
276 #ifdef DEBUG
277     diag_printf("synth disk write block %d\n", block_num);
278 #endif
279  
280     if (synth_info->filefd >= 0)
281     {
282         cyg_hal_sys_lseek(synth_info->filefd, 
283                           block_num * chan->info->block_size,
284                           CYG_HAL_SYS_SEEK_SET);
285         cyg_hal_sys_write(synth_info->filefd, buf, len*512);
286 //        cyg_hal_sys_fdatasync(synth_info->filefd);
287         return ENOERR;
288     }
289     return -EIO; 
290 }
291
292 // ----------------------------------------------------------------------------
293
294 static Cyg_ErrNo
295 synth_disk_get_config(disk_channel *chan, 
296                       cyg_uint32    key,
297                       const void   *xbuf, 
298                       cyg_uint32   *len)
299 {
300
301 #ifdef DEBUG
302     diag_printf("synth disk get config\n");
303 #endif
304     
305     return -EINVAL;
306 }
307
308 // ----------------------------------------------------------------------------
309
310 static Cyg_ErrNo
311 synth_disk_set_config(disk_channel *chan, 
312                       cyg_uint32    key,
313                       const void   *xbuf, 
314                       cyg_uint32   *len)
315 {
316     Cyg_ErrNo res = ENOERR;
317 #ifdef DEBUG
318     diag_printf("synth disk set config\n");
319 #endif
320
321     switch ( key )
322     {
323     case CYG_IO_SET_CONFIG_DISK_MOUNT:
324         // We have nothing to do here for this option.
325         break;
326             
327     case CYG_IO_SET_CONFIG_DISK_UMOUNT:
328         if( chan->info->mounts == 0 )
329         {
330             // If this is the last unmount of this disk, then disconnect it from
331             // the driver system so the user can swap it out if he wants.
332             res = (chan->callbacks->disk_disconnected)(chan);
333         }
334         break;
335             
336     default:
337         res = -EINVAL;
338         break;
339     }
340     
341     return res;
342 }
343
344 // ----------------------------------------------------------------------------
345
346 externC cyg_bool synth_disk_change( int unit, char *filename, int size,
347                                     int cyls, int heads, int sectors)
348 {
349     struct cyg_devtab_entry  *tab        = &synth_disk_io0;
350     disk_channel             *chan       = (disk_channel *) tab->priv;
351     synth_disk_info_t        *synth_info = (synth_disk_info_t *) chan->dev_priv;
352     int err = 0;
353     
354     if (!chan->init) 
355         return false;
356
357     synth_info->filename = filename;
358     synth_info->size = size;
359     synth_info->cylinders_num = cyls;
360     synth_info->heads_num = heads;
361     synth_info->sectors_num = sectors;
362     
363 #ifdef DEBUG
364     diag_printf("synth disk %d change size=%d\n", 
365                 synth_info->num, synth_info->size);
366 #endif
367
368     err = cyg_hal_sys_close( synth_info->filefd );
369
370 #ifdef DEBUG
371     if( err != 0 )
372     {
373         diag_printf("synth disk change, failed to close old image: %d\n",err);
374     }
375 #endif
376     
377     synth_info->filefd = cyg_hal_sys_open(synth_info->filename, 
378             CYG_HAL_SYS_O_RDWR,
379             CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|CYG_HAL_SYS_S_IRWXO);
380
381     if (-ENOENT == synth_info->filefd)
382     {
383         synth_info->filefd = cyg_hal_sys_open(synth_info->filename, 
384             CYG_HAL_SYS_O_RDWR|CYG_HAL_SYS_O_CREAT, 0644);
385         
386         if (synth_info->filefd >= 0)
387         {
388             unsigned char b = 0x00;
389             int i;
390         
391             for (i = 0; i < synth_info->size; i++)
392                 cyg_hal_sys_write(synth_info->filefd, &b, 1);    
393         }
394     }
395
396     if (synth_info->filefd < 0)
397     {
398         CYG_ASSERT(false, "Can't open/create disk image file");
399         return false;
400     }
401
402     return true;
403 }
404
405 // ----------------------------------------------------------------------------
406 // EOF synthdisk.c