1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
/*
* blkio/read.c
*
* Copyright (C) 1998 Russell King
*
* The block I/O interface allows an OS-independent method to access devices
*
* Read data from device on RiscOS architecture
*/
#include <errno.h>
#include "util/debug.h"
#include "util/error.h"
#include "blkio.h"
#include "filecore.h"
#ifdef RISCOS
#include "!Swi.h"
static u_int read_block(blkio_t *blkio, void *data, blk_t block, u_int nr_blocks)
{
_kernel_oserror *ret;
u_int swino, sector, nr, limit, res = 0;
const char *what, *swiname;
if (blkio->swi_sectorop) {
swino = blkio->swi_sectorop;
sector = block * (blkio->blocksize >> blkio->disc_record->d.log2secsize);
nr = nr_blocks * blkio->blocksize;
limit = 0x20000000;
what = "sectoraddr";
swiname = "sectorop";
} else {
swino = blkio->swi_discop;
sector = block * blkio->blocksize;
nr = nr_blocks * blkio->blocksize;
limit = 0x20000000 / blkio->blocksize;
what = "discaddr";
swiname = "discop";
}
do {
if (block + nr >= limit) {
set_error("Unable to access block 0x%X above limit 0x%X", what, block, limit);
break;
}
dbg_printf("-%s: [r1=0x%X r2=0x%X r3=%p r4=0x%X]", swiname,
(((unsigned int)blkio->disc_record) << 6)|1,
(blkio->drive << 29) | (sector & 0x1fffffff), data, nr);
ret = swix(swino, rin(r1|r2|r3|r4), (((unsigned int)blkio->disc_record) << 6)|1,
(blkio->drive << 29) | (sector & 0x1fffffff), data, nr);
if (ret) {
set_error("%s", ret->errmess);
break;
}
res = nr_blocks;
} while (0);
return res;
}
#endif
#ifdef UNIX
#include <unistd.h>
#include <syscall.h>
#if _FILE_OFFSET_BITS == 64
#define my_llseek lseek
#else
#undef SYS__llseek
#define SYS__llseek (__NR__llseek - __NR_SYSCALL_BASE)
static inline
_syscall5(int,_llseek,int,fd,u_int,off_high,u_int,off_low,loff_t *,loff,int,whence);
static loff_t my_llseek(int fd, loff_t off, int whence)
{
u_int off_high, off_low;
off_high = off >> 32;
off_low = off & 0xffffffff;
_llseek(fd, off_high, off_low, &off, whence);
return off;
}
#endif
static u_int read_block(blkio_t *blkio, void *data, blk_t block, u_int nr_blocks)
{
u_int len, res = 0;
loff_t loff;
loff = (loff_t)block * blkio->blocksize;
len = nr_blocks * blkio->blocksize;
do {
if (my_llseek(blkio->fd, loff, SEEK_SET) != loff)
break;
if (read(blkio->fd, data, len) != len)
break;
res = nr_blocks;
} while (0);
return res;
}
#endif
/* Function: u_int blkio_read (blkio_t *blkio, void *data, blk_t block, u_int nr_blocks)
* Purpose : Read `nr_blocks' blocks starting at `block' from the device previously opened
* with blkio_open into memory area `data'
* Params : blkio - structure returned by blkio_open
* : data - memory area to read into
* : block - block number to read
* : nr_blocks - number of blocks to read
* Returns : number of blocks actually read
*/
u_int blkio_read (blkio_t *blkio, void *data, blk_t block, u_int nr_blocks)
{
u_int res;
dbg_printf("blkio_read(%p 0x%X +0x%X)", data, block, nr_blocks);
dbg_level_up();
dbg_printf("-blocksize=0x%X", blkio->blocksize);
res = read_block(blkio, data, block, nr_blocks);
dbg_level_down();
dbg_printf("ret=%d", res);
return res;
}
|