Mercurial > sos > sos
view arch/fba.c @ 96:a480d02a10c8
merge
author | Jonathan Pevarnek <pevarnj@gmail.com> |
---|---|
date | Sat, 14 May 2011 12:54:47 -0400 |
parents | 40af39d064fa |
children |
line wrap: on
line source
#include "channel.h" #include <die.h> #define FBA_BLK_SIZE 512 #define DASD_FBA_WRITE 0x41 #define DASD_FBA_READ 0x42 #define DASD_FBA_LOCATE_RECORD 0x43 #define DASD_FBA_DEFINE_EXTENT 0x63 enum op_type { WRITE = 0, READ, }; struct fba_DE_data { u8 perm:2, /* Permissions on this extent */ __zero0:2, da:1, diag:1, /* allow diagnose */ __zero1:2; u8 __zero3; u16 blksize; /* Blocksize */ u32 ext_loc; /* Extent locator */ u32 ext_beg; /* logical number of block 0 in extent */ u32 ext_end; /* logocal number of last block in extent */ }; struct fba_LO_data { u8 zero:4, cmd:4; u8 aux; u16 count; u32 blkno; }; /* build a Define-Extent CCW */ static void fba_define_extent(struct ccw *ccw, struct fba_DE_data *data, enum op_type rw, u16 blksize, u32 blkno, u32 len) { ccw->cmd = DASD_FBA_DEFINE_EXTENT; ccw->count = 0x10; ccw->addr = (u32) (u64) data; __builtin_memset(data, 0, sizeof(struct fba_DE_data)); switch(rw) { case WRITE: data->perm = 0x00; break; case READ: data->perm = 0x01; break; default: die(); break; } data->blksize = blksize; data->ext_loc = blkno; data->ext_end = len - 1; } /* build a Locate-Record CCW */ static void fba_locate_record(struct ccw *ccw, struct fba_LO_data *data, enum op_type rw, u32 blkno, u32 len) { ccw->cmd = DASD_FBA_LOCATE_RECORD; ccw->count = 0x08; ccw->addr = (u32) (u64) data; __builtin_memset(data, 0, sizeof(struct fba_LO_data)); switch(rw) { case WRITE: data->cmd = 0x05; break; case READ: data->cmd = 0x06; break; default: die(); break; } data->blkno = blkno; data->count = len; } /* build a Read or Write CCW */ static void fba_readwrite(struct ccw *ccw, void *ptr, enum op_type rw, u32 len) { if(len > 0xffff) die(); switch(rw) { case 0: ccw->cmd = DASD_FBA_WRITE; break; case 1: ccw->cmd = DASD_FBA_READ; break; default: die(); break; } ccw->count = len; ccw->addr = (u32) (u64) ptr; } /** * fba_read_blk - read a block from an FBA device * @dev: device to read from * @blkno: block number to read * @ptr: buffer to fill * @sync: synchronous I/O */ static int __fba_readwrite_blk(u32 dev, u32 blkno, void *ptr, enum op_type dir) { struct orb orb; struct ccw ccw[3]; struct fba_DE_data defext; struct fba_LO_data locate; __builtin_memset(&orb, 0, sizeof(struct orb)); orb.lpm = 0xff; orb.addr = (u32) (u64) ccw; orb.f = 1; __builtin_memset(ccw, 0, sizeof(ccw)); /* Define-Extent */ fba_define_extent(&ccw[0], &defext, dir, FBA_BLK_SIZE, blkno, 1); ccw[0].flags |= 0x40; /* Locate */ fba_locate_record(&ccw[1], &locate, dir, 0, 1); ccw[1].flags |= 0x40; /* Read */ fba_readwrite(&ccw[2], ptr, dir, FBA_BLK_SIZE); if (start_sch(dev, &orb)) die(); wait_for_io_int(); return 0; } int fba_read_blk(u32 dev, u32 blkno, void *ptr) { return __fba_readwrite_blk(dev, blkno, ptr, READ); } int fba_write_blk(u32 dev, u32 blkno, void *ptr) { return __fba_readwrite_blk(dev, blkno, ptr, WRITE); }