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
|
/*
* blkio/read.c
*
* Copyright (C) 1998 Russell King
*
* The block I/O interface allows an OS-independent method to access devices
*
* Write data to 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 write_block(blkio_t *blkio, const 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 = "sector";
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 >= limit) {
set_error ("Unable to write %s 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)|2,
(blkio->drive << 29) | (sector & 0x1fffffff), data, nr);
ret = swix (swino, rin(r1|r2|r3|r4), (((unsigned int)blkio->disc_record) << 6)|2,
(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 write_block(blkio_t *blkio, const 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 (write(blkio->fd, data, len) != len)
break;
res = nr_blocks;
} while (0);
return res;
}
#endif
/* Function: u_int blkio_write (blkio_t *blkio, const void *data, blk_t block, u_int nr_blocks)
* Purpose : Write `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 write data from
* : block - block number to write
* : nr_blocks - number of blocks to write
* Returns : number of blocks actually written
*/
u_int blkio_write (blkio_t *blkio, const void *data, blk_t block, u_int nr_blocks)
{
u_int res;
dbg_printf ("blkio_write(%p 0x%X +0x%X)", data, block, nr_blocks);
dbg_level_up ();
res = write_block(blkio, data, block, nr_blocks);
dbg_level_down ();
dbg_printf ("ret=%d", res);
return res;
}
|