|
|
1.1 ! root 1: /* ! 2: * Creation Date: <2003/12/03 21:20:58 samuel> ! 3: * Time-stamp: <2004/01/07 19:34:50 samuel> ! 4: * ! 5: * <deblocker.c> ! 6: * ! 7: * deblocker implementation ! 8: * ! 9: * Copyright (C) 2003, 2004 Samuel Rydh ([email protected]) ! 10: * ! 11: * This program is free software; you can redistribute it and/or ! 12: * modify it under the terms of the GNU General Public License ! 13: * version 2 ! 14: * ! 15: */ ! 16: ! 17: #include "config.h" ! 18: #include "libopenbios/bindings.h" ! 19: #include "libc/diskio.h" ! 20: #include "packages.h" ! 21: ! 22: typedef struct { ! 23: ucell mark_hi, mark_lo; ! 24: xt_t read_xt; ! 25: xt_t write_xt; ! 26: ! 27: int max_xfer; ! 28: int blksize; ! 29: char *buf; ! 30: } deblk_info_t; ! 31: ! 32: DECLARE_NODE( deblocker, 0, sizeof(deblk_info_t), "+/packages/deblocker" ); ! 33: ! 34: /* ( -- flag ) */ ! 35: static void ! 36: deblk_open( deblk_info_t *di ) ! 37: { ! 38: xt_t xt; ! 39: ! 40: di->read_xt = find_parent_method("read-blocks"); ! 41: di->write_xt = find_parent_method("write-blocks"); ! 42: ! 43: if( !di->read_xt ) ! 44: RET(0); ! 45: ! 46: di->blksize = di->max_xfer = 512; ! 47: if( (xt=find_parent_method("block-size")) ) { ! 48: call_parent( xt ); ! 49: di->blksize = POP(); ! 50: } ! 51: if( (xt=find_parent_method("max-transfer")) ) { ! 52: call_parent( xt ); ! 53: di->max_xfer = POP(); ! 54: } ! 55: /* printk("block-size: %x max_xfer: %x read_xt %x write_xt %x\n", ! 56: di->blksize, di->max_xfer, di->write_xt, di->read_xt ); */ ! 57: ! 58: di->buf = malloc( di->blksize ); ! 59: PUSH(-1); ! 60: } ! 61: ! 62: /* ( -- ) */ ! 63: static void ! 64: deblk_close( deblk_info_t *di ) ! 65: { ! 66: free( di->buf ); ! 67: } ! 68: ! 69: /* ( pos_lo pos_hi -- status ) */ ! 70: static void ! 71: deblk_seek( deblk_info_t *di ) ! 72: { ! 73: ucell pos_hi = POP(); ! 74: ucell pos_lo = POP(); ! 75: ducell mark = ((ducell)pos_hi << BITS) | pos_lo; ! 76: ! 77: /* printk("deblk_seek %x %08x\n", pos_hi, pos_lo ); */ ! 78: ! 79: /* -1 means seek to EOF (at least in our implementation) */ ! 80: if( (dcell)mark == -1 ) ! 81: RET(-1); ! 82: di->mark_hi = pos_hi; ! 83: di->mark_lo = pos_lo; ! 84: ! 85: /* 0,1 == success, -1 == error */ ! 86: PUSH(0); ! 87: } ! 88: ! 89: /* ( -- mark.d ) */ ! 90: static void ! 91: deblk_tell( deblk_info_t *di ) ! 92: { ! 93: PUSH( di->mark_lo ); ! 94: PUSH( di->mark_hi ); ! 95: } ! 96: ! 97: ! 98: #define DO_IO( xt, buf, blk, n ) \ ! 99: ({ PUSH3(pointer2cell(buf), blk, n); call_parent(xt); POP(); }) ! 100: ! 101: typedef struct { ! 102: /* block operation */ ! 103: char *blk_buf; ! 104: int nblks; ! 105: ! 106: /* byte operation */ ! 107: cell offs; ! 108: int len; ! 109: char *data; /* start of data */ ! 110: } work_t; ! 111: ! 112: static void ! 113: split( deblk_info_t *di, char *data, int len, work_t w[3] ) ! 114: { ! 115: ducell mark = ((ducell)di->mark_hi << BITS) | di->mark_lo; ! 116: memset( w, 0, sizeof(work_t[3]) ); ! 117: ! 118: w[0].offs = mark % di->blksize; ! 119: w[0].blk_buf = di->buf; ! 120: w[0].data = data; ! 121: if( w[0].offs ) { ! 122: w[0].len = MIN( len, di->blksize - w[0].offs ); ! 123: w[0].nblks = w[0].len ? 1:0; ! 124: data += w[0].len; ! 125: len -= w[0].len; ! 126: } ! 127: ! 128: w[1].blk_buf = data; ! 129: w[1].nblks = (len / di->blksize); ! 130: w[1].len = w[1].nblks * di->blksize; ! 131: data += w[1].len; ! 132: len -= w[1].len; ! 133: ! 134: w[2].blk_buf = di->buf; ! 135: w[2].data = data; ! 136: w[2].len = len; ! 137: w[2].nblks = len ? 1:0; ! 138: } ! 139: ! 140: static int ! 141: do_readwrite( deblk_info_t *di, int is_write, xt_t xt ) ! 142: { ! 143: int blk, i, n, len = POP(); ! 144: char *dest = (char*)cell2pointer(POP()); ! 145: int last=0, retlen=0; ! 146: work_t w[3]; ! 147: ducell mark = ((ducell)di->mark_hi << BITS) | di->mark_lo; ! 148: ! 149: /* printk("read: %x %x\n", (int)dest, len ); */ ! 150: ! 151: if( !xt ) ! 152: return -1; ! 153: ! 154: blk = mark / di->blksize; ! 155: split( di, dest, len, w ); ! 156: ! 157: for( i=0; !last && i<3; i++ ) { ! 158: if( !w[i].nblks ) ! 159: continue; ! 160: ! 161: if( is_write && i != 1 ) { ! 162: DO_IO( di->read_xt, w[i].blk_buf, blk, w[i].nblks ); ! 163: memcpy( w[i].blk_buf + w[i].offs, w[i].data, w[i].len ); ! 164: } ! 165: ! 166: n = DO_IO( xt, w[i].blk_buf, blk, w[i].nblks ); ! 167: if( n < 0 ) { ! 168: if( !retlen ) ! 169: retlen = -1; ! 170: break; ! 171: } ! 172: if( n != w[i].nblks ) { ! 173: w[i].len = MIN( n*di->blksize, w[i].len ); ! 174: last = 1; ! 175: } ! 176: if( !is_write && i != 1 ) ! 177: memcpy( w[i].data, w[i].blk_buf + w[i].offs, w[i].len ); ! 178: retlen += w[i].len; ! 179: blk += n; ! 180: } ! 181: if( retlen > 0 ) { ! 182: mark += retlen; ! 183: di->mark_hi = mark >> BITS; ! 184: di->mark_lo = mark & (ucell) -1; ! 185: } ! 186: return retlen; ! 187: } ! 188: ! 189: /* ( addr len -- actual ) */ ! 190: static void ! 191: deblk_read( deblk_info_t *di ) ! 192: { ! 193: /* printk("deblk_read\n"); */ ! 194: int ret = do_readwrite( di, 0, di->read_xt ); ! 195: PUSH( ret ); ! 196: } ! 197: ! 198: /* ( buf len --- actlen ) */ ! 199: static void ! 200: deblk_write( deblk_info_t *di ) ! 201: { ! 202: int ret = do_readwrite( di, 1, di->write_xt ); ! 203: PUSH( ret ); ! 204: } ! 205: ! 206: /* remember to fix is-deblocker if new methods are added */ ! 207: NODE_METHODS( deblocker ) = { ! 208: { "open", deblk_open }, ! 209: { "close", deblk_close }, ! 210: { "read", deblk_read }, ! 211: { "write", deblk_write }, ! 212: { "seek", deblk_seek }, ! 213: { "tell", deblk_tell }, ! 214: }; ! 215: ! 216: ! 217: void ! 218: deblocker_init( void ) ! 219: { ! 220: REGISTER_NODE( deblocker ); ! 221: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.