/*\ Check if asynchronous I/O operation completed. If yes, invalidate id. \*/ int elio_probe(io_request_t *req_id, int* status) { int errval=-1; int aio_i = 0; #ifdef PABLO int pablo_code = PABLO_elio_probe; PABLO_start( pablo_code ); #endif if(*req_id == ELIO_DONE){ *status = ELIO_DONE; } else { #ifdef AIO # if defined(CRAY) # if defined(FFIO) { struct ffsw dumstat, *prdstat=&(cb_fout[*req_id].stat); fffcntl(cb_fout[*req_id].filedes, FC_ASPOLL, prdstat, &dumstat); errval = (FFSTAT(*prdstat) == 0) ? INPROGRESS: 0; } # else errval = ( IO_DONE(cb_fout[*req_id].stat) == 0)? INPROGRESS: 0; # endif # elif defined(AIX) errval = aio_error(cb_fout[(int)*req_id].aio_handle); # else errval = aio_error(cb_fout+(int)*req_id); # endif #endif switch (errval) { case 0: while(aio_req[aio_i] != *req_id && aio_i < MAX_AIO_REQ) aio_i++; if(aio_i >= MAX_AIO_REQ) ELIO_ERROR(HANDFAIL, aio_i); *req_id = ELIO_DONE; *status = ELIO_DONE; aio_req[aio_i] = NULL_AIO; break; case INPROGRESS: *status = ELIO_PENDING; break; default: return PROBFAIL; } } #ifdef PABLO PABLO_end(pablo_code); #endif return ELIO_OK; }
int _er90b_writea(struct fdinfo *fio, bitptr bufptr, int nbytes, struct ffsw *retstat, int fulp, int *ubc) { int ret = 0; char *buf; ER90BYT *f; int zero = 0; struct ffsw dumstat; buf = BPTR2CP(bufptr); if ((BPBITOFF(bufptr) & 7) != 0 || *ubc != 0) ERETURN(retstat, FDC_ERR_UBC, 0); if (fio->rwflag == POSITIN) { f = (ER90BYT *)fio->lyr_info; if (f->tpos) { ret = _tape_tpwait(f->fd, &(f->tpos)); if (ret < 0) ERETURN(retstat, errno, 0); } } else if (fio->rwflag == READIN) { /* write after read requires position to zero */ ret = _er90b_pos(fio, FP_RSEEK, &zero, 1, &dumstat); if (ret < 0) { *retstat = dumstat; return(ERR); } } if (nbytes > 0) { CLRFFSTAT(*retstat); /* flag async in progress */ ret= writea(fio->realfd, buf, nbytes, (struct iosw *)retstat, 0); if (ret < 0) ERETURN(retstat, errno, 0); } else if (nbytes < 0) { ERETURN(retstat, FDC_ERR_REQ, 0); } else { /* nbytes == 0 */ retstat->sw_flag = 1; FFSTAT(*retstat) = FFCNT; /* I/O is done, and other stat */ /* fields are already set. */ } fio->rwflag = WRITIN; return (ret); }
/*\ Wait for asynchronous I/O operation to complete. Invalidate id. \*/ int elio_wait(io_request_t *req_id) { int aio_i=0; int rc; rc=0; /* just to remove the compiler warning */ #ifdef PABLO int pablo_code = PABLO_elio_wait; PABLO_start( pablo_code ); #endif if(*req_id != ELIO_DONE ) { # ifdef AIO # if defined(CRAY) # if defined(FFIO) { struct ffsw dumstat, *prdstat=&(cb_fout[*req_id].stat); fffcntl(cb_fout[*req_id].filedes, FC_RECALL, prdstat, &dumstat); if (FFSTAT(*prdstat) == FFERR) ELIO_ERROR(SUSPFAIL,0); } # else { struct iosw *statlist[1]; statlist[0] = &(cb_fout[*req_id].stat); recall(cb_fout[*req_id].filedes, 1, statlist); } # endif # elif defined(AIX) # if !defined(AIX52) && !defined(_AIO_AIX_SOURCE) do { /* I/O can be interrupted on SP through rcvncall ! */ rc =(int)aio_suspend(1, cb_fout_arr+(int)*req_id); } while(rc == -1 && errno == EINTR); # endif # else if((int)aio_suspend((const struct aiocb *const*)(cb_fout_arr+(int)*req_id), 1, NULL) != 0) rc =-1; # endif if(rc ==-1) ELIO_ERROR(SUSPFAIL,0); # if defined(DECOSF) /* on DEC aio_return is required to clean internal data structures */ if(aio_return(cb_fout+(int)*req_id) == -1) ELIO_ERROR(RETUFAIL,0); # endif #endif while(aio_req[aio_i] != *req_id && aio_i < MAX_AIO_REQ) aio_i++; if(aio_i >= MAX_AIO_REQ) ELIO_ERROR(HANDFAIL, aio_i); aio_req[aio_i] = NULL_AIO; *req_id = ELIO_DONE; } #ifdef PABLO PABLO_end(pablo_code); #endif return ELIO_OK; }
void AQSTAT( _f_int *aqp, _f_int *reply, _f_int *reqid, _f_int *status, _f_int *wait) { AQFIL *f; struct fflistreq *base, *limit, *ptr, *busy, *eptr; struct ffsw *istat; struct ffsw dumstat; int indx; int ret; int max; int isbusy; f = (AQFIL *) *aqp; if (f == NULL || f->aq_chk != AQ_CHK) { *status = -FEAQBADH; /* file handle is not valid */ return; } base = f->aq_base; limit = f->aq_limit; max = limit - base; /* * Lock the tail of the queue so no one can stomp on the entry for * which we are searching. */ AQ_LOCK(aq_lknxtq); AQ_LOCK(aq_lkbusy); /* don't nobody move */ busy = f->aq_busy; /* * Examine the entire queue, regardless of pointers */ for (indx = 0 ; indx < max ; indx++) { if ( f->aq_reqid[indx] == *reqid ) { eptr = &base[indx]; istat = base[indx].li_status; ptr = f->aq_ptr; /* Grab stable copy */ /* If it moves, that's OK. */ /* * If the user requested that we wait for this one... */ if (_numargs() > 4 && *wait != 0) { /* * Determine if the entry in question is * between busy and ptr. */ isbusy = NO; if (busy <= ptr) { if (busy <= eptr && eptr < ptr) isbusy = YES; } else { if (eptr < ptr || busy <= eptr) isbusy = YES; } /* * Now pointing to entry in question. * Wait for its completion, if btwn busy and ptr, * Unlock queue head to allow additions * to the queue while waiting. */ AQ_UNLOCK(aq_lknxtq); /* * If the requested reqid has not been fired, * fire the listio before the wait. */ if (isbusy == NO) { _aqcall(f); } goto finish_io2; } /* * If user did not request wait, just return the status, * but first check to see if it is done. If it is, Give * the recall routine a shot at cleanup and finish up as * though a wait had been requested. */ if (f->aq_ffio == YES) { AQPOLL(eptr, &dumstat); if (FFSTAT(*istat) != FFBSY) { goto finish_io1; } } else if ( istat->sw_flag != 0 ) { goto finish_io1; } /* * If the entry is found, but not complete, it is * either QUEUED and active or QUEUED and not yet * activated. * If eptr is between busy and ptr, it is active. */ *status = LQUEUED; /* not yet active */ if (busy <= ptr) { if (busy <= eptr && eptr < ptr) /* queued and active */ *status = QUEUED; } else { if (eptr < ptr || busy <= eptr) /* queued and active */ *status = QUEUED; } goto done; } } *status = NOTFOUND; done: AQ_UNLOCK(aq_lkbusy); AQ_UNLOCK(aq_lknxtq); return; finish_io1: AQ_UNLOCK(aq_lknxtq); finish_io2: /* * Do the 'recall' on the request. */ ret = _aqrcl(f, eptr); /* * The request is now done. Now that we are about to return the status * of the request, check if this entry is at tail of queue. * If the request is at the tail of the queue free up the entry. * This is probably silly. */ if (f->aq_busy == eptr) INC_QP(f->aq_busy, limit, max); /* * Set return status */ *status = IOCOMPLETE; if (ret != 0) { *status = -ret; if (ret == FERDWRER) *reply = eptr->li_status->sw_count; } /* * Flag the status as delivered */ f->aq_told[indx] = 1; /* mark status as having been sent to user */ AQ_UNLOCK(aq_lkbusy); return; }
long _frch( unit *cup, long *uda, long chars, int mode, long *status) { register int bytsiz; register int chr; register long nchr; register long ncnt; unsigned char tbuf[TBUFSZB], *tp; /* Line buffer */ FILE *fptr; struct ffsw stat; struct fdinfo *fio; #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) register long count; char *tpinterim; #endif switch (cup->ufs) { case FS_TEXT: case STD: fptr = cup->ufp.std; /* * Switch the FILE structure into read mode */ #if !defined(_LITTLE_ENDIAN) || (defined(_LITTLE_ENDIAN) && defined(__sv2)) if ((FILE_FLAG(fptr) & (_IOREAD | _IORW)) == _IORW) { if (FILE_FLAG(fptr) & _IOWRT) (void) fseek(fptr, 0, SEEK_CUR); FILE_FLAG(fptr) |= _IOREAD; } #endif /* * Loop on getc until the character count has been * exhausted, an end of file is encountered, or end * of record. */ nchr = 0; #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) while (nchr < chars) { fill: errno = 0; count = chars - nchr; tp = tbuf; count = MIN(TBUFSZB, (count + 1)); tpinterim = fgets((char *)tp, count, fptr); if (tpinterim == NULL) { /* * Search for the newline char in the buffer, but * search only the number of characters left in * the request, plus one in case it is the * newline (if it is in the buffer). If we find * newline, we're done. */ /* EOF here means incomplete record. */ if (ferror(fptr)) { if ( errno == EINTR && _GINTIO == 0) { clearerr(fptr); goto fill; } if (errno == 0) errno = FESTIOER; return(IOERR); } /* * If nchr > zero, file has no newline. * Make sure we handle it properly. */ if (feof(fptr)) { if (nchr == 0) { *status = EOD; return(0); } *status = CNT; return(nchr); } } else { unsigned char *tmpptr; ncnt = count - 1; #ifdef KEY /* Bug 3797 */ /* no newline if fgets encountered eof */ tmpptr = strchr(tp, '\n'); #ifdef KEY /* Bug 3975 */ char *nlptr = memchr(tp, '\n', ncnt); /* Temporary fix to deal with the situation * in which nulls appear before the newline. * Correct fix is to eliminate those nulls. */ if (NULL == tmpptr && NULL != nlptr) { tmpptr = nlptr; } #endif /* KEY Bug 3975 */ #else tmpptr = memchr(tp, '\n', ncnt); #endif /* KEY Bug 3797 */ if (tmpptr != NULL) { /* eor */ *status = EOR; ncnt = tmpptr - tp; nchr += ncnt; _unpack(tp, uda, ncnt, -1); /* Return number of chars read */ return(nchr); } #ifdef KEY /* Bug 3797 */ /* fgets got chars ending in eof, not newline */ else if (feof(fptr)) { *status = EOR; ncnt = strlen(tp); nchr += ncnt; _unpack(tp, uda, ncnt, -1); return nchr; } #endif /* KEY Bug 3797 */ _unpack(tp, uda, ncnt, -1); nchr += ncnt; uda += ncnt; /* go refill the buffer */ } } #else while (nchr < chars) { if (FILE_CNT(fptr) <= 0) { fill: errno = 0; chr = _filbuf(fptr); /* EOF here means incomplete record. */ if (chr == EOF) { if (ferror(fptr)) { if ( errno == EINTR && _GINTIO == 0 ) { clearerr(fptr); goto fill; } if (errno == 0) errno = FESTIOER; return(IOERR); } /* * If nchr > zero, file has no newline. * Make sure we handle it properly. */ if (nchr == 0) { *status = EOD; return(0); } *status = CNT; return(nchr); } /* * Put character returned by filbuf() back */ FILE_CNT(fptr)++; FILE_PTR(fptr)--; } /* * Search for a newline char in the buffer, but search * only the number of characters left in the request, * plus one in case it is the newline (if it is in * the buffer). If we find the newline, we're done. */ if ((chars - nchr) < FILE_CNT(fptr)) { ncnt = chars - nchr; tp = memchr(FILE_PTR(fptr), '\n', ncnt + 1); } else { ncnt = FILE_CNT(fptr); /* assume no EOR yet */ tp = memchr(FILE_PTR(fptr), '\n', ncnt); } if (tp != NULL) { /* Found end of record */ *status = EOR; ncnt = tp - FILE_PTR(fptr); nchr += ncnt; _unpack((char *)FILE_PTR(fptr), uda, ncnt, -1); FILE_CNT(fptr) -= ncnt + 1; FILE_PTR(fptr) += ncnt + 1; return(nchr); /* Return number of characters read */ } _unpack((char *)FILE_PTR(fptr), uda, ncnt, -1); FILE_CNT(fptr) -= ncnt; FILE_PTR(fptr) += ncnt; nchr += ncnt; uda += ncnt; /* go refill the buffer */ } #endif /* * Get the next character to see if at end of record. * Set the user's status word accordingly. */ chr = getc(fptr); *status = CNT; if (chr == '\n' ) { *status = EOR; return(nchr); /* Return number of characters read */ } /* * We are not at end of record. Thus if reading in full * record mode skip until EOR is found. If reading in * partial record mode, unget the last character read. */ if (mode == FULL) #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) { fill2: count = TBUFSZB; tp = tbuf; tpinterim = fgets((char *)tp, count, fptr); if (tpinterim == NULL) { /* EOF means incomplete record. */ if (ferror(fptr)) { if ( errno == EINTR && _GINTIO == 0 ) { clearerr(fptr); goto fill2; } } /* Return number of chars read. */ return(nchr); } else { unsigned char *tmpptr; ncnt = count - 1; tmpptr = memchr(tp, '\n', ncnt); if (tmpptr != NULL) { /* Found eor */ /* Return number of chars read */ return(nchr); } else goto fill2; } } #else while (1) { if (FILE_CNT(fptr) <= 0) { fill2: chr = _filbuf(fptr); /* EOF here means incomplete record. */ if (chr == EOF) { if (ferror(fptr)) { if ( errno == EINTR && _GINTIO == 0 ) { clearerr(fptr); goto fill2; } } /* Return number of characters read */ return(nchr); } FILE_CNT(fptr)++; FILE_PTR(fptr)--; } tp = memchr(FILE_PTR(fptr), '\n', FILE_CNT(fptr)); if (tp != NULL) { tp++; FILE_CNT(fptr) -= tp - FILE_PTR(fptr); FILE_PTR(fptr) = tp; return(nchr); } else FILE_CNT(fptr) = 0; } #endif else { ungetc ((char) chr, fptr); } return(nchr); /* return number of character read */ case FS_FDC: nchr = 0; fio = cup->ufp.fdc; /* * If no conversion is to be done, or no characters requested * (usually for null request, FULL mode), make it simple and direct. */ if (cup->ucharset == 0 || chars == 0) { register long breq; register int ffstat; register int ret; /* * If file is direct access, we know that all reads are * going to be whole records in FULL mode. We also * know that the open code would not let us get this far * if we were not dealing with a stream layer. */ breq = chars; ret = XRCALL(fio, readcrtn) fio, CPTR2BP(uda), breq, &stat, mode); if (ret < 0) { errno = stat.sw_error; return(IOERR); } ffstat = FFSTAT(stat); if (!cup->useq && !cup->ublkd && ffstat == FFCNT) ffstat = FFEOR; *status = FF2FTNST(ffstat); nchr = ret; return(nchr); /* Return number of characters read */ } /* * Get proper byte size (might not be 8-bits if doing conversion). */ #if NUMERIC_DATA_CONVERSION_ENABLED bytsiz = __fndc_charsz[cup->ucharset]; #else bytsiz = 8; #endif FFSTAT(cup->uffsw) = FFCNT; *status = CNT; while (nchr < chars && FFSTAT(cup->uffsw) != FFEOR) { register long bgot; register long breq; register long padc; register int ret; register long totbits; int ubc; /* * Calculate the number of bits that need to be taken * from the foreign data stream. * * ncnt = number of resultant bytes */ ncnt = chars - nchr; if (ncnt > TBUFSZB) ncnt = TBUFSZB; totbits = bytsiz * ncnt; /* bit count */ breq = (totbits + 7) >> 3; /* full 8-bit bytes */ ubc = (breq << 3) - totbits;/* unused bits */ ret = XRCALL(fio, readrtn) fio, CPTR2BP(tbuf), breq, &cup->uffsw, PARTIAL, &ubc); if (ret < 0) { /* if an error */ errno = cup->uffsw.sw_error; return(IOERR); } /* if end of file */ if (ret == 0) { if (nchr == 0) *status = FF2FTNST(FFSTAT(stat)); return(nchr); /* Return number of characters read */ } /* * how many bits did we get? Convert back to foreign * character count. */ totbits = (ret << 3) - ubc; bgot = totbits / bytsiz; /* foreign bytes */ ubc = totbits - (bgot * bytsiz); if (ubc != 0) { errno = FEINTUNK; return(IOERR); } padc = 0; if (FFSTAT(cup->uffsw) == FFEOR) { padc = chars - (bgot + nchr); *status = EOR; } if (_fdc_unpackc(tbuf, &uda[nchr], bgot, padc, cup->ucharset) < 0) { return(IOERR); } nchr += bgot; } /* check for null request, non-EOR */ if (FFSTAT(cup->uffsw) == FFCNT && mode == FULL) { register int ret; int ubc; ret = XRCALL(fio, readrtn) fio, CPTR2BP(tbuf), 0, &cup->uffsw, FULL, &ubc); if (ret < 0) { /* if an error */ errno = cup->uffsw.sw_error; return(IOERR); } } return(nchr); case FS_AUX: errno = FEMIXAUX; return(IOERR); default: errno = FEINTFST; return(IOERR); }
static void _rb( FIOSPTR css, /* Current Fortran I/O state */ unit *cup, /* Unit pointer */ _f_int *recmode, /* Mode */ gfptr_t bloc, /* Beginning location */ gfptr_t eloc, /* Ending location */ type_packet *tip) /* Type information packet */ { register int bytshft; register int mode; register long bytes; register long elsize; register long itemlen; register long items; register long stat; register ftype_t type90; int state; char *uda, *udax; #ifdef _CRAYT3D register short shared; register long ntot; register long numleft; long shrd[MAXSH]; #endif if (cup->useq == 0) /* If direct access file */ _ferr(css, FEBIONDA, "BUFFER IN"); if (cup->ufmt) /* If formatted file */ _ferr(css, FEBIONFM, "BUFFER IN"); if (cup->uerr && !cup->unitchk) _ferr(css, cup->uffsw.sw_error); /* * This check taken out temporarily because we'd like to be able to * follow an ENDFILE statement or a READ which encounters an endfile * record with a BUFFER IN statement. The sticky EOF principle should * permit such a BUFFER IN to simply return an EOF status. But what * really happens is the preceding ENDFILE or READ statement sets * cup->uend, triggering an error here. We really need a flag to * store the status of the previous BUFFER IN/OUT statement which is * separate from cup->uend. * * if (cup->uend && !cup->unitchk) * _ferr(css, FERDPEOF); */ cup->unitchk = 0; cup->uerr = 0; elsize = tip->elsize; /* Data size in bytes */ type90 = tip->type90; /* * Adjust the word count depending on the type. */ bytshft = ((sizeof(elsize) << 3) - 1) - _leadz(elsize); /* log2(elsize) */ if (type90 == DVTYPE_ASCII) { /* If character item */ uda = _fcdtocp(bloc.fcd); udax = _fcdtocp(eloc.fcd); itemlen = _fcdlen (eloc.fcd); } else { #ifdef _CRAYT3D shared = 0; if (_issddptr(bloc.v)) { int *tmpptr; /* Shared data */ if (!_issddptr(eloc.v)) { _ferr(css, FEINTUNK); } shared = 1; ntot = 0; if ((cup->ufs == FS_FDC) && (cup->uflagword & FFC_ASYNC)) { /* When we can do I/O from shared memory */ /* we can support this. */ _ferr(css, FESHRSUP); } /* * When compiler spr 76429 (on T3D) is closed, we can try replacing * the lines that use tmpptr with this. * items = _sdd_read_offset((void *)eloc.v) - * _sdd_read_offset((void *)bloc.v) + 1; */ uda = bloc.v; /* temporary */ udax = eloc.v; tmpptr = (int *)((int)udax & 0x7fffffffffffffff); items = *(tmpptr + 1); tmpptr = (int *)((int)uda & 0x7fffffffffffffff); items = items - *(tmpptr + 1) + 1; } else #endif /* _CRAYT3D */ { uda = bloc.v; udax = eloc.v; } itemlen = elsize; } #ifdef _CRAYT3D if (shared) { bytes = items << bytshft; } else #endif { bytes = (udax - uda) + itemlen; items = bytes >> bytshft; } if (bytes < 0) _ferr(css, FEBIOFWA, "BUFFER IN"); mode = (*recmode < 0) ? PARTIAL : FULL; cup->urecmode = mode; cup->uwrt = 0; state = CNT; if ((items << bytshft) != bytes) _ferr(css, FEBIOFWD); #ifdef _CRAYT3D if ( !shared && cup->uasync ) { #else if (cup->uasync) { #endif int ubc = 0; WAITIO(cup, _ferr(css, cup->uffsw.sw_error)); #if defined(_UNICOS) || defined(NUMERIC_DATA_CONVERSION_ENABLED) /* * Pad word-aligned numeric data on word boundaries within * the record for CRI and some foreign data formats. */ if ((cup->urecpos & cup->ualignmask) != 0 && type90 != DVTYPE_ASCII && elsize > 4 ) { int padubc; register int pbytes; int padval; COMPADD(cup, pbytes, padubc, padval); if (pbytes != 0) { stat = XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc, WPTR2BP(&padval), pbytes, &cup->uffsw, PARTIAL, &padubc); if (stat != pbytes || FFSTAT(cup->uffsw) != FFCNT) { cup->uerr = 1; goto badpart; } cup->urecpos += (stat << 3) - padubc; } }
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); } }