diff options
Diffstat (limited to 'qemu/roms/openbios/libc/diskio.c')
-rw-r--r-- | qemu/roms/openbios/libc/diskio.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/qemu/roms/openbios/libc/diskio.c b/qemu/roms/openbios/libc/diskio.c new file mode 100644 index 000000000..23f38ebb2 --- /dev/null +++ b/qemu/roms/openbios/libc/diskio.c @@ -0,0 +1,248 @@ +/* + * 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; +} |