Annotation of qemu/roms/openbios/packages/deblocker.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.