/* * _sds_fr_mem moves data into SDS from user memory. * * Returns 0 on normal return, or else -1 with error code in errno. */ _sds_fr_mem( bitptr sdsaddr, /* SDS bit address where data will be received */ bitptr ubuf, /* user buffer containing data */ int nbits /* number of bits to move */ ) { long sds_bit_offset; char *ucaddr; long *uwaddr; int ret; if (nbits & (BITPBLOCK - 1)) { errno = FDC_ERR_GRAN; /* must be block multiple */ return -1; } ucaddr = BPTR2CP(ubuf); uwaddr = BPTR2WP(ubuf); if (ucaddr != (char*)uwaddr) { errno = FDC_ERR_SDSWB; /* must be word-aligned */ return -1; } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); if (sds_bit_offset & (BITPBLOCK - 1)) { errno = FDC_ERR_GRAN; /* must be block multiple */ return -1; } ret = sswrite(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(nbits)); if (ret == -1) errno = FDC_ERR_SDSIO; return ret; }
/* * _any_mem_fr_sds moves data into user memory from a secondary data segment (SDS). * * unlike _mem_fr_sds, _any_mem_fr_sds handles moving a number of bits that * may not be a multiple of 512. * * Returns 0 on normal return, or else -1 with error code in errno. */ _any_mem_fr_sds( bitptr ubuf, /* user buffer to receive data */ bitptr sdsaddr, /* SDS bit address of data */ int nbits /* number of bits to move */ ) { int sds_bit_offset; int sds_bit_offset_blk; int rbits; char localbuf[BYTPBLOCK]; bitptr locptr; long *uwaddr; char *ucaddr; sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); if (sds_bit_offset & (BITPBLOCK -1)) { /* The sds address is not on a block boundary. */ /* Read data from sds to a local buffer. Copy the */ /* appropriate part of the local buffer to user's memory. */ sds_bit_offset_blk = (sds_bit_offset & ~(BITPBLOCK - 1)); if(ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } rbits = MIN(nbits, BITPBLOCK - (sds_bit_offset - sds_bit_offset_blk)); locptr = CPTR2BP(localbuf); SET_BPTR(locptr, INC_BPTR(locptr, sds_bit_offset - sds_bit_offset_blk)); MOV_BITS(ubuf, locptr, rbits); SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); nbits -= rbits; SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); if (nbits == 0) return(0); /* Verify that our sds address is now on a block boundary */ assert (((SUBT_BPTR(sdsaddr, WPTR2BP(0))) & (BITPBLOCK -1)) == 0); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); uwaddr = BPTR2WP(ubuf); ucaddr = BPTR2CP(ubuf); if ((nbits & (BITPBLOCK-1)) || (ucaddr != (char *)uwaddr)){ int left; /* Either we are not reading in a multiple of blocks or */ /* the user's address is not word-aligned. */ /* Round nbits down to a block boundary and */ /* move those to user's memory. */ locptr = CPTR2BP(localbuf); rbits = nbits & ~(BITPBLOCK-1); if (rbits) { if (ucaddr != (char*)uwaddr) { /* ubuf is not word aligned. */ /* Read the data from sds into a local */ /* buffer and copy to the user's memory */ left = rbits; sds_bit_offset_blk = BITS2BLOCKS(sds_bit_offset); while (left > 0) { if (ssread((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(ubuf, locptr, BITPBLOCK); SET_BPTR(ubuf, INC_BPTR(ubuf, BITPBLOCK)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, BITPBLOCK)); sds_bit_offset_blk++; left-= BITPBLOCK; } } else { if (ssread(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(rbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); } /* get last block into local memory and */ /* transfer to user's memory */ if (ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } assert((nbits - rbits) < BITPBLOCK); MOV_BITS(ubuf, locptr, nbits - rbits); } else { if(ssread(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(nbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } return(0); }
/* * _any_sds_fr_mem moves data into a secondary data segment (SDS) from * user memory * * unlike _sds_fr_mem, _any_sds_fr_mem handles moving a number of bits that * may not be a multiple of 512. * * Returns 0 on normal return, or else -1 with error code in errno. */ _any_sds_fr_mem( bitptr sdsaddr, /* SDS bit address of data */ bitptr ubuf, /* user buffer to receive data */ int nbits /* number of bits to move */ ) { int sds_bit_offset; int sds_bit_offset_blk; int rbits; char localbuf[BYTPBLOCK]; bitptr locptr; long *uwaddr; char *ucaddr; sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); if (sds_bit_offset & (BITPBLOCK -1)) { /* The sds address is not on a block boundary. */ /* Read data from sds to a local buffer. Copy the */ /* user's memory to the appropriate part of the local */ /* buffer, and write it back out to sds. */ sds_bit_offset_blk = (sds_bit_offset & ~(BITPBLOCK - 1)); if (ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } rbits = MIN(nbits, BITPBLOCK - (sds_bit_offset - sds_bit_offset_blk)); locptr = CPTR2BP(localbuf); SET_BPTR(locptr, INC_BPTR(locptr, sds_bit_offset - sds_bit_offset_blk)); MOV_BITS(locptr, ubuf, rbits); SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); nbits -= rbits; if(sswrite((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); if (nbits == 0) return(0); assert(((SUBT_BPTR(sdsaddr, WPTR2BP(0))) & (BITPBLOCK -1)) == 0); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); uwaddr = BPTR2WP(ubuf); ucaddr = BPTR2CP(ubuf); if ((nbits & (BITPBLOCK-1)) || (ucaddr != (char *)uwaddr)){ int left; locptr = CPTR2BP(localbuf); /* round down nbits to a block boundary */ rbits = nbits & ~(BITPBLOCK-1); if (rbits) { if (ucaddr != (char*)uwaddr) { /* ubuf is not word aligned. */ left = rbits; sds_bit_offset_blk = BITS2BLOCKS(sds_bit_offset); while (left > 0) { if( ssread((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(locptr, ubuf, BITPBLOCK); SET_BPTR(ubuf, INC_BPTR(ubuf, BITPBLOCK)); if( sswrite((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, BITPBLOCK)); sds_bit_offset_blk++; left-= BITPBLOCK; } } else { if (_sds_fr_mem(sdsaddr, ubuf, rbits) == -1) { return(-1); } SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); } /* Get last block into local memory. Merge in user's memory */ /* and write it back out to sds. */ if( ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(locptr, ubuf, nbits - rbits); if( sswrite((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } else { if(sswrite(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(nbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } return(0); }
int _sqb_pos(struct fdinfo *fio, int cmd, long *arg, int len, struct ffsw *stat) { int ret = 0; struct sqb_f *sqb_info; struct sqbio *sqbptr; struct sqbio *sqborig; struct sqbio *s; struct fdinfo *llfio; int found = 0; int nbits; int sync = -1; llfio = fio->fioptr; sqb_info = (struct sqb_f *)fio->lyr_info; if (fio->rwflag == WRITIN) { /* flush buffers and wait for outstanding I/O to finish. */ if (_sqb_flush(fio, stat) < 0) { return(ERR); } } switch(cmd) { /* For now, this is not supported on SGI systems. */ /* We need to work out what "arg" should be. */ #if !defined(__mips) && !defined(_LITTLE_ENDIAN) case FP_RSEEK: if ((fio->rwflag == READIN) || (fio->rwflag == POSITIN)) { if (*arg < 0) { /* Seeking backwards */ /* Are we seeking within the current */ /* buffer? */ sqbptr = sqb_info->sqbio_cur; if (sqbptr->status == IOACTIVE) { while (sqbptr->iostat.sw_flag == 0 || sqbptr->iostat.sw_stat == 0) { ret = XRCALL(llfio,fcntlrtn) llfio, FC_RECALL, &(sqbptr->iostat), stat); if (ret < 0) { return(ERR); } } if (FFSTAT(sqbptr->iostat) == FFERR) { ERETURN(stat, sqbptr->iostat.sw_error,0); } sqbptr->_cnt = sqbptr->iostat.sw_count<<3; sqbptr->status = IODATA; } if (sqbptr->status == IODATA) { nbits = -(*arg); /* convert to positive */ nbits = nbits<<3; if (nbits <= SUBT_BPTR(sqb_info->_ptr,sqbptr->_base)){ SET_BPTR(sqb_info->_ptr, INC_BPTR(sqb_info->_ptr,-nbits)); sqbptr->_cnt += nbits; break; } } } else { /* seeking forward */ /* Any chance that the position would be in */ /* our buffers? */ nbits = *arg << 3; if (nbits > sqb_info->nbuf * sqb_info->bufsiz){ /* won't be in any of the buffers */ goto a1; } sqbptr = sqb_info->sqbio_cur; sqborig = sqbptr; do { if (sqbptr->status == IOACTIVE) { while (sqbptr->iostat.sw_flag == 0 || sqbptr->iostat.sw_stat == 0) { ret = XRCALL(llfio,fcntlrtn) llfio, FC_RECALL, &(sqbptr->iostat), stat); if (ret < 0) { return(ERR); } } if (FFSTAT(sqbptr->iostat) == FFERR) { ERETURN(stat, sqbptr->iostat.sw_error,0); } sqbptr->_cnt = sqbptr->iostat.sw_count<<3; sqbptr->status = IODATA; } if (sqbptr->status == IODATA) { if (nbits <= sqbptr->_cnt) { /* Desired position is in this buffer */ sqbptr->_cnt -= nbits; /* Clear out buffers that preceeded this */ s = sqborig; for (; s != sqbptr; s= s->nxt) { s->status = EMPTY; CLRFFSTAT(s->iostat); } sqb_info->sqbio_cur = sqbptr; if (sqbptr != sqborig) sqb_info->_ptr = sqbptr->_base; SET_BPTR(sqb_info->_ptr, INC_BPTR(sqb_info->_ptr,nbits)); found = 1; break; } else { nbits -= sqbptr->_cnt; } } else goto a1; /* all out of data */ sqbptr = sqbptr->nxt; } while (sqbptr != sqborig); } }