| /* |
| * Creation Date: <2003/12/07 19:36:00 samuel> |
| * Time-stamp: <2004/01/07 19:28:43 samuel> |
| * |
| * <diskio.c> |
| * |
| * I/O wrappers |
| * |
| * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * version 2 |
| * |
| */ |
| |
| #include "config.h" |
| #include "libopenbios/bindings.h" |
| #include "libc/diskio.h" |
| |
| //#define CONFIG_DEBUG_DISKIO |
| #ifdef CONFIG_DEBUG_DISKIO |
| #define DPRINTF(fmt, args...) \ |
| do { printk(fmt , ##args); } while (0) |
| #else |
| #define DPRINTF(fmt, args...) |
| #endif |
| |
| typedef struct { |
| ihandle_t ih; |
| int do_close; |
| xt_t read_xt; |
| xt_t seek_xt; |
| |
| xt_t reopen_xt; |
| xt_t tell_xt; |
| xt_t get_path_xt; |
| xt_t get_fstype_xt; |
| xt_t open_nwrom_xt; |
| xt_t volume_name_xt; |
| } priv_fd_t; |
| |
| #define MAX_FD 32 |
| static priv_fd_t *file_descriptors[MAX_FD]; |
| |
| static int |
| lookup_xt( ihandle_t ih, const char *method, xt_t *xt ) |
| { |
| if( *xt ) |
| return 0; |
| *xt = find_ih_method( method, ih ); |
| return (*xt) ? 0:1; |
| } |
| |
| int |
| open_ih( ihandle_t ih ) |
| { |
| xt_t read_xt=0, seek_xt=0; |
| priv_fd_t *fdp; |
| int fd; |
| |
| if( !ih || lookup_xt(ih, "read", &read_xt) ) |
| return -1; |
| if( lookup_xt(ih, "seek", &seek_xt) ) |
| return -1; |
| |
| for (fd=0; fd<MAX_FD; fd++) |
| if(file_descriptors[fd]==NULL) |
| break; |
| if(fd==MAX_FD) |
| return -1; |
| |
| fdp = malloc( sizeof(*fdp) ); |
| /* Better clear the fd, as it |
| * contains valuable information |
| */ |
| memset(fdp, 0, sizeof(*fdp)); |
| fdp->ih = ih; |
| fdp->read_xt = read_xt; |
| fdp->seek_xt = seek_xt; |
| fdp->do_close = 0; |
| |
| file_descriptors[fd]=fdp; |
| DPRINTF("%s(0x%lx) = %d\n", __func__, (unsigned long)ih, fd); |
| return fd; |
| } |
| |
| int |
| open_io( const char *spec ) |
| { |
| int fd; |
| ihandle_t ih = open_dev( spec ); |
| priv_fd_t *fdp; |
| |
| DPRINTF("%s(%s)\n", __func__, spec); |
| if( !ih ) |
| return -1; |
| |
| if( (fd=open_ih(ih)) == -1 ) { |
| close_dev( ih ); |
| return -1; |
| } |
| |
| fdp = file_descriptors[fd]; |
| fdp->do_close = 1; |
| |
| return fd; |
| } |
| |
| int |
| reopen( int fd, const char *filename ) |
| { |
| priv_fd_t *fdp = file_descriptors[fd]; |
| int ret; |
| |
| if( lookup_xt(fdp->ih, "reopen", &fdp->reopen_xt) ) |
| return -1; |
| |
| push_str( filename ); |
| call_package( fdp->reopen_xt, fdp->ih ); |
| ret = (POP() == (ucell)-1)? 0 : -1; |
| |
| DPRINTF("%s(%d, %s) = %d\n", __func__, fd, filename, ret); |
| return ret; |
| } |
| |
| int |
| reopen_nwrom( int fd ) |
| { |
| priv_fd_t *fdp = file_descriptors[fd]; |
| |
| DPRINTF("%s(%d)\n", __func__, fd); |
| if( lookup_xt(fdp->ih, "open-nwrom", &fdp->open_nwrom_xt) ) |
| return -1; |
| call_package( fdp->open_nwrom_xt, fdp->ih ); |
| return (POP() == (ucell)-1)? 0 : -1; |
| } |
| |
| ihandle_t |
| get_ih_from_fd( int fd ) |
| { |
| priv_fd_t *fdp = file_descriptors[fd]; |
| return fdp->ih; |
| } |
| |
| const char * |
| get_file_path( int fd ) |
| { |
| priv_fd_t *fdp = file_descriptors[fd]; |
| if( lookup_xt(fdp->ih, "get-path", &fdp->get_path_xt) ) |
| return NULL; |
| call_package( fdp->get_path_xt, fdp->ih ); |
| return (char*)cell2pointer(POP()); |
| } |
| |
| const char * |
| get_volume_name( int fd ) |
| { |
| priv_fd_t *fdp = file_descriptors[fd]; |
| if( lookup_xt(fdp->ih, "volume-name", &fdp->volume_name_xt) ) |
| return NULL; |
| call_package( fdp->volume_name_xt, fdp->ih ); |
| return (char*)cell2pointer(POP()); |
| } |
| |
| const char * |
| get_fstype( int fd ) |
| { |
| priv_fd_t *fdp = file_descriptors[fd]; |
| if( lookup_xt(fdp->ih, "get-fstype", &fdp->get_fstype_xt) ) |
| return NULL; |
| call_package( fdp->get_fstype_xt, fdp->ih ); |
| return (char*)cell2pointer(POP()); |
| } |
| |
| int |
| read_io( int fd, void *buf, size_t cnt ) |
| { |
| priv_fd_t *fdp; |
| ucell ret; |
| |
| DPRINTF("%s(%d, %p, %u)\n", __func__, fd, buf, cnt); |
| if (fd != -1) { |
| fdp = file_descriptors[fd]; |
| |
| PUSH( pointer2cell(buf) ); |
| PUSH( cnt ); |
| call_package( fdp->read_xt, fdp->ih ); |
| ret = POP(); |
| |
| if( !ret && cnt ) |
| ret = -1; |
| } else { |
| ret = -1; |
| } |
| |
| return ret; |
| } |
| |
| int |
| seek_io( int fd, long long offs ) |
| { |
| priv_fd_t *fdp; |
| |
| DPRINTF("%s(%d, %lld)\n", __func__, fd, offs); |
| if (fd != -1) { |
| fdp = file_descriptors[fd]; |
| |
| DPUSH( offs ); |
| call_package( fdp->seek_xt, fdp->ih ); |
| return ((((cell)POP()) >= 0)? 0 : -1); |
| } else { |
| return -1; |
| } |
| } |
| |
| long long |
| tell( int fd ) |
| { |
| priv_fd_t *fdp = file_descriptors[fd]; |
| long long offs; |
| |
| if( lookup_xt(fdp->ih, "tell", &fdp->tell_xt) ) |
| return -1; |
| call_package( fdp->tell_xt, fdp->ih ); |
| offs = DPOP(); |
| DPRINTF("%s(%d) = %lld\n", __func__, fd, offs); |
| return offs; |
| } |
| |
| int |
| close_io( int fd ) |
| { |
| priv_fd_t *fdp; |
| |
| DPRINTF("%s(%d)\n", __func__, fd); |
| if (fd != -1) { |
| fdp = file_descriptors[fd]; |
| |
| if( fdp->do_close ) |
| close_dev( fdp->ih ); |
| free( fdp ); |
| |
| file_descriptors[fd]=NULL; |
| } |
| |
| return 0; |
| } |