blob: d0f5c6a42cb8fb82e8f262dc2ee7ae5cefcd9b31 [file] [log] [blame]
/*
* <arch/unix/blk.c>
*
* block device emulation for unix hosts
*
* Copyright (C) 2004 Stefan Reinauer <stepan@openbios.org>
*
* 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 "blk.h"
typedef struct {
int unit;
int channel;
} blk_data_t;
DECLARE_NODE( blk, INSTALL_OPEN, sizeof(blk_data_t), "+/unix/block/disk" );
static void
blk_open( blk_data_t *pb )
{
phandle_t ph;
fword("my-unit");
pb->unit = POP();
pb->channel = 0; /* FIXME */
selfword("open-deblocker");
/* interpose disk-label */
ph = find_dev("/packages/disk-label");
fword("my-args");
PUSH_ph( ph );
fword("interpose");
/* printk("osi-blk: open %d\n", pb->unit ); */
PUSH( -1 );
}
static void
blk_close( __attribute__((unused)) blk_data_t *pb )
{
selfword("close-deblocker");
}
/* ( buf blk nblks -- actual ) */
static void
blk_read_blocks( blk_data_t *pb )
{
cell i, n = POP();
cell blk = POP();
char *dest = (char*)POP();
// printk("blk_read_blocks %x block=%d n=%d\n", (ucell)dest, blk, n );
for( i=0; i<n; ) {
char buf[4096];
ucell m = MIN( n-i, sizeof(buf)/512 );
if( read_from_disk(pb->channel, pb->unit, blk+i, (ucell)buf, m*512) < 0 ) {
printk("read_from_disk: error\n");
RET(0);
}
memcpy( dest, buf, m * 512 );
i += m;
dest += m * 512;
}
PUSH( n );
}
/* ( -- bs ) */
static void
blk_block_size( __attribute__((unused)) blk_data_t *pb )
{
PUSH( 512 );
}
/* ( -- maxbytes ) */
static void
blk_max_transfer( __attribute__((unused)) blk_data_t *pb )
{
PUSH( 1024*1024 );
}
static void
blk_initialize( __attribute__((unused)) blk_data_t *pb )
{
fword("is-deblocker");
}
NODE_METHODS( blk ) = {
{ NULL, blk_initialize },
{ "open", blk_open },
{ "close", blk_close },
{ "read-blocks", blk_read_blocks },
{ "block-size", blk_block_size },
{ "max-transfer", blk_max_transfer},
};
void
blk_init( void )
{
REGISTER_NODE( blk );
}