Initial version of libomxil-vc4 for RPI3
[platform/adaptation/broadcom/libomxil-vc4.git] / interface / vmcs_host / vc_vchi_filesys.c
1 /*
2 Copyright (c) 2012, Broadcom Europe Ltd
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the copyright holder nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <ctype.h>
31 #include <assert.h>
32
33 #include "vchost.h"
34
35 #include "interface/vcos/vcos.h"
36 #include "interface/vchi/vchi.h"
37 #include "interface/vchi/common/endian.h"
38
39 #include "vc_vchi_filesys.h"
40 #include "interface/vmcs_host/vc_vchi_fileservice_defs.h"
41
42 /******************************************************************************
43 Global data.
44 ******************************************************************************/
45
46 /******************************************************************************
47 Local types and defines.
48 ******************************************************************************/
49 typedef enum {
50    VC_SECTOR_IO_NONE,
51    VC_SECTOR_IO_READING,
52    VC_SECTOR_IO_WRITING
53 } VC_SECTOR_IO_T;
54
55 typedef struct {
56
57    VCHI_SERVICE_HANDLE_T open_handle;
58
59    int32_t               num_connections;
60
61    //Host->2727
62    FILESERV_MSG_T        fileserv_msg;
63
64    //2727->Host   XXX
65    FILESERV_MSG_T        vc_msg;
66
67    VCOS_THREAD_T         filesys_thread;
68
69    // used to signal response has arrived
70    VCOS_EVENT_T          response_event;
71
72    //we lock each vc_filesys function call
73    VCOS_MUTEX_T          filesys_lock;
74
75    //used to signal msg arrivals
76    VCOS_EVENT_T          filesys_msg_avail;
77
78    // Outstanding transaction's ID
79    volatile uint32_t     cur_xid;
80
81    // Copy of the header code from responses
82    int32_t      resp_code;
83    int32_t      err_no;
84
85    char        *bulk_buffer;
86    int32_t      initialised;
87
88 } FILESYS_SERVICE_T;
89
90 static FILESYS_SERVICE_T vc_filesys_client;
91
92
93 /******************************************************************************
94 Static functions.
95 ******************************************************************************/
96
97 //Lock the host state
98 static __inline int32_t lock_obtain (void) {
99    int ret = -1;
100    if(vc_filesys_client.initialised && vcos_mutex_lock(&vc_filesys_client.filesys_lock) == VCOS_SUCCESS) {
101       vchi_service_use(vc_filesys_client.open_handle);
102       ret = 0;
103    }
104    return ret;
105 }
106
107 //Unlock the host state
108 static __inline void lock_release (void) {
109    vcos_assert(vc_filesys_client.initialised);
110    vchi_service_release(vc_filesys_client.open_handle);
111    vcos_mutex_unlock(&vc_filesys_client.filesys_lock);
112 }
113
114 // File Service VCHI functions
115
116 static int vchi_msg_stub(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len );
117
118 static int vchi_msg_stub_noblock(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len);
119
120 static int vc_fs_message_handler( FILESERV_MSG_T* msg, uint32_t nbytes );
121
122 static void *filesys_task_func(void *arg);
123
124 static void filesys_callback( void *callback_param, VCHI_CALLBACK_REASON_T reason, void *msg_handle );
125
126
127
128 #ifdef PRINTF
129 #ifdef WIN32
130 #define printf tprintf
131 #endif
132 static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
133                     struct file_service_msg_body const * body);
134 #endif
135 static int fs_host_direntbytestream_create(struct dirent *d, void *buffer);
136 static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer);
137
138 /*---------------------------------------------------------------------------*/
139
140 /******************************************************************************
141 NAME
142    vc_filesys_init
143
144 SYNOPSIS
145    vc_filesys_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) {
146
147 FUNCTION
148    Initialise the file system for use. A negative return value
149    indicates failure (which may mean it has not been started on VideoCore).
150
151 RETURNS
152    int
153 ******************************************************************************/
154 int vc_vchi_filesys_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections )
155 {
156    int32_t success = 0;
157    SERVICE_CREATION_T filesys_parameters;
158    VCOS_THREAD_ATTR_T attrs;
159    VCOS_STATUS_T status;
160
161    // record the number of connections
162    memset( &vc_filesys_client, 0, sizeof(FILESYS_SERVICE_T) );
163    vc_filesys_client.num_connections = num_connections;
164
165    if(!vcos_verify(vc_filesys_client.num_connections < 2))
166       return -1;
167
168    status = vcos_mutex_create(&vc_filesys_client.filesys_lock, "HFilesys");
169    vcos_assert(status == VCOS_SUCCESS);
170
171    status = vcos_event_create(&vc_filesys_client.filesys_msg_avail, "HFilesys");
172    vcos_assert(status == VCOS_SUCCESS);
173
174    //create sema used to signal cmd response has arrived
175    status = vcos_event_create(&vc_filesys_client.response_event, "HFilesys");
176    vcos_assert(status == VCOS_SUCCESS);
177
178    vc_filesys_client.bulk_buffer = vcos_malloc_aligned(FILESERV_MAX_BULK, 16, "HFilesys bulk_recv");
179    vc_filesys_client.cur_xid = 0;
180
181    memset(&filesys_parameters, 0, sizeof(filesys_parameters));
182    filesys_parameters.service_id = FILESERV_4CC;   // 4cc service code
183    filesys_parameters.connection = connections[0]; // passed in fn ptrs
184    filesys_parameters.rx_fifo_size = 0;            // rx fifo size (unused)
185    filesys_parameters.tx_fifo_size = 0;            // tx fifo size (unused)
186    filesys_parameters.callback = &filesys_callback;
187    filesys_parameters.callback_param = &vc_filesys_client.filesys_msg_avail;
188    filesys_parameters.want_unaligned_bulk_rx = 0;
189    filesys_parameters.want_unaligned_bulk_tx = 0;
190    filesys_parameters.want_crc = 0;
191    filesys_parameters.version.version = VC_FILESERV_VER;
192    filesys_parameters.version.version_min = VC_FILESERV_VER;
193
194    success = vchi_service_open( initialise_instance, &filesys_parameters, &vc_filesys_client.open_handle );
195    vcos_assert( success == 0 );
196
197    vcos_thread_attr_init(&attrs);
198    vcos_thread_attr_setstacksize(&attrs, 4000);
199    vcos_thread_attr_settimeslice(&attrs, 1);
200
201    vc_filesys_client.initialised = 1;
202
203    status = vcos_thread_create(&vc_filesys_client.filesys_thread, "HFilesys", &attrs, filesys_task_func, NULL);
204    vcos_assert(status == VCOS_SUCCESS);
205
206    /* Not using service immediately - release videocore */
207    vchi_service_release(vc_filesys_client.open_handle);
208
209    return (int)success;
210 }
211
212 static void *filesys_task_func(void *arg)
213 {
214    int32_t success;
215    uint32_t msg_len;
216
217    (void)arg;
218
219    vc_hostfs_init();
220
221    while(1) {
222       // wait for the semaphore to say that there is a message
223       if (vcos_event_wait(&vc_filesys_client.filesys_msg_avail) != VCOS_SUCCESS || vc_filesys_client.initialised == 0)
224          break;
225
226       vchi_service_use(vc_filesys_client.open_handle);
227       // read the message - should we really "peek" this
228       while (1) {
229          success = vchi_msg_dequeue(vc_filesys_client.open_handle, &vc_filesys_client.vc_msg,
230                                     sizeof(vc_filesys_client.vc_msg), &msg_len, VCHI_FLAGS_NONE);
231          if (!success)
232             break;
233
234          /* coverity[tainted_string_argument] */
235          success = (int32_t) vc_fs_message_handler(&vc_filesys_client.vc_msg, msg_len);
236          (void)success;
237       }
238       vchi_service_release(vc_filesys_client.open_handle);
239    }
240
241    return 0;
242 }
243
244
245 /******************************************************************************
246 NAME
247    filesys_callback
248
249 SYNOPSIS
250    void filesys_callback( void *callback_param,
251                      const VCHI_CALLBACK_REASON_T reason,
252                      const void *msg_handle )
253
254 FUNCTION
255    VCHI callback
256
257 RETURNS
258    int
259 ******************************************************************************/
260 static void filesys_callback( void *callback_param,
261                              const VCHI_CALLBACK_REASON_T reason,
262                              void *msg_handle )
263 {
264    (void)msg_handle;
265
266    switch( reason ) {
267
268    case VCHI_CALLBACK_MSG_AVAILABLE:
269       {
270          VCOS_EVENT_T *event = (VCOS_EVENT_T *) callback_param;
271          if(event)
272             vcos_event_signal(event);
273       }
274       break;
275
276    case VCHI_CALLBACK_BULK_RECEIVED:
277       break;
278    case VCHI_CALLBACK_BULK_SENT:
279       break;
280
281    default:
282       return;
283    }
284 }
285
286 /******************************************************************************
287 NAME
288    vc_filesys_stop
289
290 SYNOPSIS
291    void vc_filesys_stop()
292
293 FUNCTION
294    This tells us that the file system service has stopped, thereby preventing
295    any of the functions from doing anything.
296
297 RETURNS
298    void
299 ******************************************************************************/
300
301 void vc_filesys_stop ()
302 {
303    int32_t result;
304    void *dummy;
305
306    if(lock_obtain() != 0)
307       return;
308
309    result = vchi_service_close(vc_filesys_client.open_handle);
310    vcos_assert(result == 0);
311
312    vc_filesys_client.initialised = 0;
313
314    vcos_event_signal(&vc_filesys_client.filesys_msg_avail);
315    vcos_thread_join(&vc_filesys_client.filesys_thread, &dummy);
316
317    vcos_event_delete(&vc_filesys_client.filesys_msg_avail);
318    vcos_event_delete(&vc_filesys_client.response_event);
319    vcos_mutex_delete(&vc_filesys_client.filesys_lock);
320
321    if(vc_filesys_client.bulk_buffer)
322       vcos_free(vc_filesys_client.bulk_buffer);
323 }
324
325 /******************************************************************************
326 NAME
327    vc_filesys_single_param
328
329 SYNOPSIS
330    int vc_filesys_single_param(uint32_t param, uint32_t fn)
331
332 FUNCTION
333    Utility function for implementing filesys methods
334
335 RETURNS
336    void
337 ******************************************************************************/
338 static int vc_filesys_single_param(uint32_t param, uint32_t fn)
339 {
340    int success = -1;
341
342    if(lock_obtain() == 0)
343    {
344       vc_filesys_client.fileserv_msg.params[0] = param;
345       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, fn, 4) == FILESERV_RESP_OK)
346          success = 0;
347       
348       lock_release();
349    }
350
351    return success;
352 }
353
354 /******************************************************************************
355 NAME
356    vc_filesys_single_string
357
358 SYNOPSIS
359    int vc_filesys_single_string(uint32_t param, const char *str, uint32_t fn, int return_param)
360
361 FUNCTION
362    Utility function for implementing filesys methods
363
364 RETURNS
365    void
366 ******************************************************************************/
367 static int vc_filesys_single_string(uint32_t param, const char *str, uint32_t fn, int return_param)
368 {
369    int ret = -1;
370    int len = strlen(str);
371
372    if(len < FILESERV_MAX_DATA && lock_obtain() == 0)
373    {
374       vc_filesys_client.fileserv_msg.params[0] = param;
375       /* coverity[buffer_size_warning] - the length of str has already been checked */
376       strncpy((char*)vc_filesys_client.fileserv_msg.data, str, FILESERV_MAX_DATA);
377     
378       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, fn, len+1+16) == FILESERV_RESP_OK)
379       {
380          if(return_param)
381             ret = (int) vc_filesys_client.fileserv_msg.params[0];
382          else
383             ret = 0;
384       }
385
386       lock_release();
387    }
388
389    return ret;
390 }
391
392 /* Standard UNIX low-level library functions (declared in unistd.h) */
393 /******************************************************************************
394 NAME
395    vc_filesys_close
396
397 SYNOPSIS
398    int vc_filesys_close(int fildes)
399
400 FUNCTION
401    Deallocates the file descriptor to a file.
402
403 RETURNS
404    Successful completion: 0
405    Otherwise: -1
406 ******************************************************************************/
407
408 int vc_filesys_close(int fildes)
409 {
410    return vc_filesys_single_param((uint32_t) fildes, VC_FILESYS_CLOSE);
411 }
412
413
414 /******************************************************************************
415 NAME
416    vc_filesys_lseek
417
418 SYNOPSIS
419    long vc_filesys_lseek(int fildes, long offset, int whence)
420
421 FUNCTION
422    Sets the file pointer associated with the open file specified by fildes.
423
424 RETURNS
425    Successful completion: offset
426    Otherwise: -1
427 ******************************************************************************/
428
429 long vc_filesys_lseek(int fildes, long offset, int whence)
430 {
431    long set = -1;
432
433    if(lock_obtain() == 0)
434    {
435       vc_filesys_client.fileserv_msg.params[0] = (uint32_t) fildes;
436       vc_filesys_client.fileserv_msg.params[1] = (uint32_t) offset;
437       vc_filesys_client.fileserv_msg.params[2] = (uint32_t) whence;
438       
439       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_LSEEK, 12) == FILESERV_RESP_OK)
440          set = (long) vc_filesys_client.fileserv_msg.params[0];
441       
442       lock_release();
443    }
444
445    return set;
446 }
447
448 /******************************************************************************
449 NAME
450    vc_filesys_lseek64
451
452 SYNOPSIS
453    int64_t vc_filesys_lseek64(int fildes, int64_t offset, int whence)
454
455 FUNCTION
456    Sets the file pointer associated with the open file specified by fildes.
457
458 RETURNS
459    Successful completion: file pointer value
460    Otherwise: -1
461 ******************************************************************************/
462
463 int64_t vc_filesys_lseek64(int fildes, int64_t offset, int whence)
464 {
465    int64_t set = -1;
466
467    if(lock_obtain() == 0)
468    {
469       vc_filesys_client.fileserv_msg.params[0] = (uint32_t) fildes;
470       vc_filesys_client.fileserv_msg.params[1] = (uint32_t) offset;        // LSB
471       vc_filesys_client.fileserv_msg.params[2] = (uint32_t)(offset >> 32); // MSB
472       vc_filesys_client.fileserv_msg.params[3] = (uint32_t) whence;
473       
474       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_LSEEK64, 16) == FILESERV_RESP_OK)
475       {
476          set = vc_filesys_client.fileserv_msg.params[0];
477          set += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
478       }
479       
480       lock_release();
481    }
482
483    return set;
484 }
485
486 /******************************************************************************
487 NAME
488    vc_filesys_mount
489
490 SYNOPSIS
491    int vc_filesys_mount(const char *device, const char *mountpoint, const char *options)
492
493 FUNCTION
494    Mounts a filesystem at a given location
495
496 RETURNS
497    Successful completion: 0
498 ******************************************************************************/
499
500 int vc_filesys_mount(const char *device, const char *mountpoint, const char *options)
501 {
502    int set = -1, len;
503    int a = strlen(device);
504    int b = strlen(mountpoint);
505    int c = strlen(options);
506
507    if(a + b + c + 3 < FILESERV_MAX_DATA && lock_obtain() == 0)
508    {
509       char *str = (char *) vc_filesys_client.fileserv_msg.data;
510
511       memcpy(str, device, a);
512       str[a] = 0;
513       memcpy(str+a+1, mountpoint, b);
514       str[a+1+b] = 0;
515       memcpy(str+a+b+2, options, c);
516       str[a+b+c+2] = 0;
517       len = a + b + c + 3 + (int)(((FILESERV_MSG_T *)0)->data);
518       len = ((len + (VCHI_BULK_GRANULARITY-1)) & ~(VCHI_BULK_GRANULARITY-1)) + VCHI_BULK_GRANULARITY;
519       
520       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_MOUNT, len) == FILESERV_RESP_OK)
521          set = (int) vc_filesys_client.fileserv_msg.params[0];
522
523       lock_release();
524    }
525
526    return set;
527 }
528
529 /******************************************************************************
530 NAME
531    vc_filesys_umount
532
533 SYNOPSIS
534    int vc_filesys_mount(const char *mountpoint)
535
536 FUNCTION
537    Un-mounts a removable device from the location that it has been mounted
538    to earlier in the session
539
540 RETURNS
541    Successful completion: 0
542 ******************************************************************************/
543
544 int vc_filesys_umount(const char *mountpoint)
545 {
546    return vc_filesys_single_string(0, mountpoint, VC_FILESYS_UMOUNT, 1);
547 }
548
549 /******************************************************************************
550 NAME
551    vc_filesys_open
552
553 SYNOPSIS
554    int vc_filesys_open(const char *path, int vc_oflag)
555
556 FUNCTION
557    Establishes a connection between a file and a file descriptor.
558
559 RETURNS
560    Successful completion: file descriptor
561    Otherwise: -1
562 ******************************************************************************/
563
564 int vc_filesys_open(const char *path, int vc_oflag)
565 {
566    return vc_filesys_single_string((uint32_t) vc_oflag, path, VC_FILESYS_OPEN, 1);
567 }
568
569
570 /******************************************************************************
571 NAME
572    vc_filesys_read
573
574 SYNOPSIS
575    int vc_filesys_read(int fildes, void *buf, unsigned int nbyte)
576
577 FUNCTION
578    Attempts to read nbyte bytes from the file associated with the file
579    descriptor, fildes, into the buffer pointed to by buf.
580
581 RETURNS
582    Successful completion: number of bytes read
583    Otherwise: -1
584 ******************************************************************************/
585
586 /******************************************************************************
587
588 FUNCTION
589
590
591 RETURNS
592    Successful completion: the number of bytes received
593    Otherwise  negative error code
594 ******************************************************************************/
595 static int vc_vchi_msg_bulk_read(FILESERV_MSG_T* msg, uint16_t cmd_id, uint32_t transfer_len, uint8_t* recv_addr )
596 {
597    uint32_t i;
598    int msg_len;
599    uint32_t host_align_bytes;
600    uint32_t num_bytes_read;
601    int32_t success;
602
603    //this is current file_io_buffer size so assuming never more than this
604    //otherwise we will split the read into chunks
605    if(!vcos_verify(transfer_len <= FILESERV_MAX_BULK))
606       return -1;
607
608    //number of bytes required to align recv_addr
609    host_align_bytes = VCHI_BULK_ALIGN_NBYTES(recv_addr);
610
611    i = vc_filesys_client.cur_xid + 1;
612    i &= 0x7fffffffUL;
613    vc_filesys_client.cur_xid = i;
614
615    msg->xid = vc_filesys_client.cur_xid;
616
617    //fill in cmd id: VC_FILESYS_READ etc
618    msg->cmd_code = cmd_id;
619
620    msg->params[2] = transfer_len;
621
622    msg->params[3] = host_align_bytes;
623
624    //24 comes from the static size of FILESERV_MSG_T
625    msg_len = 24;
626
627    if(vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ) != 0)
628       return -1;
629
630    //wait to receive response
631    if(vcos_event_wait(&vc_filesys_client.response_event) != VCOS_SUCCESS || msg->cmd_code == FILESERV_RESP_ERROR)
632       return -1;
633
634    //total bytes read
635    num_bytes_read = msg->params[0];
636
637    if(!vcos_verify(num_bytes_read <= FILESERV_MAX_BULK))
638       return -1;
639
640    //everything is in msg->data
641    if(msg->cmd_code == FILESERV_RESP_OK) {
642       if(!vcos_verify(num_bytes_read <= FILESERV_MAX_DATA))
643          return -1;
644
645       memcpy(recv_addr, msg->data, num_bytes_read);
646       return (int) num_bytes_read;
647    }
648
649 // Make this code conditional to stop Coverity complaining about dead code
650 #if VCHI_BULK_ALIGN > 1
651    //copy host_align_bytes bytes to recv_addr, now ready for bulk
652    if(host_align_bytes) {
653       memcpy(recv_addr, msg->data, host_align_bytes);
654       recv_addr += host_align_bytes;
655       transfer_len -= host_align_bytes;
656    }
657 #endif
658
659    //receive bulk from host
660    if(msg->cmd_code == FILESERV_BULK_WRITE){
661       //number of end bytes
662       uint32_t end_bytes = msg->params[1];
663       //calculate what portion of read transfer by bulk
664       uint32_t bulk_bytes = (num_bytes_read-host_align_bytes-end_bytes);
665
666       success = vchi_bulk_queue_receive(vc_filesys_client.open_handle,
667                               recv_addr,
668                               bulk_bytes,
669                               VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
670                               NULL );
671       if(!vcos_verify(success == 0))
672          return -1;
673
674       recv_addr+=bulk_bytes;
675
676       //copy any left over end bytes from original msg
677       if(end_bytes)
678          memcpy(recv_addr, &msg->data[host_align_bytes], end_bytes);
679    }
680    else {
681       return -1;
682    }
683
684    return (int) num_bytes_read;
685 }
686
687
688 int vc_filesys_read(int fildes, void *buf, unsigned int nbyte)
689 {
690    int bulk_bytes = 0;
691    int actual_read = 0;
692    int total_byte = 0;
693    uint8_t* ptr = (uint8_t*)buf;
694
695    if (nbyte == 0) {
696       return 0;
697    }
698
699    if(lock_obtain() == 0)
700    {
701       do {
702          bulk_bytes = nbyte > FILESERV_MAX_BULK ? FILESERV_MAX_BULK : nbyte;
703          
704          //we overwrite the response here so fill in data again
705          vc_filesys_client.fileserv_msg.params[0] = (uint32_t)fildes;
706          vc_filesys_client.fileserv_msg.params[1] = 0xffffffffU;        // offset: use -1 to indicate no offset
707          
708          actual_read = vc_vchi_msg_bulk_read(&vc_filesys_client.fileserv_msg , VC_FILESYS_READ, (uint32_t)bulk_bytes, (uint8_t*)ptr);
709          
710          if(bulk_bytes != actual_read) {
711             if(actual_read < 0)
712                total_byte = -1;
713             else
714                total_byte += actual_read;
715             //exit loop
716             break;
717          }
718
719          ptr+=bulk_bytes;
720          nbyte -= actual_read;
721          total_byte += actual_read;
722       }while(nbyte > 0);
723
724       lock_release();
725    }
726
727    return total_byte;
728 }
729
730 /******************************************************************************
731 NAME
732    vc_filesys_write
733
734 SYNOPSIS
735    int vc_filesys_write(int fildes, const void *buf, unsigned int nbyte)
736
737 FUNCTION
738    Attempts to write nbyte bytes from the buffer pointed to by buf to file
739    associated with the file descriptor, fildes.
740
741 RETURNS
742    Successful completion: number of bytes written
743    Otherwise: -1
744 ******************************************************************************/
745
746 /******************************************************************************
747
748 FUNCTION
749
750
751 RETURNS
752    Successful completion: the number of bytes received
753    Otherwise  negative error code
754 ******************************************************************************/
755 static int vc_vchi_msg_bulk_write(FILESERV_MSG_T* msg, uint16_t cmd_id, uint32_t transfer_len, uint8_t* send_addr )
756 {
757    uint32_t i;
758    int msg_len;
759    uint32_t align_bytes = 0;
760    uint32_t bulk_end_bytes = 0;
761    uint32_t bulk_bytes = 0;
762    int num_bytes_written = -1;
763
764    //this is current file_io_buffer size so assuming never more than this
765    //otherwise we will split the read into chunks
766    if(!vcos_verify(transfer_len <= FILESERV_MAX_BULK))
767       return -1;
768
769    i = vc_filesys_client.cur_xid + 1;
770    i &= 0x7fffffffUL;
771    vc_filesys_client.cur_xid = i;
772
773    msg->xid = vc_filesys_client.cur_xid;
774
775    //fill in cmd id VC_FILESYS_OPEN etc
776    msg->cmd_code = cmd_id;
777
778    msg->params[2] = transfer_len;
779
780    //24 comes from the static size of FILESERV_MSG_T
781    msg_len = 24;
782
783    //put it all in one msg
784    if(transfer_len <= FILESERV_MAX_DATA) {
785       memcpy(msg->data, send_addr, transfer_len);
786       msg->params[3] = 0;
787       msg_len += transfer_len;
788       //send request to write to host
789       if(vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ) != 0)
790          return -1;
791
792       // wait to receive response
793       if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS &&
794          msg->cmd_code != FILESERV_RESP_ERROR && msg->params[0] == transfer_len)
795       {
796          //vc_fs_message_handler copies resp into outgoing msg struct
797          num_bytes_written = (int)msg->params[0];
798       }
799    }
800    else {
801       //required to make send_addr for bulk
802       align_bytes = VCHI_BULK_ALIGN_NBYTES(send_addr);
803
804 // Make this code conditional to stop Coverity complaining about dead code
805 #if VCHI_BULK_ALIGN > 1
806       //copy vc_align bytes to msg->data, send_addr ready for bulk
807       if(align_bytes) {
808          msg->params[3] = align_bytes;
809          memcpy(msg->data, send_addr, align_bytes);
810          transfer_len -= align_bytes;
811          send_addr += align_bytes;
812          msg_len += align_bytes;
813       }
814       else
815 #endif
816          msg->params[3] = 0;
817
818       // need to ensure we have the appropriate alignment
819       bulk_bytes = (transfer_len)&(~(VCHI_BULK_GRANULARITY-1));
820
821       bulk_end_bytes = transfer_len-bulk_bytes;
822
823       if(bulk_end_bytes) {
824          memcpy(msg->data+align_bytes, send_addr+bulk_bytes, bulk_end_bytes);
825          msg_len += bulk_end_bytes;
826       }
827
828       //send request to write to host
829       if(vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ) != 0)
830          return -1;
831
832       //send bulk VCHI_FLAGS_BLOCK_UNTIL_QUEUED is ok because we wait for response msg with actual length written
833       if(vchi_bulk_queue_transmit( vc_filesys_client.open_handle,
834                                    send_addr,
835                                    bulk_bytes,
836                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
837                                    NULL ) != 0)
838          return -1;
839
840       // wait to receive response sent by filsys_task_func
841       if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS && msg->cmd_code == FILESERV_BULK_READ)
842          num_bytes_written = (int)msg->params[0];
843    }
844
845    return num_bytes_written;
846 }
847
848
849 int vc_filesys_write(int fildes, const void *buf, unsigned int nbyte)
850 {
851    int num_wrt = 0;
852    int bulk_bytes = 0;
853    int actual_written = 0;
854    uint8_t *ptr = (uint8_t*) buf;
855
856    if (nbyte == 0) {
857       return 0;
858    }
859
860    if(lock_obtain() == 0)
861    {
862       //will split the read into 4K chunks based on vc fwrite buffer size array size
863       //we will make this more dynamic later
864       do {
865          bulk_bytes = nbyte > FILESERV_MAX_BULK ? FILESERV_MAX_BULK : nbyte;
866          
867          //we overwrite the response here so fill in data again
868          vc_filesys_client.fileserv_msg.params[0] = (uint32_t)fildes;
869          vc_filesys_client.fileserv_msg.params[1] = 0xffffffffU;        // offset: use -1 to indicate no offset
870          
871          actual_written = vc_vchi_msg_bulk_write(&vc_filesys_client.fileserv_msg , VC_FILESYS_WRITE, (uint32_t)bulk_bytes, (uint8_t*)ptr);
872          
873          if(bulk_bytes != actual_written) {
874             if(actual_written < 0)
875                num_wrt = -1;
876             else
877                num_wrt += actual_written;
878             break;
879          }
880          
881          ptr+=bulk_bytes;
882          nbyte -= actual_written;
883          num_wrt += actual_written;
884       }while(nbyte > 0);
885
886       lock_release();
887    }
888
889    return num_wrt;
890 }
891
892
893 /* Directory management functions */
894
895 /******************************************************************************
896 NAME
897    vc_filesys_closedir
898
899 SYNOPSIS
900    int vc_filesys_closedir(void *dhandle)
901
902 FUNCTION
903    Ends a directory list iteration.
904
905 RETURNS
906    Successful completion: 0
907    Otherwise: -1
908 ******************************************************************************/
909
910 int vc_filesys_closedir(void *dhandle)
911 {
912    return vc_filesys_single_param((uint32_t)dhandle, VC_FILESYS_CLOSEDIR);
913 }
914
915
916 /******************************************************************************
917 NAME
918    vc_filesys_format
919
920 SYNOPSIS
921    int vc_filesys_format(const char *path)
922
923 FUNCTION
924    Formats the physical file system that contains path.
925
926 RETURNS
927    Successful completion: 0
928    Otherwise: -1
929 ******************************************************************************/
930
931 int vc_filesys_format(const char *path)
932 {
933    return vc_filesys_single_string(0, path, VC_FILESYS_FORMAT, 0);
934 }
935
936
937 /******************************************************************************
938 NAME
939    vc_filesys_freespace
940
941 SYNOPSIS
942    int vc_filesys_freespace(const char *path)
943
944 FUNCTION
945    Returns the amount of free space on the physical file system that contains
946    path.
947
948 RETURNS
949    Successful completion: free space
950    Otherwise: -1
951 ******************************************************************************/
952
953 int vc_filesys_freespace(const char *path)
954 {
955    return vc_filesys_single_string(0, path, VC_FILESYS_FREESPACE, 1);
956 }
957
958
959 /******************************************************************************
960 NAME
961    vc_filesys_freespace64
962
963 SYNOPSIS
964    int64_t vc_filesys_freespace64(const char *path)
965
966 FUNCTION
967    Returns the amount of free space on the physical file system that contains
968    path.
969
970 RETURNS
971    Successful completion: free space
972    Otherwise: -1
973 ******************************************************************************/
974
975 int64_t vc_filesys_freespace64(const char *path)
976 {
977    int64_t freespace = -1LL;
978
979    if(lock_obtain() == 0)
980    {
981       strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
982       
983       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_FREESPACE64,
984                         (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK)
985       {
986          freespace = vc_filesys_client.fileserv_msg.params[0];
987          freespace += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
988       }
989
990       lock_release();
991    }
992
993    return freespace;
994 }
995
996
997 /******************************************************************************
998 NAME
999    vc_filesys_get_attr
1000
1001 SYNOPSIS
1002    int vc_filesys_get_attr(const char *path, fattributes_t *attr)
1003
1004 FUNCTION
1005    Gets the file/directory attributes.
1006
1007 RETURNS
1008    Successful completion: 0
1009    Otherwise: -1
1010 ******************************************************************************/
1011
1012 int vc_filesys_get_attr(const char *path, fattributes_t *attr)
1013 {
1014    int success = -1;
1015
1016    if(lock_obtain() == 0)
1017    {
1018       strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
1019       
1020       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_GET_ATTR,
1021                         (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK)
1022       {
1023          success = 0;
1024          *attr = (fattributes_t) vc_filesys_client.fileserv_msg.params[0];
1025       }
1026
1027       lock_release();
1028    }
1029
1030    return success;
1031 }
1032
1033
1034 /******************************************************************************
1035 NAME
1036    vc_filesys_fstat
1037
1038 SYNOPSIS
1039    int64_t vc_filesys_fstat(int fildes, FSTAT_T *buf)
1040
1041 FUNCTION
1042    Returns the file stat info structure for the specified file.
1043    This structure includes date and size info.
1044
1045 RETURNS
1046    Successful completion: 0
1047    Otherwise: -1
1048 ******************************************************************************/
1049
1050 int vc_filesys_fstat(int fildes, FSTAT_T *buf)
1051 {
1052    int success = -1;
1053
1054    if (buf != NULL && lock_obtain() == 0)
1055    {
1056       vc_filesys_client.fileserv_msg.params[0] = (uint32_t) fildes;
1057       if ( vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_FSTAT, 4) == FILESERV_RESP_OK )
1058       {
1059          buf->st_size = (int64_t)vc_filesys_client.fileserv_msg.params[0];          // LSB
1060          buf->st_size |= (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;    // MSB
1061          buf->st_modtime = (uint32_t)vc_filesys_client.fileserv_msg.params[2];
1062          // there's room for expansion here to pass across more elements of the structure if required...
1063          success = 0;
1064       }
1065
1066       lock_release();
1067    }
1068
1069    return success;
1070 }
1071
1072
1073 /******************************************************************************
1074 NAME
1075    vc_filesys_mkdir
1076
1077 SYNOPSIS
1078    int vc_filesys_mkdir(const char *path)
1079
1080 FUNCTION
1081    Creates a new directory named by the pathname pointed to by path.
1082
1083 RETURNS
1084    Successful completion: 0
1085    Otherwise: -1
1086 ******************************************************************************/
1087
1088 int vc_filesys_mkdir(const char *path)
1089 {
1090    return vc_filesys_single_string(0, path, VC_FILESYS_MKDIR, 0);
1091 }
1092
1093
1094 /******************************************************************************
1095 NAME
1096    vc_filesys_opendir
1097
1098 SYNOPSIS
1099    void *vc_filesys_opendir(const char *dirname)
1100
1101 FUNCTION
1102    Starts a directory list iteration.
1103
1104 RETURNS
1105    Successful completion: dhandle (pointer)
1106    Otherwise: NULL
1107 ******************************************************************************/
1108
1109 void *vc_filesys_opendir(const char *dirname)
1110 {
1111    return (void *) vc_filesys_single_string(0, dirname, VC_FILESYS_OPENDIR, 1);
1112 }
1113
1114
1115 /******************************************************************************
1116 NAME
1117    vc_filesys_dirsize
1118
1119 SYNOPSIS
1120    int vc_filesys_dirsize(const char *path)
1121
1122 FUNCTION
1123    Look through the specified directory tree and sum the file sizes.
1124
1125 RETURNS
1126    Successful completion: 0
1127    Otherwise: -1
1128 ******************************************************************************/
1129
1130 int64_t vc_filesys_dirsize(const char *path, uint32_t *num_files, uint32_t *num_dirs)
1131 {
1132    int64_t ret = -1;
1133
1134    if(lock_obtain() == 0)
1135    {
1136       strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
1137       
1138       // FIXME: Should probably use a non-blocking call here since it may take a
1139       // long time to do the operation...
1140       if ( vchi_msg_stub(&vc_filesys_client.fileserv_msg,
1141                          VC_FILESYS_DIRSIZE,
1142                          (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK )
1143       {
1144          ret = vc_filesys_client.fileserv_msg.params[0]; 
1145          ret += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
1146          if (num_files)
1147             *num_files = vc_filesys_client.fileserv_msg.params[2];
1148          if (num_dirs)
1149             *num_dirs = vc_filesys_client.fileserv_msg.params[3];
1150       }
1151
1152       lock_release();
1153    }
1154
1155    return ret;
1156 }
1157
1158
1159 /******************************************************************************
1160 NAME
1161    vc_filesys_readdir_r
1162
1163 SYNOPSIS
1164    struct dirent *vc_filesys_readdir_r(void *dhandle, struct dirent *result)
1165
1166 FUNCTION
1167    Fills in the passed result structure with details of the directory entry
1168    at the current psition in the directory stream specified by the argument
1169    dhandle, and positions the directory stream at the next entry.
1170
1171 RETURNS
1172    Successful completion: result
1173    End of directory stream: NULL
1174 ******************************************************************************/
1175
1176 struct dirent *vc_filesys_readdir_r(void *dhandle, struct dirent *result)
1177 {
1178    struct dirent *ret = NULL;
1179
1180    if(lock_obtain() == 0)
1181    {
1182       vc_filesys_client.fileserv_msg.params[0] = (uint32_t)dhandle;
1183       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_READDIR, 4) == FILESERV_RESP_OK)
1184       {
1185          fs_host_direntbytestream_interp(result, (void *)vc_filesys_client.fileserv_msg.data);
1186          ret = result;
1187       }
1188
1189       lock_release();
1190    }
1191
1192    return ret;
1193 }
1194
1195
1196 /******************************************************************************
1197 NAME
1198    vc_filesys_remove
1199
1200 SYNOPSIS
1201    int vc_filesys_remove(const char *path)
1202
1203 FUNCTION
1204    Removes a file or a directory. A directory must be empty before it can be
1205    deleted.
1206
1207 RETURNS
1208    Successful completion: 0
1209    Otherwise: -1
1210 ******************************************************************************/
1211
1212 int vc_filesys_remove(const char *path)
1213 {
1214    return vc_filesys_single_string(0, path, VC_FILESYS_REMOVE, 0);
1215 }
1216
1217
1218 /******************************************************************************
1219 NAME
1220    vc_filesys_rename
1221
1222 SYNOPSIS
1223    int vc_filesys_rename(const char *oldfile, const char *newfile)
1224
1225 FUNCTION
1226    Changes the name of a file. The old and new pathnames must be on the same
1227    physical file system.
1228
1229 RETURNS
1230    Successful completion: 0
1231    Otherwise: -1
1232 ******************************************************************************/
1233
1234 int vc_filesys_rename(const char *oldfile, const char *newfile)
1235 {
1236    int a, b, success = -1;
1237
1238    // Ensure the pathnames aren't too long
1239    if ((a = strlen(oldfile)) < FS_MAX_PATH && (b = strlen(newfile)) < FS_MAX_PATH && lock_obtain() == 0)
1240    {
1241       strncpy((char *)vc_filesys_client.fileserv_msg.data, oldfile, FS_MAX_PATH);
1242       strncpy((char *)&vc_filesys_client.fileserv_msg.data[a+1], newfile, FS_MAX_PATH);
1243       
1244       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_RENAME, 16+a+1+b+1) == FILESERV_RESP_OK)
1245          success = 0;
1246
1247       lock_release();
1248    }
1249
1250    return success;
1251 }
1252
1253
1254 /******************************************************************************
1255 NAME
1256    vc_filesys_reset
1257
1258 SYNOPSIS
1259    int vc_filesys_reset()
1260
1261 FUNCTION
1262    Send a vc_FILESYS_RESET command. This will return immediately.
1263
1264 RETURNS
1265    Successful completion: FILESERV_RESP_OK
1266    Otherwise: -
1267 ******************************************************************************/
1268
1269 int vc_filesys_reset()
1270 {
1271    return vc_filesys_single_param(0, VC_FILESYS_RESET);
1272 }
1273
1274
1275 /******************************************************************************
1276 NAME
1277    vc_filesys_set_attr
1278
1279 SYNOPSIS
1280    int vc_filesys_set_attr(const char *path, fattributes_t attr)
1281
1282 FUNCTION
1283    Sets file/directory attributes.
1284
1285 RETURNS
1286    Successful completion: 0
1287    Otherwise: -1
1288 ******************************************************************************/
1289
1290 int vc_filesys_set_attr(const char *path, fattributes_t attr)
1291 {
1292    return vc_filesys_single_string((uint32_t) attr, path, VC_FILESYS_SET_ATTR, 0);
1293 }
1294
1295
1296 /******************************************************************************
1297 NAME
1298    vc_filesys_setend
1299
1300 SYNOPSIS
1301    int vc_filesys_setend(int fildes)
1302
1303 FUNCTION
1304    Truncates file at current position.
1305
1306 RETURNS
1307    Successful completion: 0
1308    Otherwise: -1
1309 ******************************************************************************/
1310
1311 int vc_filesys_setend(int fildes)
1312 {
1313    return vc_filesys_single_param((uint32_t) fildes, VC_FILESYS_SETEND);
1314 }
1315
1316
1317
1318 /******************************************************************************
1319 NAME
1320    vc_filesys_scandisk
1321
1322 SYNOPSIS
1323    void vc_filesys_scandisk(const char *path)
1324
1325 FUNCTION
1326    Truncates file at current position.
1327
1328 RETURNS
1329    -
1330 ******************************************************************************/
1331
1332 void vc_filesys_scandisk(const char *path)
1333 {
1334    vc_filesys_single_string(0, path, VC_FILESYS_SCANDISK, 0);
1335    return;
1336 }
1337
1338 /******************************************************************************
1339 NAME
1340    vc_filesys_chkdsk
1341
1342 SYNOPSIS
1343    int vc_filesys_chkdsk(const char *path, int fix_errors)
1344
1345 FUNCTION
1346    Truncates file at current position.
1347
1348 RETURNS
1349    -
1350 ******************************************************************************/
1351
1352 int vc_filesys_chkdsk(const char *path, int fix_errors)
1353 {
1354    return vc_filesys_single_string(fix_errors, path, VC_FILESYS_CHKDSK, 1);
1355 }
1356
1357 /******************************************************************************
1358 NAME
1359    vc_filesys_size
1360
1361 SYNOPSIS
1362    int vc_filesys_size(const char *path)
1363
1364 FUNCTION
1365    return size of file
1366
1367 RETURNS
1368    -
1369 ******************************************************************************/
1370
1371 int vc_filesys_size(const char *path)
1372 {
1373    int fd;
1374    int end_pos = 0;
1375    int success = -1;
1376    if((fd = vc_filesys_open(path, VC_O_RDONLY)) == 0)
1377    {
1378       end_pos = vc_filesys_lseek(fd, 0, SEEK_END);
1379       success = vc_filesys_close(fd);
1380       (void)success;
1381    }
1382
1383    return end_pos;
1384 }
1385 /******************************************************************************
1386 NAME
1387    vc_filesys_totalspace
1388
1389 SYNOPSIS
1390    int vc_filesys_totalspace(const char *path)
1391
1392 FUNCTION
1393    Returns the total amount of space on the physical file system that contains
1394    path.
1395
1396 RETURNS
1397    Successful completion: total space
1398    Otherwise: -1
1399 ******************************************************************************/
1400
1401 int vc_filesys_totalspace(const char *path)
1402 {
1403    return vc_filesys_single_string(0, path, VC_FILESYS_TOTALSPACE, 1);
1404 }
1405
1406
1407 /******************************************************************************
1408 NAME
1409    vc_filesys_totalspace64
1410
1411 SYNOPSIS
1412    int64_t vc_filesys_totalspace64(const char *path)
1413
1414 FUNCTION
1415    Returns the total amount of space on the physical file system that contains
1416    path.
1417
1418 RETURNS
1419    Successful completion: total space
1420    Otherwise: -1
1421 ******************************************************************************/
1422
1423 int64_t vc_filesys_totalspace64(const char *path)
1424 {
1425    int64_t totalspace = -1LL;
1426
1427    if(lock_obtain() == 0)
1428    {
1429       strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
1430       
1431       if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_TOTALSPACE64,
1432                         (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK)
1433       {
1434          totalspace = vc_filesys_client.fileserv_msg.params[0];
1435          totalspace += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
1436       }
1437
1438       lock_release();
1439    }
1440
1441    return totalspace;
1442 }
1443
1444
1445 /******************************************************************************
1446 NAME
1447    vc_filesys_diskwritable
1448
1449 SYNOPSIS
1450    int vc_filesys_diskwritable(const char *path)
1451
1452 FUNCTION
1453    Return whether the named disk is writable.
1454
1455 RETURNS
1456    Successful completion: 1 (disk writable) or 0 (disk not writable)
1457    Otherwise: -1
1458 ******************************************************************************/
1459
1460 int vc_filesys_diskwritable(const char *path)
1461 {
1462    return vc_filesys_single_string(0, path, VC_FILESYS_DISKWRITABLE, 1);
1463 }
1464
1465 /******************************************************************************
1466 NAME
1467    vc_filesys_fstype
1468
1469 SYNOPSIS
1470    int vc_filesys_fstype(const char *path)
1471
1472 FUNCTION
1473    Return the filesystem type of the named disk.
1474
1475 RETURNS
1476    Successful completion: disk type (see vc_fileservice_defs.h)
1477    Otherwise: -1
1478 ******************************************************************************/
1479
1480 int vc_filesys_fstype(const char *path)
1481 {
1482    return vc_filesys_single_string(0, path, VC_FILESYS_FSTYPE, 1);
1483 }
1484
1485 /******************************************************************************
1486 NAME
1487    vc_filesys_open_disk_raw
1488
1489 SYNOPSIS
1490    int vc_filesys_open_disk_raw(const char *path)
1491
1492 FUNCTION
1493    Open disk for access in raw mode.
1494
1495 RETURNS
1496    Successful completion: 0
1497    Otherwise: -1
1498 ******************************************************************************/
1499
1500 int vc_filesys_open_disk_raw(const char *path)
1501 {
1502    return vc_filesys_single_string(0, path, VC_FILESYS_OPEN_DISK_RAW, 1);
1503 }
1504
1505 /******************************************************************************
1506 NAME
1507    vc_filesys_close_disk_raw
1508
1509 SYNOPSIS
1510    int vc_filesys_close_disk_raw(const char *path)
1511
1512 FUNCTION
1513    Close disk from access in raw mode.
1514
1515 RETURNS
1516    Successful completion: 0
1517    Otherwise: -1
1518 ******************************************************************************/
1519
1520 int vc_filesys_close_disk_raw(const char *path)
1521 {
1522    return vc_filesys_single_string(0, path, VC_FILESYS_CLOSE_DISK_RAW, 1);
1523 }
1524
1525
1526 /******************************************************************************
1527 NAME
1528    vc_filesys_open_disk
1529
1530 SYNOPSIS
1531    int vc_filesys_open_disk(const char *path)
1532
1533 FUNCTION
1534    Open disk for normal access.
1535
1536 RETURNS
1537    Successful completion: 0
1538    Otherwise: -1
1539 ******************************************************************************/
1540
1541 int vc_filesys_open_disk(const char *path)
1542 {
1543    return vc_filesys_single_string(0, path, VC_FILESYS_OPEN_DISK, 1);
1544 }
1545
1546 /******************************************************************************
1547 NAME
1548    vc_filesys_close_disk
1549
1550 SYNOPSIS
1551    int vc_filesys_close_disk(const char *path)
1552
1553 FUNCTION
1554    Close disk from normal access.
1555
1556 RETURNS
1557    Successful completion: 0
1558    Otherwise: -1
1559 ******************************************************************************/
1560
1561 int vc_filesys_close_disk(const char *path)
1562 {
1563    return vc_filesys_single_string(0, path, VC_FILESYS_CLOSE_DISK, 1);
1564 }
1565
1566 /******************************************************************************
1567 NAME
1568    vc_filesys_numsectors
1569
1570 SYNOPSIS
1571    int vc_filesys_numsectors(const char *path)
1572
1573 FUNCTION
1574    Return number of sectors on disk
1575
1576 RETURNS
1577    Successful completion: greater than 0
1578    Otherwise: -1
1579 ******************************************************************************/
1580
1581 int vc_filesys_numsectors(const char *path)
1582 {
1583    return vc_filesys_single_string(0, path, VC_FILESYS_NUMSECTORS, 1);
1584 }
1585
1586 /******************************************************************************
1587 NAME
1588    vc_filesys_read_sectors
1589
1590 SYNOPSIS
1591    int vc_filesys_read_sectors(const char *path, uint32_t sector_num, char *buffer, uint32_t num_sectors)
1592
1593 FUNCTION
1594    Start streaming sectors from 2727
1595
1596 RETURNS
1597    Successful completion: 0
1598    Otherwise: -1
1599 ******************************************************************************/
1600 int vc_filesys_read_sectors(const char *path, uint32_t sector_num, char *sectors, uint32_t num_sectors, uint32_t *sectors_read)
1601 {
1602 #if VCHI_BULK_ALIGN > 1
1603    uint32_t align_bytes = 0;
1604 #endif
1605    char* bulk_addr = sectors;
1606    int len;
1607    int ret = -1;
1608
1609    if((len = (int)strlen(path)) < FS_MAX_PATH && lock_obtain() == 0)
1610    {
1611       strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
1612       vc_filesys_client.fileserv_msg.params[0] = sector_num;
1613       vc_filesys_client.fileserv_msg.params[1] = num_sectors;
1614
1615 #if VCHI_BULK_ALIGN > 1
1616       //required to make buffer aligned for bulk
1617       align_bytes = VCHI_BULK_ALIGN_NBYTES(sectors);
1618 #endif
1619       //note for read we are currently doing memcpy on host to tell 2727 align is 0
1620       vc_filesys_client.fileserv_msg.params[2] = 0;
1621       
1622       //we send read request
1623       if (vchi_msg_stub_noblock(&vc_filesys_client.fileserv_msg, VC_FILESYS_READ_SECTORS, 16+len+1) == 0)
1624       {
1625          while(num_sectors)
1626          {
1627             uint32_t bulk_sectors = (num_sectors > FILESERV_MAX_BULK_SECTOR) ? (uint32_t)FILESERV_MAX_BULK_SECTOR : num_sectors;
1628             if(vchi_bulk_queue_receive( vc_filesys_client.open_handle,
1629 #if VCHI_BULK_ALIGN > 1
1630                                         align_bytes ? vc_filesys_client.bulk_buffer : bulk_addr,
1631 #else
1632                                         bulk_addr,
1633 #endif
1634                                         (bulk_sectors*FILESERV_SECTOR_LENGTH), VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL) != 0)
1635                break;
1636
1637 #if VCHI_BULK_ALIGN > 1
1638             if(align_bytes) {
1639                //this is bad but will do for now..
1640                memcpy( bulk_addr, vc_filesys_client.bulk_buffer, (bulk_sectors*FILESERV_SECTOR_LENGTH));
1641             }
1642 #endif
1643             bulk_addr += (bulk_sectors*FILESERV_SECTOR_LENGTH);
1644             num_sectors -= bulk_sectors;
1645          }
1646
1647          // now wait to receive resp from original msg...
1648          if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS && vc_filesys_client.fileserv_msg.cmd_code == FILESERV_RESP_OK)
1649          {
1650             *sectors_read = vc_filesys_client.fileserv_msg.params[0];
1651             ret = 0;
1652          }
1653          else
1654          {
1655             //error code in [0]
1656             *sectors_read = vc_filesys_client.fileserv_msg.params[1];
1657             ret = vc_filesys_client.fileserv_msg.params[0];
1658          }
1659       }
1660
1661       lock_release();
1662    }
1663
1664    return ret;
1665 }
1666
1667 /******************************************************************************
1668 NAME
1669    vc_filesys_write_sectors
1670
1671 SYNOPSIS
1672    int vc_filesys_write_sectors(const char *path, uint32_t sector_num, char *sectors, uint32_t num_sectors, uint32_t *sectors_written)
1673
1674 FUNCTION
1675    Start streaming sectors to 2727
1676
1677 RETURNS
1678    Successful completion: 0
1679    Otherwise: -error code
1680 ******************************************************************************/
1681 int vc_filesys_write_sectors(const char *path, uint32_t sector_num, char *sectors, uint32_t num_sectors, uint32_t *sectors_written)
1682 {
1683    uint32_t align_bytes = 0;
1684    char* bulk_addr = sectors;
1685    int len;
1686    int ret = -1;
1687
1688    len = (int) strlen(path);
1689    if((len = (int) strlen(path)) < FS_MAX_PATH && lock_obtain() == 0)
1690    {
1691       vc_filesys_client.fileserv_msg.params[0] = sector_num;
1692       vc_filesys_client.fileserv_msg.params[1] = num_sectors;
1693       
1694       //required to make buffer aligned for bulk
1695       align_bytes = ((unsigned long)sectors & (VCHI_BULK_ALIGN-1));
1696       vc_filesys_client.fileserv_msg.params[2] = align_bytes;
1697       
1698       //copy path at end of any alignbytes
1699       strncpy(((char *)vc_filesys_client.fileserv_msg.data), path, FS_MAX_PATH);
1700       
1701       //we send write request
1702       if (vchi_msg_stub_noblock(&vc_filesys_client.fileserv_msg, VC_FILESYS_WRITE_SECTORS, 16+len+1) == 0)
1703       {
1704          if(align_bytes) {
1705             //note we are cheating and going backward to make addr aligned and sending more data...
1706             bulk_addr -= align_bytes;
1707          }
1708          
1709          while(num_sectors) {
1710             uint32_t bulk_sectors = (num_sectors > FILESERV_MAX_BULK_SECTOR) ? (uint32_t)FILESERV_MAX_BULK_SECTOR : num_sectors;
1711             //we send some extra data at the start
1712             if(vchi_bulk_queue_transmit( vc_filesys_client.open_handle, bulk_addr,
1713                                          VCHI_BULK_ROUND_UP((bulk_sectors*FILESERV_SECTOR_LENGTH)+align_bytes),
1714                                          VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, NULL) != 0)
1715                break;
1716             
1717             //go to next ALIGNED address
1718             bulk_addr += FILESERV_MAX_BULK;
1719             num_sectors -= bulk_sectors;
1720          }
1721          
1722          // now wait to receive resp from original msg...
1723          if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS && vc_filesys_client.fileserv_msg.cmd_code == FILESERV_RESP_OK)
1724          {
1725             *sectors_written = vc_filesys_client.fileserv_msg.params[0];
1726             ret = 0;
1727          }
1728          else
1729          {
1730             //error code in [0]
1731             *sectors_written = vc_filesys_client.fileserv_msg.params[1];
1732             ret = vc_filesys_client.fileserv_msg.params[0];
1733          }
1734       }
1735
1736       lock_release();
1737    }
1738
1739    return ret;
1740 }
1741
1742 /******************************************************************************
1743 NAME
1744    vc_filesys_errno
1745
1746 SYNOPSIS
1747    int vc_filesys_errno(void)
1748
1749 FUNCTION
1750    Returns the error code of the last file system error that occurred.
1751
1752 RETURNS
1753    Error code
1754 ******************************************************************************/
1755
1756 int vc_filesys_errno(void)
1757 {
1758    return (int) vc_filesys_client.err_no;
1759 }
1760
1761
1762 /* File Service Message FIFO functions */
1763
1764 /******************************************************************************
1765 NAME
1766    vchi_msg_stub
1767
1768 SYNOPSIS
1769    static int vc_fs_stub(int verb, int ext_len)
1770
1771 FUNCTION
1772    Generates a request and sends it to the co-processor. It then suspends
1773    until it receives a reply from the host. The calling task must hold
1774    the filesys_lock.
1775
1776 RETURNS
1777    Successful completion: Response code of reply
1778    Otherwise: -
1779 ******************************************************************************/
1780 static int vchi_msg_stub(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len )
1781 {
1782    int ret = -1;
1783    vchi_msg_stub_noblock(msg, cmd_id, msg_len);
1784     
1785    // wait to receive response
1786    if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS)
1787       ret = (int) msg->cmd_code;
1788
1789    return ret;
1790 }
1791
1792 static int vchi_msg_stub_noblock(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len)
1793 {
1794    uint32_t i;
1795
1796    if(!vcos_verify(msg_len <= VCHI_MAX_MSG_SIZE))
1797       return -1;
1798
1799    //will get changed by response from command
1800    vc_filesys_client.resp_code = FILESERV_RESP_ERROR;
1801
1802    //the top bit is used for host/vc
1803    i = vc_filesys_client.cur_xid + 1;
1804    i &= 0x7fffffffUL;
1805    vc_filesys_client.cur_xid = i;
1806
1807    //fill in transaction id, used for response identification
1808    vchi_writebuf_uint32( &(msg->xid), vc_filesys_client.cur_xid  );
1809
1810    //fill in cmd id VC_FILESYS_OPEN etc
1811    vchi_writebuf_uint32( &(msg->cmd_code), cmd_id );
1812
1813    //we always have cmd_id, xid
1814    msg_len += 8;
1815     
1816    //return response code
1817    return (int) vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
1818 }
1819
1820 static int vc_send_response( FILESERV_MSG_T* msg, uint32_t retval, uint32_t nbytes )
1821 {
1822    int success = -1;
1823    //convert all to over the wire values
1824    vchi_writebuf_uint32(&msg->cmd_code, retval);
1825    vchi_writebuf_uint32(&msg->xid, msg->xid);
1826    vchi_writebuf_uint32(&msg->params[0], msg->params[0]);
1827    vchi_writebuf_uint32(&msg->params[1], msg->params[1]);
1828    vchi_writebuf_uint32(&msg->params[2], msg->params[2]);
1829    vchi_writebuf_uint32(&msg->params[3], msg->params[3]);
1830
1831    //start with 8 because always xid and retval
1832    nbytes += 8;
1833
1834    if(vcos_verify(nbytes <= VCHI_MAX_MSG_SIZE))
1835       success = (int) vchi_msg_queue( vc_filesys_client.open_handle, msg, nbytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
1836
1837    return success;
1838 }
1839
1840 /******************************************************************************
1841 NAME
1842    vc_fs_message_handler
1843
1844 SYNOPSIS
1845    static int vc_fs_message_handler()
1846
1847 FUNCTION
1848    Handle messages from the co-processor.
1849
1850 RETURNS
1851    0 - No message found.
1852    1 - Request received and actioned.
1853    2 - Reply received.
1854 ******************************************************************************/
1855
1856 static int vc_fs_message_handler( FILESERV_MSG_T* msg, uint32_t nbytes )
1857 {
1858    int rr = 0;
1859    uint32_t xid = vchi_readbuf_uint32(&msg->xid);
1860
1861    if (xid == vc_filesys_client.cur_xid) {
1862
1863           //memcpy reply to msg should really peek before
1864       vc_filesys_client.fileserv_msg.xid = xid;
1865       vc_filesys_client.fileserv_msg.cmd_code  = vchi_readbuf_uint32(&msg->cmd_code);
1866       vc_filesys_client.fileserv_msg.params[0] = vchi_readbuf_uint32(&msg->params[0]);
1867       vc_filesys_client.fileserv_msg.params[1] = vchi_readbuf_uint32(&msg->params[1]);
1868       vc_filesys_client.fileserv_msg.params[2] = vchi_readbuf_uint32(&msg->params[2]);
1869       vc_filesys_client.fileserv_msg.params[3] = vchi_readbuf_uint32(&msg->params[3]);
1870
1871       //copy any data, 24 is size of header
1872       if(nbytes >24)
1873          memcpy(&vc_filesys_client.fileserv_msg.data, msg->data, (nbytes-24));
1874
1875       vc_filesys_client.resp_code = (int32_t)vc_filesys_client.fileserv_msg.cmd_code;
1876
1877       if (vc_filesys_client.resp_code == FILESERV_RESP_ERROR) {
1878          vc_filesys_client.err_no = (int32_t)vc_filesys_client.fileserv_msg.params[0];
1879       }
1880
1881       // signal vchi_msg_stub which will be waiting for response
1882       vcos_event_signal(&vc_filesys_client.response_event);
1883
1884       rr = 2;
1885    }
1886    else if ((xid & 0x80000000UL) == 0x80000000UL) {
1887       /* Process new requests from the co-processor */
1888
1889       uint32_t retval = FILESERV_RESP_OK;
1890
1891       //this is the number of uint32_t param[] + data that we send back to VC in bytes
1892
1893       uint32_t rlen = 0;
1894       int i;
1895
1896       switch (msg->cmd_code) {
1897
1898       case VC_FILESYS_CLOSE:
1899
1900          i = vc_hostfs_close((int)msg->params[0]);
1901          if (i != 0) {
1902             retval = FILESERV_RESP_ERROR;
1903          }
1904          rlen = 0;
1905          break;
1906
1907       case VC_FILESYS_CLOSEDIR:
1908
1909          i = vc_hostfs_closedir((void *)msg->params[0]);
1910          if (i != 0) {
1911             retval = FILESERV_RESP_ERROR;
1912          }
1913          rlen = 0;
1914          break;
1915
1916       case VC_FILESYS_FORMAT:
1917
1918          i = vc_hostfs_format((const char *)msg->data);
1919          if (i != 0) {
1920             retval = FILESERV_RESP_ERROR;
1921          }
1922          rlen = 0;
1923          break;
1924
1925       case VC_FILESYS_FREESPACE:
1926
1927          i = vc_hostfs_freespace((const char *)msg->data);
1928          if (i < 0) {
1929             retval = FILESERV_RESP_ERROR;
1930             rlen = 0;
1931          } else {
1932             msg->params[0] = (uint32_t)i;
1933             rlen = 4;
1934          }
1935          break;
1936
1937       case VC_FILESYS_FREESPACE64:
1938          {
1939             int64_t freespace;
1940             freespace = vc_hostfs_freespace64((const char *)msg->data);
1941             if (freespace < (int64_t)0) {
1942                retval = FILESERV_RESP_ERROR;
1943                rlen = 0;
1944             } else {
1945                msg->params[0] = (uint32_t)freespace;
1946                msg->params[1] = (uint32_t)(freespace>>32);
1947                rlen = 8;
1948             }
1949          }
1950          break;
1951
1952       case VC_FILESYS_GET_ATTR:
1953          {
1954             fattributes_t attr;
1955
1956             i = vc_hostfs_get_attr((const char *)msg->data,
1957                                    &attr);
1958             if (i != 0) {
1959                retval = FILESERV_RESP_ERROR;
1960                rlen = 0;
1961             } else {
1962                msg->params[0] = (uint32_t) attr;
1963                rlen = 4;
1964             }
1965          }
1966          break;
1967       case VC_FILESYS_LSEEK:
1968
1969          i = vc_hostfs_lseek( (int)msg->params[0],
1970                               (int)msg->params[1],
1971                               (int)msg->params[2]);
1972          if (i < 0) {
1973             retval = FILESERV_RESP_ERROR;
1974             rlen = 0;
1975          } else {
1976             msg->params[0] = (uint32_t) i;
1977             rlen = 4;
1978          }
1979          break;
1980
1981       case VC_FILESYS_LSEEK64:
1982          {
1983             int64_t offset;
1984             offset = (((int64_t) msg->params[2]) << 32) + msg->params[1];
1985
1986             offset = vc_hostfs_lseek64( (int)msg->params[0], offset, (int)msg->params[3]);
1987             if (offset < (int64_t)0) {
1988                retval = FILESERV_RESP_ERROR;
1989                rlen = 0;
1990             } else {
1991                msg->params[0] = (uint32_t)offset;
1992                msg->params[1] = (uint32_t)(offset>>32);
1993                rlen = 8;
1994             }
1995          }
1996          break;
1997
1998       case VC_FILESYS_MKDIR:
1999
2000          i = vc_hostfs_mkdir((const char *)msg->data);
2001          if (i != 0) {
2002             retval = FILESERV_RESP_ERROR;
2003          }
2004          rlen = 0;
2005          break;
2006
2007       case VC_FILESYS_OPEN:
2008
2009          i = vc_hostfs_open((const char *)msg->data,
2010                             (int) msg->params[0]);
2011          if (i < 0) {
2012             retval = FILESERV_RESP_ERROR;
2013          } else {
2014             msg->params[0] = (uint32_t) i;
2015          }
2016          rlen = 4;
2017          break;
2018
2019       case VC_FILESYS_OPENDIR:
2020
2021          msg->params[0] = (uint32_t)vc_hostfs_opendir(
2022                                                       (const char *)msg->data);
2023          if ((void *)msg->params[0] == NULL) {
2024             retval = FILESERV_RESP_ERROR;
2025          }
2026          rlen = 4;
2027          break;
2028
2029       case VC_FILESYS_READ:
2030          {
2031             uint32_t fd = msg->params[0];
2032             uint32_t offset = msg->params[1];
2033             int total_bytes = (int)msg->params[2];
2034             uint32_t nalign_bytes = msg->params[3];
2035
2036             i = 0;
2037
2038             if(!vcos_verify(((int)vc_filesys_client.bulk_buffer & (VCHI_BULK_ALIGN-1)) == 0 &&
2039                             total_bytes <= FILESERV_MAX_BULK))
2040             {
2041                retval = FILESERV_RESP_ERROR;
2042                rlen = 4;
2043                break;
2044             }
2045
2046             rlen = 0;
2047
2048             //perform any seeking
2049             if ( (uint32_t)0xffffffffUL != offset)
2050             {
2051                i = vc_hostfs_lseek( (int)fd,
2052                                     (long int) offset,
2053                                     VC_FILESYS_SEEK_SET);
2054                if ( 0 > i)
2055                {
2056                   retval = FILESERV_RESP_ERROR;
2057                   rlen = 4;
2058                   break;
2059                }
2060             }
2061
2062
2063             //put it all in one msg
2064             if(total_bytes <= FILESERV_MAX_DATA) {
2065                i = vc_hostfs_read( (int)fd,
2066                                    msg->data,
2067                                    (unsigned int) total_bytes);
2068
2069                if(i < 0) {
2070                   retval = FILESERV_RESP_ERROR;
2071                   msg->params[0] = 0;
2072                }
2073                else {
2074                   retval = FILESERV_RESP_OK;
2075                   //send back length of read
2076                   msg->params[0] = (uint32_t) i;
2077                }
2078
2079                msg->params[1] = 0;
2080                rlen = 16 + (uint32_t) i;
2081             }
2082             //bulk transfer required
2083             else {
2084                uint32_t end_bytes = 0;
2085                retval = FILESERV_BULK_WRITE;
2086
2087                //we send the bytes required for HOST buffer align
2088                if(nalign_bytes) {
2089                   i = vc_hostfs_read( (int)fd,
2090                                       msg->data,
2091                                       (unsigned int)nalign_bytes);
2092                   if(i < 0) {
2093                      retval = FILESERV_RESP_ERROR;
2094                      rlen = 16;
2095                      break;
2096                   }
2097                   else if(i != (int)nalign_bytes) {
2098                      //all data will be in one msg
2099                      retval = FILESERV_RESP_OK;
2100                      msg->params[0] = (uint32_t) i;
2101                      msg->params[1] = 0;
2102                      rlen = 16 + (uint32_t) i;
2103                      //send response
2104                      break;
2105                   }
2106
2107                   total_bytes -= i;
2108                   rlen += (uint32_t) i;
2109                }
2110
2111                //bulk bytes
2112                i = vc_hostfs_read((int)fd, vc_filesys_client.bulk_buffer, (unsigned int)total_bytes);
2113
2114                if(i < 0) {
2115                   retval = FILESERV_RESP_ERROR;
2116                   rlen = 16;
2117                   break;
2118                }
2119                else if((i+nalign_bytes) <= FILESERV_MAX_DATA) {
2120                   retval = FILESERV_RESP_OK;
2121                   memcpy(&msg->data[nalign_bytes], &vc_filesys_client.bulk_buffer[0], (size_t) i);
2122                   //read size
2123                   msg->params[0] = (i + nalign_bytes);
2124                   msg->params[1] = 0;
2125                   rlen = i + nalign_bytes + 16;
2126                   break;
2127                }
2128
2129                //copy end unaligned length bytes into msg->data
2130                end_bytes  = (uint32_t) (i & (VCHI_BULK_GRANULARITY-1));
2131                if(end_bytes) {
2132                   int end_index = i - (int) end_bytes;
2133                   memcpy(&msg->data[nalign_bytes], &vc_filesys_client.bulk_buffer[end_index], end_bytes);
2134                   rlen += end_bytes;
2135                }
2136
2137                //send back total bytes
2138                msg->params[0] = (uint32_t)(i + nalign_bytes);
2139                //number of end bytes
2140                msg->params[1] = end_bytes;
2141                //number of bulk bytes
2142                msg->params[2] = (uint32_t)(i - end_bytes);
2143                //16 for param len
2144                rlen += 16;
2145
2146                //queue bulk to be sent
2147                if(vchi_bulk_queue_transmit( vc_filesys_client.open_handle,
2148                                             vc_filesys_client.bulk_buffer,
2149                                             msg->params[2],
2150                                             VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
2151                                             NULL ) != 0)
2152                {
2153                   retval = FILESERV_RESP_ERROR;
2154                   rlen = 4;
2155                   break;
2156                }
2157             }
2158          }
2159          //send response
2160          break;
2161
2162       case VC_FILESYS_READDIR:
2163          {
2164             struct dirent result;
2165             if (vc_hostfs_readdir_r((void *)msg->params[0],
2166                                     &result) == NULL) {
2167                retval = FILESERV_RESP_ERROR;
2168                rlen = 4;
2169             } else {
2170                rlen = (uint32_t) (16+fs_host_direntbytestream_create(&result,
2171                                                                      (void *)msg->data));
2172             }
2173          }
2174          break;
2175
2176       case VC_FILESYS_REMOVE:
2177
2178          i = vc_hostfs_remove((const char *)msg->data);
2179          if (i != 0) {
2180             retval = FILESERV_RESP_ERROR;
2181          }
2182          rlen = 0;
2183          break;
2184
2185       case VC_FILESYS_RENAME:
2186
2187          i = (int) strlen((char *)msg->data);
2188          if (vc_hostfs_rename((const char *)msg->data,
2189                               (const char *)&msg->data[i+1])
2190              != 0) {
2191             retval = FILESERV_RESP_ERROR;
2192          }
2193          rlen = 0;
2194          break;
2195
2196       case VC_FILESYS_SETEND:
2197
2198          i = vc_hostfs_setend( (int)msg->params[0] );
2199          if (i != 0) {
2200             retval = FILESERV_RESP_ERROR;
2201          }
2202          rlen = 0;
2203          break;
2204
2205       case VC_FILESYS_SET_ATTR:
2206
2207          i = vc_hostfs_set_attr((const char *)msg->data,
2208                                 (fattributes_t)msg->params[0]);
2209          if (i != 0) {
2210             retval = FILESERV_RESP_ERROR;
2211          }
2212          rlen = 0;
2213          break;
2214
2215       case VC_FILESYS_TOTALSPACE:
2216
2217          i = vc_hostfs_totalspace((const char *)msg->data);
2218          if (i < 0) {
2219             retval = FILESERV_RESP_ERROR;
2220             rlen = 0;
2221          } else {
2222             msg->params[0] = (uint32_t) i;
2223             rlen = 4;
2224          }
2225          break;
2226
2227       case VC_FILESYS_TOTALSPACE64:
2228          {
2229             int64_t totalspace;
2230             totalspace = vc_hostfs_totalspace64((const char *)msg->data);
2231             if (totalspace < (int64_t)0) {
2232                retval = FILESERV_RESP_ERROR;
2233                rlen = 0;
2234             } else {
2235                msg->params[0] = (uint32_t)totalspace;
2236                msg->params[1] = (uint32_t)(totalspace>>32);
2237                rlen = 8;
2238             }
2239          }
2240          break;
2241 #if 0  // I don't think host systems are ready for these yet
2242       case VC_FILESYS_SCANDISK:
2243
2244          vc_hostfs_scandisk((const char *)msg->data);
2245          rlen = 0;
2246          break;
2247
2248       case VC_FILESYS_CHKDSK:
2249
2250          i = vc_hostfs_chkdsk((const char *)msg->data, msg->params[0]);
2251          if (i < 0) {
2252             retval = FILESERV_RESP_ERROR;
2253             rlen = 0;
2254          } else {
2255             msg->params[0] = (uint32_t)i;
2256             rlen = 4;
2257          }
2258          break;
2259 #endif
2260       case VC_FILESYS_WRITE:
2261          {
2262             uint32_t fd = msg->params[0];
2263             //            uint32_t offset = msg->params[1];
2264             int total_bytes = (int)msg->params[2];
2265             uint32_t nalign_bytes = msg->params[3];
2266             retval = FILESERV_RESP_OK;
2267             i = 0;
2268
2269             //everything in one msg
2270             if(total_bytes <= FILESERV_MAX_DATA)
2271             {
2272                i = vc_hostfs_write( (int)fd,
2273                                     msg->data,
2274                                     (unsigned int) total_bytes);
2275                if (i < 0) {
2276                   retval = FILESERV_RESP_ERROR;
2277                } else {
2278                   msg->params[0] = (uint32_t) i;
2279                }
2280                rlen = 4;
2281                //send response
2282                break;
2283             }
2284             else
2285             {
2286                uint32_t end_bytes;
2287                uint32_t bulk_bytes;
2288                uint32_t total_bytes_written = 0;
2289                i = 0;
2290                //one return param
2291                rlen = 4;
2292                retval = FILESERV_BULK_READ;
2293
2294                //write bytes required for VC buffer align
2295                if(nalign_bytes) {
2296                   i = vc_hostfs_write( (int)fd,
2297                                        msg->data,
2298                                        (unsigned int)nalign_bytes);
2299                   if(i < 0) {
2300                      retval = FILESERV_RESP_ERROR;
2301                      msg->params[0] = 0;
2302                      //break from switch and send reply
2303                      break;
2304                   }
2305                   total_bytes_written += i;
2306                   total_bytes -= nalign_bytes;
2307                }
2308
2309                //calculate bytes that wil lbe sent by bulk
2310                bulk_bytes = (uint32_t)((total_bytes)&(~(VCHI_BULK_ALIGN-1)));
2311             
2312                end_bytes = total_bytes-bulk_bytes;
2313
2314
2315
2316                if(vchi_bulk_queue_receive(vc_filesys_client.open_handle,
2317                                           vc_filesys_client.bulk_buffer,
2318                                           bulk_bytes,
2319                                           VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
2320                                           NULL) != 0 ||
2321                   (i = vc_hostfs_write( (int)fd,
2322                                         vc_filesys_client.bulk_buffer,
2323                                         (unsigned int) bulk_bytes)) < 0)
2324                {
2325                   retval = FILESERV_RESP_ERROR;
2326                   msg->params[0] = 0;
2327                   break;
2328                }
2329             
2330                total_bytes_written += i;
2331             
2332                if(end_bytes) {
2333                   i = vc_hostfs_write( (int)fd,
2334                                        msg->data+nalign_bytes,
2335                                        (unsigned int)end_bytes);
2336                
2337                   total_bytes_written += i;
2338                }
2339             
2340                if(i < 0) {
2341                   retval = FILESERV_RESP_ERROR;
2342                   msg->params[0] = 0;
2343                   break;
2344                }
2345             
2346                msg->params[0] = total_bytes_written;
2347
2348             }
2349          }
2350          break;
2351
2352       default:
2353          rlen = 4;
2354          retval = FILESERV_RESP_ERROR;
2355          break;
2356       }
2357
2358       //convert all to over the wire values and send
2359       vc_send_response( msg, retval, rlen );
2360
2361       rr = 1;
2362
2363    } else {
2364       /* A message has been left in the fifo and the host side has been reset.
2365          The message needs to be flushed. It would be better to do this by resetting
2366          the fifos. */
2367    }
2368
2369    return rr;
2370 }
2371
2372
2373 /******************************************************************************
2374 NAME
2375    showmsg
2376
2377 SYNOPSIS
2378    static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
2379                        struct file_service_msg_body const * body)
2380
2381 FUNCTION
2382    De-bug tool: prints out fifo message.
2383
2384 RETURNS
2385    void
2386 ******************************************************************************/
2387
2388 #ifdef PRINTF
2389 static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
2390                     struct file_service_msg_body const * body)
2391 {
2392    unsigned int ael = (head->ext_length + 15) & ~15;
2393    printf("Sync=%08x XID=%08x Code=%08x Extlen=%08x (%d bytes follow)\n",
2394           head->sync, head->xid, head->cmd_code, head->ext_length, ael);
2395    if (ael) {
2396       unsigned int i;
2397       printf("Content:");
2398       for (i = 0; i < 4 && i*4 < head->ext_length; ++i) printf(" %08x", body->params[i]);
2399       //for(i = 0; i+16 < head->ext_length; ++i) printf(" %02x", body->data[i]);
2400       if (head->ext_length > 16) printf(" plus %d bytes\n", head->ext_length);
2401    }
2402    printf("\n");
2403 }
2404 #endif
2405
2406
2407 /******************************************************************************
2408 NAME
2409    fs_host_direntbytestream_create
2410
2411 SYNOPSIS
2412    static int fs_host_direntbytestream_create(struct dirent *d, void *buffer)
2413
2414 FUNCTION
2415    Turns a variable of type struct dirent into a compiler independent byte
2416    stream, which is stored in buffer.
2417
2418 RETURNS
2419    Successful completion: The length of the byte stream
2420    Otherwise: -1
2421 ******************************************************************************/
2422 static void write_bytestream(void *a, char *b, int n)
2423 {
2424    int i;
2425    for (i=0;i<n;i++) {
2426       b[i] = ((char *)a)[i];
2427    }
2428    for (;i<4;i++) {
2429       b[i] = 0;
2430    }
2431 }
2432
2433 static int fs_host_direntbytestream_create(struct dirent *d, void *buffer)
2434 {
2435    char *buf = (char*)buffer;
2436
2437    // Write d_name (D_NAME_MAX_SIZE chars)
2438    memcpy(buf, &d->d_name, D_NAME_MAX_SIZE);
2439    buf += D_NAME_MAX_SIZE;
2440
2441    // Write d_size (unsigned int)
2442    write_bytestream((void *)&d->d_size, buf, (int)sizeof(d->d_size));
2443    buf += 4;
2444
2445    // Write d_attrib (int)
2446    write_bytestream((void *)&d->d_attrib, buf, (int)sizeof(d->d_attrib));
2447    buf += 4;
2448
2449    // Write d_modtime (time_t)
2450    write_bytestream((void *)&d->d_modtime, buf, (int)sizeof(d->d_modtime));
2451    buf += 4;
2452
2453    return (int)(buf-(char *)buffer);
2454 }
2455
2456
2457 /******************************************************************************
2458 NAME
2459    fs_host_direntbytestream_interp
2460
2461 SYNOPSIS
2462    static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer)
2463
2464 FUNCTION
2465    Turns a compiler independent byte stream back into a struct of type dirent.
2466
2467 RETURNS
2468    Successful completion: 0
2469    Otherwise: -1
2470 ******************************************************************************/
2471 static void read_bytestream(void *a, char *b, int n)
2472 {
2473    int i;
2474    for (i=0;i<n;i++) {
2475       ((char *)a)[i] = b[i];
2476    }
2477 }
2478
2479 static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer)
2480 {
2481    char *buf = (char*)buffer;
2482
2483    // Read d_name (D_NAME_MAX_SIZE chars)
2484    memcpy(&d->d_name, buf, D_NAME_MAX_SIZE);
2485    buf += D_NAME_MAX_SIZE;
2486
2487    // Read d_size (unsigned int)
2488    read_bytestream((void *)&d->d_size, buf, (int)sizeof(d->d_size));
2489    d->d_size = VC_VTOH32(d->d_size);
2490    buf += 4;
2491
2492    // Read d_attrib (int)
2493    read_bytestream((void *)&d->d_attrib, buf, (int)sizeof(d->d_attrib));
2494    d->d_attrib = VC_VTOH32(d->d_attrib);
2495    buf += 4;
2496
2497    // Read d_modtime (time_t)
2498    read_bytestream((void *)&d->d_modtime, buf, (int)sizeof(d->d_modtime));
2499    d->d_modtime = VC_VTOH32(d->d_modtime);
2500
2501    return;
2502 }
2503
2504
2505
2506 void vc_filesys_sendreset(void)
2507 {
2508    //TODO
2509 }