2 Copyright (c) 2012, Broadcom Europe Ltd
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.
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.
35 #include "interface/vcos/vcos.h"
36 #include "interface/vchi/vchi.h"
37 #include "interface/vchi/common/endian.h"
39 #include "vc_vchi_filesys.h"
40 #include "interface/vmcs_host/vc_vchi_fileservice_defs.h"
42 /******************************************************************************
44 ******************************************************************************/
46 /******************************************************************************
47 Local types and defines.
48 ******************************************************************************/
57 VCHI_SERVICE_HANDLE_T open_handle;
59 int32_t num_connections;
62 FILESERV_MSG_T fileserv_msg;
65 FILESERV_MSG_T vc_msg;
67 VCOS_THREAD_T filesys_thread;
69 // used to signal response has arrived
70 VCOS_EVENT_T response_event;
72 //we lock each vc_filesys function call
73 VCOS_MUTEX_T filesys_lock;
75 //used to signal msg arrivals
76 VCOS_EVENT_T filesys_msg_avail;
78 // Outstanding transaction's ID
79 volatile uint32_t cur_xid;
81 // Copy of the header code from responses
90 static FILESYS_SERVICE_T vc_filesys_client;
93 /******************************************************************************
95 ******************************************************************************/
98 static __inline int32_t lock_obtain (void) {
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);
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);
114 // File Service VCHI functions
116 static int vchi_msg_stub(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len );
118 static int vchi_msg_stub_noblock(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len);
120 static int vc_fs_message_handler( FILESERV_MSG_T* msg, uint32_t nbytes );
122 static void *filesys_task_func(void *arg);
124 static void filesys_callback( void *callback_param, VCHI_CALLBACK_REASON_T reason, void *msg_handle );
130 #define printf tprintf
132 static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
133 struct file_service_msg_body const * body);
135 static int fs_host_direntbytestream_create(struct dirent *d, void *buffer);
136 static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer);
138 /*---------------------------------------------------------------------------*/
140 /******************************************************************************
145 vc_filesys_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) {
148 Initialise the file system for use. A negative return value
149 indicates failure (which may mean it has not been started on VideoCore).
153 ******************************************************************************/
154 int vc_vchi_filesys_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections )
157 SERVICE_CREATION_T filesys_parameters;
158 VCOS_THREAD_ATTR_T attrs;
159 VCOS_STATUS_T status;
161 // record the number of connections
162 memset( &vc_filesys_client, 0, sizeof(FILESYS_SERVICE_T) );
163 vc_filesys_client.num_connections = num_connections;
165 if(!vcos_verify(vc_filesys_client.num_connections < 2))
168 status = vcos_mutex_create(&vc_filesys_client.filesys_lock, "HFilesys");
169 vcos_assert(status == VCOS_SUCCESS);
171 status = vcos_event_create(&vc_filesys_client.filesys_msg_avail, "HFilesys");
172 vcos_assert(status == VCOS_SUCCESS);
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);
178 vc_filesys_client.bulk_buffer = vcos_malloc_aligned(FILESERV_MAX_BULK, 16, "HFilesys bulk_recv");
179 vc_filesys_client.cur_xid = 0;
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;
194 success = vchi_service_open( initialise_instance, &filesys_parameters, &vc_filesys_client.open_handle );
195 vcos_assert( success == 0 );
197 vcos_thread_attr_init(&attrs);
198 vcos_thread_attr_setstacksize(&attrs, 4000);
199 vcos_thread_attr_settimeslice(&attrs, 1);
201 vc_filesys_client.initialised = 1;
203 status = vcos_thread_create(&vc_filesys_client.filesys_thread, "HFilesys", &attrs, filesys_task_func, NULL);
204 vcos_assert(status == VCOS_SUCCESS);
206 /* Not using service immediately - release videocore */
207 vchi_service_release(vc_filesys_client.open_handle);
212 static void *filesys_task_func(void *arg)
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)
226 vchi_service_use(vc_filesys_client.open_handle);
227 // read the message - should we really "peek" this
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);
234 /* coverity[tainted_string_argument] */
235 success = (int32_t) vc_fs_message_handler(&vc_filesys_client.vc_msg, msg_len);
238 vchi_service_release(vc_filesys_client.open_handle);
245 /******************************************************************************
250 void filesys_callback( void *callback_param,
251 const VCHI_CALLBACK_REASON_T reason,
252 const void *msg_handle )
259 ******************************************************************************/
260 static void filesys_callback( void *callback_param,
261 const VCHI_CALLBACK_REASON_T reason,
268 case VCHI_CALLBACK_MSG_AVAILABLE:
270 VCOS_EVENT_T *event = (VCOS_EVENT_T *) callback_param;
272 vcos_event_signal(event);
276 case VCHI_CALLBACK_BULK_RECEIVED:
278 case VCHI_CALLBACK_BULK_SENT:
286 /******************************************************************************
291 void vc_filesys_stop()
294 This tells us that the file system service has stopped, thereby preventing
295 any of the functions from doing anything.
299 ******************************************************************************/
301 void vc_filesys_stop ()
306 if(lock_obtain() != 0)
309 result = vchi_service_close(vc_filesys_client.open_handle);
310 vcos_assert(result == 0);
312 vc_filesys_client.initialised = 0;
314 vcos_event_signal(&vc_filesys_client.filesys_msg_avail);
315 vcos_thread_join(&vc_filesys_client.filesys_thread, &dummy);
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);
321 if(vc_filesys_client.bulk_buffer)
322 vcos_free(vc_filesys_client.bulk_buffer);
325 /******************************************************************************
327 vc_filesys_single_param
330 int vc_filesys_single_param(uint32_t param, uint32_t fn)
333 Utility function for implementing filesys methods
337 ******************************************************************************/
338 static int vc_filesys_single_param(uint32_t param, uint32_t fn)
342 if(lock_obtain() == 0)
344 vc_filesys_client.fileserv_msg.params[0] = param;
345 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, fn, 4) == FILESERV_RESP_OK)
354 /******************************************************************************
356 vc_filesys_single_string
359 int vc_filesys_single_string(uint32_t param, const char *str, uint32_t fn, int return_param)
362 Utility function for implementing filesys methods
366 ******************************************************************************/
367 static int vc_filesys_single_string(uint32_t param, const char *str, uint32_t fn, int return_param)
370 int len = strlen(str);
372 if(len < FILESERV_MAX_DATA && lock_obtain() == 0)
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);
378 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, fn, len+1+16) == FILESERV_RESP_OK)
381 ret = (int) vc_filesys_client.fileserv_msg.params[0];
392 /* Standard UNIX low-level library functions (declared in unistd.h) */
393 /******************************************************************************
398 int vc_filesys_close(int fildes)
401 Deallocates the file descriptor to a file.
404 Successful completion: 0
406 ******************************************************************************/
408 int vc_filesys_close(int fildes)
410 return vc_filesys_single_param((uint32_t) fildes, VC_FILESYS_CLOSE);
414 /******************************************************************************
419 long vc_filesys_lseek(int fildes, long offset, int whence)
422 Sets the file pointer associated with the open file specified by fildes.
425 Successful completion: offset
427 ******************************************************************************/
429 long vc_filesys_lseek(int fildes, long offset, int whence)
433 if(lock_obtain() == 0)
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;
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];
448 /******************************************************************************
453 int64_t vc_filesys_lseek64(int fildes, int64_t offset, int whence)
456 Sets the file pointer associated with the open file specified by fildes.
459 Successful completion: file pointer value
461 ******************************************************************************/
463 int64_t vc_filesys_lseek64(int fildes, int64_t offset, int whence)
467 if(lock_obtain() == 0)
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;
474 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_LSEEK64, 16) == FILESERV_RESP_OK)
476 set = vc_filesys_client.fileserv_msg.params[0];
477 set += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
486 /******************************************************************************
491 int vc_filesys_mount(const char *device, const char *mountpoint, const char *options)
494 Mounts a filesystem at a given location
497 Successful completion: 0
498 ******************************************************************************/
500 int vc_filesys_mount(const char *device, const char *mountpoint, const char *options)
503 int a = strlen(device);
504 int b = strlen(mountpoint);
505 int c = strlen(options);
507 if(a + b + c + 3 < FILESERV_MAX_DATA && lock_obtain() == 0)
509 char *str = (char *) vc_filesys_client.fileserv_msg.data;
511 memcpy(str, device, a);
513 memcpy(str+a+1, mountpoint, b);
515 memcpy(str+a+b+2, options, c);
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;
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];
529 /******************************************************************************
534 int vc_filesys_mount(const char *mountpoint)
537 Un-mounts a removable device from the location that it has been mounted
538 to earlier in the session
541 Successful completion: 0
542 ******************************************************************************/
544 int vc_filesys_umount(const char *mountpoint)
546 return vc_filesys_single_string(0, mountpoint, VC_FILESYS_UMOUNT, 1);
549 /******************************************************************************
554 int vc_filesys_open(const char *path, int vc_oflag)
557 Establishes a connection between a file and a file descriptor.
560 Successful completion: file descriptor
562 ******************************************************************************/
564 int vc_filesys_open(const char *path, int vc_oflag)
566 return vc_filesys_single_string((uint32_t) vc_oflag, path, VC_FILESYS_OPEN, 1);
570 /******************************************************************************
575 int vc_filesys_read(int fildes, void *buf, unsigned int nbyte)
578 Attempts to read nbyte bytes from the file associated with the file
579 descriptor, fildes, into the buffer pointed to by buf.
582 Successful completion: number of bytes read
584 ******************************************************************************/
586 /******************************************************************************
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 )
599 uint32_t host_align_bytes;
600 uint32_t num_bytes_read;
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))
608 //number of bytes required to align recv_addr
609 host_align_bytes = VCHI_BULK_ALIGN_NBYTES(recv_addr);
611 i = vc_filesys_client.cur_xid + 1;
613 vc_filesys_client.cur_xid = i;
615 msg->xid = vc_filesys_client.cur_xid;
617 //fill in cmd id: VC_FILESYS_READ etc
618 msg->cmd_code = cmd_id;
620 msg->params[2] = transfer_len;
622 msg->params[3] = host_align_bytes;
624 //24 comes from the static size of FILESERV_MSG_T
627 if(vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ) != 0)
630 //wait to receive response
631 if(vcos_event_wait(&vc_filesys_client.response_event) != VCOS_SUCCESS || msg->cmd_code == FILESERV_RESP_ERROR)
635 num_bytes_read = msg->params[0];
637 if(!vcos_verify(num_bytes_read <= FILESERV_MAX_BULK))
640 //everything is in msg->data
641 if(msg->cmd_code == FILESERV_RESP_OK) {
642 if(!vcos_verify(num_bytes_read <= FILESERV_MAX_DATA))
645 memcpy(recv_addr, msg->data, num_bytes_read);
646 return (int) num_bytes_read;
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;
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);
666 success = vchi_bulk_queue_receive(vc_filesys_client.open_handle,
669 VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
671 if(!vcos_verify(success == 0))
674 recv_addr+=bulk_bytes;
676 //copy any left over end bytes from original msg
678 memcpy(recv_addr, &msg->data[host_align_bytes], end_bytes);
684 return (int) num_bytes_read;
688 int vc_filesys_read(int fildes, void *buf, unsigned int nbyte)
693 uint8_t* ptr = (uint8_t*)buf;
699 if(lock_obtain() == 0)
702 bulk_bytes = nbyte > FILESERV_MAX_BULK ? FILESERV_MAX_BULK : nbyte;
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
708 actual_read = vc_vchi_msg_bulk_read(&vc_filesys_client.fileserv_msg , VC_FILESYS_READ, (uint32_t)bulk_bytes, (uint8_t*)ptr);
710 if(bulk_bytes != actual_read) {
714 total_byte += actual_read;
720 nbyte -= actual_read;
721 total_byte += actual_read;
730 /******************************************************************************
735 int vc_filesys_write(int fildes, const void *buf, unsigned int nbyte)
738 Attempts to write nbyte bytes from the buffer pointed to by buf to file
739 associated with the file descriptor, fildes.
742 Successful completion: number of bytes written
744 ******************************************************************************/
746 /******************************************************************************
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 )
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;
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))
769 i = vc_filesys_client.cur_xid + 1;
771 vc_filesys_client.cur_xid = i;
773 msg->xid = vc_filesys_client.cur_xid;
775 //fill in cmd id VC_FILESYS_OPEN etc
776 msg->cmd_code = cmd_id;
778 msg->params[2] = transfer_len;
780 //24 comes from the static size of FILESERV_MSG_T
783 //put it all in one msg
784 if(transfer_len <= FILESERV_MAX_DATA) {
785 memcpy(msg->data, send_addr, transfer_len);
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)
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)
796 //vc_fs_message_handler copies resp into outgoing msg struct
797 num_bytes_written = (int)msg->params[0];
801 //required to make send_addr for bulk
802 align_bytes = VCHI_BULK_ALIGN_NBYTES(send_addr);
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
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;
818 // need to ensure we have the appropriate alignment
819 bulk_bytes = (transfer_len)&(~(VCHI_BULK_GRANULARITY-1));
821 bulk_end_bytes = transfer_len-bulk_bytes;
824 memcpy(msg->data+align_bytes, send_addr+bulk_bytes, bulk_end_bytes);
825 msg_len += bulk_end_bytes;
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)
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,
836 VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
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];
845 return num_bytes_written;
849 int vc_filesys_write(int fildes, const void *buf, unsigned int nbyte)
853 int actual_written = 0;
854 uint8_t *ptr = (uint8_t*) buf;
860 if(lock_obtain() == 0)
862 //will split the read into 4K chunks based on vc fwrite buffer size array size
863 //we will make this more dynamic later
865 bulk_bytes = nbyte > FILESERV_MAX_BULK ? FILESERV_MAX_BULK : nbyte;
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
871 actual_written = vc_vchi_msg_bulk_write(&vc_filesys_client.fileserv_msg , VC_FILESYS_WRITE, (uint32_t)bulk_bytes, (uint8_t*)ptr);
873 if(bulk_bytes != actual_written) {
874 if(actual_written < 0)
877 num_wrt += actual_written;
882 nbyte -= actual_written;
883 num_wrt += actual_written;
893 /* Directory management functions */
895 /******************************************************************************
900 int vc_filesys_closedir(void *dhandle)
903 Ends a directory list iteration.
906 Successful completion: 0
908 ******************************************************************************/
910 int vc_filesys_closedir(void *dhandle)
912 return vc_filesys_single_param((uint32_t)dhandle, VC_FILESYS_CLOSEDIR);
916 /******************************************************************************
921 int vc_filesys_format(const char *path)
924 Formats the physical file system that contains path.
927 Successful completion: 0
929 ******************************************************************************/
931 int vc_filesys_format(const char *path)
933 return vc_filesys_single_string(0, path, VC_FILESYS_FORMAT, 0);
937 /******************************************************************************
942 int vc_filesys_freespace(const char *path)
945 Returns the amount of free space on the physical file system that contains
949 Successful completion: free space
951 ******************************************************************************/
953 int vc_filesys_freespace(const char *path)
955 return vc_filesys_single_string(0, path, VC_FILESYS_FREESPACE, 1);
959 /******************************************************************************
961 vc_filesys_freespace64
964 int64_t vc_filesys_freespace64(const char *path)
967 Returns the amount of free space on the physical file system that contains
971 Successful completion: free space
973 ******************************************************************************/
975 int64_t vc_filesys_freespace64(const char *path)
977 int64_t freespace = -1LL;
979 if(lock_obtain() == 0)
981 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
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)
986 freespace = vc_filesys_client.fileserv_msg.params[0];
987 freespace += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
997 /******************************************************************************
1002 int vc_filesys_get_attr(const char *path, fattributes_t *attr)
1005 Gets the file/directory attributes.
1008 Successful completion: 0
1010 ******************************************************************************/
1012 int vc_filesys_get_attr(const char *path, fattributes_t *attr)
1016 if(lock_obtain() == 0)
1018 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
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)
1024 *attr = (fattributes_t) vc_filesys_client.fileserv_msg.params[0];
1034 /******************************************************************************
1039 int64_t vc_filesys_fstat(int fildes, FSTAT_T *buf)
1042 Returns the file stat info structure for the specified file.
1043 This structure includes date and size info.
1046 Successful completion: 0
1048 ******************************************************************************/
1050 int vc_filesys_fstat(int fildes, FSTAT_T *buf)
1054 if (buf != NULL && lock_obtain() == 0)
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 )
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...
1073 /******************************************************************************
1078 int vc_filesys_mkdir(const char *path)
1081 Creates a new directory named by the pathname pointed to by path.
1084 Successful completion: 0
1086 ******************************************************************************/
1088 int vc_filesys_mkdir(const char *path)
1090 return vc_filesys_single_string(0, path, VC_FILESYS_MKDIR, 0);
1094 /******************************************************************************
1099 void *vc_filesys_opendir(const char *dirname)
1102 Starts a directory list iteration.
1105 Successful completion: dhandle (pointer)
1107 ******************************************************************************/
1109 void *vc_filesys_opendir(const char *dirname)
1111 return (void *) vc_filesys_single_string(0, dirname, VC_FILESYS_OPENDIR, 1);
1115 /******************************************************************************
1120 int vc_filesys_dirsize(const char *path)
1123 Look through the specified directory tree and sum the file sizes.
1126 Successful completion: 0
1128 ******************************************************************************/
1130 int64_t vc_filesys_dirsize(const char *path, uint32_t *num_files, uint32_t *num_dirs)
1134 if(lock_obtain() == 0)
1136 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
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,
1142 (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK )
1144 ret = vc_filesys_client.fileserv_msg.params[0];
1145 ret += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
1147 *num_files = vc_filesys_client.fileserv_msg.params[2];
1149 *num_dirs = vc_filesys_client.fileserv_msg.params[3];
1159 /******************************************************************************
1161 vc_filesys_readdir_r
1164 struct dirent *vc_filesys_readdir_r(void *dhandle, struct dirent *result)
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.
1172 Successful completion: result
1173 End of directory stream: NULL
1174 ******************************************************************************/
1176 struct dirent *vc_filesys_readdir_r(void *dhandle, struct dirent *result)
1178 struct dirent *ret = NULL;
1180 if(lock_obtain() == 0)
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)
1185 fs_host_direntbytestream_interp(result, (void *)vc_filesys_client.fileserv_msg.data);
1196 /******************************************************************************
1201 int vc_filesys_remove(const char *path)
1204 Removes a file or a directory. A directory must be empty before it can be
1208 Successful completion: 0
1210 ******************************************************************************/
1212 int vc_filesys_remove(const char *path)
1214 return vc_filesys_single_string(0, path, VC_FILESYS_REMOVE, 0);
1218 /******************************************************************************
1223 int vc_filesys_rename(const char *oldfile, const char *newfile)
1226 Changes the name of a file. The old and new pathnames must be on the same
1227 physical file system.
1230 Successful completion: 0
1232 ******************************************************************************/
1234 int vc_filesys_rename(const char *oldfile, const char *newfile)
1236 int a, b, success = -1;
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)
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);
1244 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_RENAME, 16+a+1+b+1) == FILESERV_RESP_OK)
1254 /******************************************************************************
1259 int vc_filesys_reset()
1262 Send a vc_FILESYS_RESET command. This will return immediately.
1265 Successful completion: FILESERV_RESP_OK
1267 ******************************************************************************/
1269 int vc_filesys_reset()
1271 return vc_filesys_single_param(0, VC_FILESYS_RESET);
1275 /******************************************************************************
1280 int vc_filesys_set_attr(const char *path, fattributes_t attr)
1283 Sets file/directory attributes.
1286 Successful completion: 0
1288 ******************************************************************************/
1290 int vc_filesys_set_attr(const char *path, fattributes_t attr)
1292 return vc_filesys_single_string((uint32_t) attr, path, VC_FILESYS_SET_ATTR, 0);
1296 /******************************************************************************
1301 int vc_filesys_setend(int fildes)
1304 Truncates file at current position.
1307 Successful completion: 0
1309 ******************************************************************************/
1311 int vc_filesys_setend(int fildes)
1313 return vc_filesys_single_param((uint32_t) fildes, VC_FILESYS_SETEND);
1318 /******************************************************************************
1323 void vc_filesys_scandisk(const char *path)
1326 Truncates file at current position.
1330 ******************************************************************************/
1332 void vc_filesys_scandisk(const char *path)
1334 vc_filesys_single_string(0, path, VC_FILESYS_SCANDISK, 0);
1338 /******************************************************************************
1343 int vc_filesys_chkdsk(const char *path, int fix_errors)
1346 Truncates file at current position.
1350 ******************************************************************************/
1352 int vc_filesys_chkdsk(const char *path, int fix_errors)
1354 return vc_filesys_single_string(fix_errors, path, VC_FILESYS_CHKDSK, 1);
1357 /******************************************************************************
1362 int vc_filesys_size(const char *path)
1369 ******************************************************************************/
1371 int vc_filesys_size(const char *path)
1376 if((fd = vc_filesys_open(path, VC_O_RDONLY)) == 0)
1378 end_pos = vc_filesys_lseek(fd, 0, SEEK_END);
1379 success = vc_filesys_close(fd);
1385 /******************************************************************************
1387 vc_filesys_totalspace
1390 int vc_filesys_totalspace(const char *path)
1393 Returns the total amount of space on the physical file system that contains
1397 Successful completion: total space
1399 ******************************************************************************/
1401 int vc_filesys_totalspace(const char *path)
1403 return vc_filesys_single_string(0, path, VC_FILESYS_TOTALSPACE, 1);
1407 /******************************************************************************
1409 vc_filesys_totalspace64
1412 int64_t vc_filesys_totalspace64(const char *path)
1415 Returns the total amount of space on the physical file system that contains
1419 Successful completion: total space
1421 ******************************************************************************/
1423 int64_t vc_filesys_totalspace64(const char *path)
1425 int64_t totalspace = -1LL;
1427 if(lock_obtain() == 0)
1429 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
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)
1434 totalspace = vc_filesys_client.fileserv_msg.params[0];
1435 totalspace += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
1445 /******************************************************************************
1447 vc_filesys_diskwritable
1450 int vc_filesys_diskwritable(const char *path)
1453 Return whether the named disk is writable.
1456 Successful completion: 1 (disk writable) or 0 (disk not writable)
1458 ******************************************************************************/
1460 int vc_filesys_diskwritable(const char *path)
1462 return vc_filesys_single_string(0, path, VC_FILESYS_DISKWRITABLE, 1);
1465 /******************************************************************************
1470 int vc_filesys_fstype(const char *path)
1473 Return the filesystem type of the named disk.
1476 Successful completion: disk type (see vc_fileservice_defs.h)
1478 ******************************************************************************/
1480 int vc_filesys_fstype(const char *path)
1482 return vc_filesys_single_string(0, path, VC_FILESYS_FSTYPE, 1);
1485 /******************************************************************************
1487 vc_filesys_open_disk_raw
1490 int vc_filesys_open_disk_raw(const char *path)
1493 Open disk for access in raw mode.
1496 Successful completion: 0
1498 ******************************************************************************/
1500 int vc_filesys_open_disk_raw(const char *path)
1502 return vc_filesys_single_string(0, path, VC_FILESYS_OPEN_DISK_RAW, 1);
1505 /******************************************************************************
1507 vc_filesys_close_disk_raw
1510 int vc_filesys_close_disk_raw(const char *path)
1513 Close disk from access in raw mode.
1516 Successful completion: 0
1518 ******************************************************************************/
1520 int vc_filesys_close_disk_raw(const char *path)
1522 return vc_filesys_single_string(0, path, VC_FILESYS_CLOSE_DISK_RAW, 1);
1526 /******************************************************************************
1528 vc_filesys_open_disk
1531 int vc_filesys_open_disk(const char *path)
1534 Open disk for normal access.
1537 Successful completion: 0
1539 ******************************************************************************/
1541 int vc_filesys_open_disk(const char *path)
1543 return vc_filesys_single_string(0, path, VC_FILESYS_OPEN_DISK, 1);
1546 /******************************************************************************
1548 vc_filesys_close_disk
1551 int vc_filesys_close_disk(const char *path)
1554 Close disk from normal access.
1557 Successful completion: 0
1559 ******************************************************************************/
1561 int vc_filesys_close_disk(const char *path)
1563 return vc_filesys_single_string(0, path, VC_FILESYS_CLOSE_DISK, 1);
1566 /******************************************************************************
1568 vc_filesys_numsectors
1571 int vc_filesys_numsectors(const char *path)
1574 Return number of sectors on disk
1577 Successful completion: greater than 0
1579 ******************************************************************************/
1581 int vc_filesys_numsectors(const char *path)
1583 return vc_filesys_single_string(0, path, VC_FILESYS_NUMSECTORS, 1);
1586 /******************************************************************************
1588 vc_filesys_read_sectors
1591 int vc_filesys_read_sectors(const char *path, uint32_t sector_num, char *buffer, uint32_t num_sectors)
1594 Start streaming sectors from 2727
1597 Successful completion: 0
1599 ******************************************************************************/
1600 int vc_filesys_read_sectors(const char *path, uint32_t sector_num, char *sectors, uint32_t num_sectors, uint32_t *sectors_read)
1602 #if VCHI_BULK_ALIGN > 1
1603 uint32_t align_bytes = 0;
1605 char* bulk_addr = sectors;
1609 if((len = (int)strlen(path)) < FS_MAX_PATH && lock_obtain() == 0)
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;
1615 #if VCHI_BULK_ALIGN > 1
1616 //required to make buffer aligned for bulk
1617 align_bytes = VCHI_BULK_ALIGN_NBYTES(sectors);
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;
1622 //we send read request
1623 if (vchi_msg_stub_noblock(&vc_filesys_client.fileserv_msg, VC_FILESYS_READ_SECTORS, 16+len+1) == 0)
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,
1634 (bulk_sectors*FILESERV_SECTOR_LENGTH), VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL) != 0)
1637 #if VCHI_BULK_ALIGN > 1
1639 //this is bad but will do for now..
1640 memcpy( bulk_addr, vc_filesys_client.bulk_buffer, (bulk_sectors*FILESERV_SECTOR_LENGTH));
1643 bulk_addr += (bulk_sectors*FILESERV_SECTOR_LENGTH);
1644 num_sectors -= bulk_sectors;
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)
1650 *sectors_read = vc_filesys_client.fileserv_msg.params[0];
1656 *sectors_read = vc_filesys_client.fileserv_msg.params[1];
1657 ret = vc_filesys_client.fileserv_msg.params[0];
1667 /******************************************************************************
1669 vc_filesys_write_sectors
1672 int vc_filesys_write_sectors(const char *path, uint32_t sector_num, char *sectors, uint32_t num_sectors, uint32_t *sectors_written)
1675 Start streaming sectors to 2727
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)
1683 uint32_t align_bytes = 0;
1684 char* bulk_addr = sectors;
1688 len = (int) strlen(path);
1689 if((len = (int) strlen(path)) < FS_MAX_PATH && lock_obtain() == 0)
1691 vc_filesys_client.fileserv_msg.params[0] = sector_num;
1692 vc_filesys_client.fileserv_msg.params[1] = num_sectors;
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;
1698 //copy path at end of any alignbytes
1699 strncpy(((char *)vc_filesys_client.fileserv_msg.data), path, FS_MAX_PATH);
1701 //we send write request
1702 if (vchi_msg_stub_noblock(&vc_filesys_client.fileserv_msg, VC_FILESYS_WRITE_SECTORS, 16+len+1) == 0)
1705 //note we are cheating and going backward to make addr aligned and sending more data...
1706 bulk_addr -= align_bytes;
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)
1717 //go to next ALIGNED address
1718 bulk_addr += FILESERV_MAX_BULK;
1719 num_sectors -= bulk_sectors;
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)
1725 *sectors_written = vc_filesys_client.fileserv_msg.params[0];
1731 *sectors_written = vc_filesys_client.fileserv_msg.params[1];
1732 ret = vc_filesys_client.fileserv_msg.params[0];
1742 /******************************************************************************
1747 int vc_filesys_errno(void)
1750 Returns the error code of the last file system error that occurred.
1754 ******************************************************************************/
1756 int vc_filesys_errno(void)
1758 return (int) vc_filesys_client.err_no;
1762 /* File Service Message FIFO functions */
1764 /******************************************************************************
1769 static int vc_fs_stub(int verb, int ext_len)
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
1777 Successful completion: Response code of reply
1779 ******************************************************************************/
1780 static int vchi_msg_stub(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len )
1783 vchi_msg_stub_noblock(msg, cmd_id, msg_len);
1785 // wait to receive response
1786 if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS)
1787 ret = (int) msg->cmd_code;
1792 static int vchi_msg_stub_noblock(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len)
1796 if(!vcos_verify(msg_len <= VCHI_MAX_MSG_SIZE))
1799 //will get changed by response from command
1800 vc_filesys_client.resp_code = FILESERV_RESP_ERROR;
1802 //the top bit is used for host/vc
1803 i = vc_filesys_client.cur_xid + 1;
1805 vc_filesys_client.cur_xid = i;
1807 //fill in transaction id, used for response identification
1808 vchi_writebuf_uint32( &(msg->xid), vc_filesys_client.cur_xid );
1810 //fill in cmd id VC_FILESYS_OPEN etc
1811 vchi_writebuf_uint32( &(msg->cmd_code), cmd_id );
1813 //we always have cmd_id, xid
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 );
1820 static int vc_send_response( FILESERV_MSG_T* msg, uint32_t retval, uint32_t nbytes )
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]);
1831 //start with 8 because always xid and retval
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 );
1840 /******************************************************************************
1842 vc_fs_message_handler
1845 static int vc_fs_message_handler()
1848 Handle messages from the co-processor.
1851 0 - No message found.
1852 1 - Request received and actioned.
1854 ******************************************************************************/
1856 static int vc_fs_message_handler( FILESERV_MSG_T* msg, uint32_t nbytes )
1859 uint32_t xid = vchi_readbuf_uint32(&msg->xid);
1861 if (xid == vc_filesys_client.cur_xid) {
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]);
1871 //copy any data, 24 is size of header
1873 memcpy(&vc_filesys_client.fileserv_msg.data, msg->data, (nbytes-24));
1875 vc_filesys_client.resp_code = (int32_t)vc_filesys_client.fileserv_msg.cmd_code;
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];
1881 // signal vchi_msg_stub which will be waiting for response
1882 vcos_event_signal(&vc_filesys_client.response_event);
1886 else if ((xid & 0x80000000UL) == 0x80000000UL) {
1887 /* Process new requests from the co-processor */
1889 uint32_t retval = FILESERV_RESP_OK;
1891 //this is the number of uint32_t param[] + data that we send back to VC in bytes
1896 switch (msg->cmd_code) {
1898 case VC_FILESYS_CLOSE:
1900 i = vc_hostfs_close((int)msg->params[0]);
1902 retval = FILESERV_RESP_ERROR;
1907 case VC_FILESYS_CLOSEDIR:
1909 i = vc_hostfs_closedir((void *)msg->params[0]);
1911 retval = FILESERV_RESP_ERROR;
1916 case VC_FILESYS_FORMAT:
1918 i = vc_hostfs_format((const char *)msg->data);
1920 retval = FILESERV_RESP_ERROR;
1925 case VC_FILESYS_FREESPACE:
1927 i = vc_hostfs_freespace((const char *)msg->data);
1929 retval = FILESERV_RESP_ERROR;
1932 msg->params[0] = (uint32_t)i;
1937 case VC_FILESYS_FREESPACE64:
1940 freespace = vc_hostfs_freespace64((const char *)msg->data);
1941 if (freespace < (int64_t)0) {
1942 retval = FILESERV_RESP_ERROR;
1945 msg->params[0] = (uint32_t)freespace;
1946 msg->params[1] = (uint32_t)(freespace>>32);
1952 case VC_FILESYS_GET_ATTR:
1956 i = vc_hostfs_get_attr((const char *)msg->data,
1959 retval = FILESERV_RESP_ERROR;
1962 msg->params[0] = (uint32_t) attr;
1967 case VC_FILESYS_LSEEK:
1969 i = vc_hostfs_lseek( (int)msg->params[0],
1970 (int)msg->params[1],
1971 (int)msg->params[2]);
1973 retval = FILESERV_RESP_ERROR;
1976 msg->params[0] = (uint32_t) i;
1981 case VC_FILESYS_LSEEK64:
1984 offset = (((int64_t) msg->params[2]) << 32) + msg->params[1];
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;
1991 msg->params[0] = (uint32_t)offset;
1992 msg->params[1] = (uint32_t)(offset>>32);
1998 case VC_FILESYS_MKDIR:
2000 i = vc_hostfs_mkdir((const char *)msg->data);
2002 retval = FILESERV_RESP_ERROR;
2007 case VC_FILESYS_OPEN:
2009 i = vc_hostfs_open((const char *)msg->data,
2010 (int) msg->params[0]);
2012 retval = FILESERV_RESP_ERROR;
2014 msg->params[0] = (uint32_t) i;
2019 case VC_FILESYS_OPENDIR:
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;
2029 case VC_FILESYS_READ:
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];
2038 if(!vcos_verify(((int)vc_filesys_client.bulk_buffer & (VCHI_BULK_ALIGN-1)) == 0 &&
2039 total_bytes <= FILESERV_MAX_BULK))
2041 retval = FILESERV_RESP_ERROR;
2048 //perform any seeking
2049 if ( (uint32_t)0xffffffffUL != offset)
2051 i = vc_hostfs_lseek( (int)fd,
2053 VC_FILESYS_SEEK_SET);
2056 retval = FILESERV_RESP_ERROR;
2063 //put it all in one msg
2064 if(total_bytes <= FILESERV_MAX_DATA) {
2065 i = vc_hostfs_read( (int)fd,
2067 (unsigned int) total_bytes);
2070 retval = FILESERV_RESP_ERROR;
2074 retval = FILESERV_RESP_OK;
2075 //send back length of read
2076 msg->params[0] = (uint32_t) i;
2080 rlen = 16 + (uint32_t) i;
2082 //bulk transfer required
2084 uint32_t end_bytes = 0;
2085 retval = FILESERV_BULK_WRITE;
2087 //we send the bytes required for HOST buffer align
2089 i = vc_hostfs_read( (int)fd,
2091 (unsigned int)nalign_bytes);
2093 retval = FILESERV_RESP_ERROR;
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;
2102 rlen = 16 + (uint32_t) i;
2108 rlen += (uint32_t) i;
2112 i = vc_hostfs_read((int)fd, vc_filesys_client.bulk_buffer, (unsigned int)total_bytes);
2115 retval = FILESERV_RESP_ERROR;
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);
2123 msg->params[0] = (i + nalign_bytes);
2125 rlen = i + nalign_bytes + 16;
2129 //copy end unaligned length bytes into msg->data
2130 end_bytes = (uint32_t) (i & (VCHI_BULK_GRANULARITY-1));
2132 int end_index = i - (int) end_bytes;
2133 memcpy(&msg->data[nalign_bytes], &vc_filesys_client.bulk_buffer[end_index], end_bytes);
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);
2146 //queue bulk to be sent
2147 if(vchi_bulk_queue_transmit( vc_filesys_client.open_handle,
2148 vc_filesys_client.bulk_buffer,
2150 VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
2153 retval = FILESERV_RESP_ERROR;
2162 case VC_FILESYS_READDIR:
2164 struct dirent result;
2165 if (vc_hostfs_readdir_r((void *)msg->params[0],
2167 retval = FILESERV_RESP_ERROR;
2170 rlen = (uint32_t) (16+fs_host_direntbytestream_create(&result,
2171 (void *)msg->data));
2176 case VC_FILESYS_REMOVE:
2178 i = vc_hostfs_remove((const char *)msg->data);
2180 retval = FILESERV_RESP_ERROR;
2185 case VC_FILESYS_RENAME:
2187 i = (int) strlen((char *)msg->data);
2188 if (vc_hostfs_rename((const char *)msg->data,
2189 (const char *)&msg->data[i+1])
2191 retval = FILESERV_RESP_ERROR;
2196 case VC_FILESYS_SETEND:
2198 i = vc_hostfs_setend( (int)msg->params[0] );
2200 retval = FILESERV_RESP_ERROR;
2205 case VC_FILESYS_SET_ATTR:
2207 i = vc_hostfs_set_attr((const char *)msg->data,
2208 (fattributes_t)msg->params[0]);
2210 retval = FILESERV_RESP_ERROR;
2215 case VC_FILESYS_TOTALSPACE:
2217 i = vc_hostfs_totalspace((const char *)msg->data);
2219 retval = FILESERV_RESP_ERROR;
2222 msg->params[0] = (uint32_t) i;
2227 case VC_FILESYS_TOTALSPACE64:
2230 totalspace = vc_hostfs_totalspace64((const char *)msg->data);
2231 if (totalspace < (int64_t)0) {
2232 retval = FILESERV_RESP_ERROR;
2235 msg->params[0] = (uint32_t)totalspace;
2236 msg->params[1] = (uint32_t)(totalspace>>32);
2241 #if 0 // I don't think host systems are ready for these yet
2242 case VC_FILESYS_SCANDISK:
2244 vc_hostfs_scandisk((const char *)msg->data);
2248 case VC_FILESYS_CHKDSK:
2250 i = vc_hostfs_chkdsk((const char *)msg->data, msg->params[0]);
2252 retval = FILESERV_RESP_ERROR;
2255 msg->params[0] = (uint32_t)i;
2260 case VC_FILESYS_WRITE:
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;
2269 //everything in one msg
2270 if(total_bytes <= FILESERV_MAX_DATA)
2272 i = vc_hostfs_write( (int)fd,
2274 (unsigned int) total_bytes);
2276 retval = FILESERV_RESP_ERROR;
2278 msg->params[0] = (uint32_t) i;
2287 uint32_t bulk_bytes;
2288 uint32_t total_bytes_written = 0;
2292 retval = FILESERV_BULK_READ;
2294 //write bytes required for VC buffer align
2296 i = vc_hostfs_write( (int)fd,
2298 (unsigned int)nalign_bytes);
2300 retval = FILESERV_RESP_ERROR;
2302 //break from switch and send reply
2305 total_bytes_written += i;
2306 total_bytes -= nalign_bytes;
2309 //calculate bytes that wil lbe sent by bulk
2310 bulk_bytes = (uint32_t)((total_bytes)&(~(VCHI_BULK_ALIGN-1)));
2312 end_bytes = total_bytes-bulk_bytes;
2316 if(vchi_bulk_queue_receive(vc_filesys_client.open_handle,
2317 vc_filesys_client.bulk_buffer,
2319 VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
2321 (i = vc_hostfs_write( (int)fd,
2322 vc_filesys_client.bulk_buffer,
2323 (unsigned int) bulk_bytes)) < 0)
2325 retval = FILESERV_RESP_ERROR;
2330 total_bytes_written += i;
2333 i = vc_hostfs_write( (int)fd,
2334 msg->data+nalign_bytes,
2335 (unsigned int)end_bytes);
2337 total_bytes_written += i;
2341 retval = FILESERV_RESP_ERROR;
2346 msg->params[0] = total_bytes_written;
2354 retval = FILESERV_RESP_ERROR;
2358 //convert all to over the wire values and send
2359 vc_send_response( msg, retval, rlen );
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
2373 /******************************************************************************
2378 static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
2379 struct file_service_msg_body const * body)
2382 De-bug tool: prints out fifo message.
2386 ******************************************************************************/
2389 static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
2390 struct file_service_msg_body const * body)
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);
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);
2407 /******************************************************************************
2409 fs_host_direntbytestream_create
2412 static int fs_host_direntbytestream_create(struct dirent *d, void *buffer)
2415 Turns a variable of type struct dirent into a compiler independent byte
2416 stream, which is stored in buffer.
2419 Successful completion: The length of the byte stream
2421 ******************************************************************************/
2422 static void write_bytestream(void *a, char *b, int n)
2426 b[i] = ((char *)a)[i];
2433 static int fs_host_direntbytestream_create(struct dirent *d, void *buffer)
2435 char *buf = (char*)buffer;
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;
2441 // Write d_size (unsigned int)
2442 write_bytestream((void *)&d->d_size, buf, (int)sizeof(d->d_size));
2445 // Write d_attrib (int)
2446 write_bytestream((void *)&d->d_attrib, buf, (int)sizeof(d->d_attrib));
2449 // Write d_modtime (time_t)
2450 write_bytestream((void *)&d->d_modtime, buf, (int)sizeof(d->d_modtime));
2453 return (int)(buf-(char *)buffer);
2457 /******************************************************************************
2459 fs_host_direntbytestream_interp
2462 static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer)
2465 Turns a compiler independent byte stream back into a struct of type dirent.
2468 Successful completion: 0
2470 ******************************************************************************/
2471 static void read_bytestream(void *a, char *b, int n)
2475 ((char *)a)[i] = b[i];
2479 static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer)
2481 char *buf = (char*)buffer;
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;
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);
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);
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);
2506 void vc_filesys_sendreset(void)