int _er90b_write(struct fdinfo *fio, bitptr bufptr, int nbytes, struct ffsw *retstat, int fulp, int *ubc) { int ret; int nbt = 0; /* number of bytes transferred so far */ int nbreq; /* number of bytes requested this request */ 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); nbreq = nbytes; 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 (nbreq > 0) { again: /* It is not safe to reissue the write if it fails */ /* with EINTR. Some data may have been transferred */ ret= write(fio->realfd, buf, nbreq); if (ret < 0) ERETURN(retstat, errno, nbt); nbt += ret; /* * The assumption is made here that the system will never return * zero bytes on a non-zero request without an error! */ if (nbt < nbytes) { buf += ret; nbreq -= ret; goto again; } } else if (nbytes < 0) ERETURN(retstat, FDC_ERR_REQ, 0); SETSTAT(retstat, FFCNT, nbt); fio->rwflag = WRITIN; return (nbt); }
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); }
_bmx_gabs(BMXFIL *f, void *blockid) { if ( f->bmx_tpos ) { if ( _tape_tpwait( f->bmx_fd, &(f->bmx_tpos) ) != 0) return(-1); } /* * If previous i/o request was a write request make sure the list * is flushed before getting the position. */ if ( f->bmx_flag & BMXIO_RW ) { if (f->bmx_flag & BMXIO_EOV == 0) { /* Not doing EOV */ if (f->bmx_lstptr->state == 0 && f->bmx_lstptr->bytes != 0) { /* error if we just wrote part of a record */ errno = FDC_ERR_NOTREC; return(-1); } else { if (__bmxflush(f) < 0) return(-1); } /* A sync is REQUIRED on Model D IOS systems. */ /* Do it for all systems. */ if (_tape_sync(f->bmx_fd) < 0) return(-1); } else { /* Flushing out the data in the library buffers, or doing * the sync could cause us to hit EOV. Call _bmx_gtpos because * it knows what to do about EOV. */ if (_bmx_gtpos(f, NULL, 0, 1) != 0) return(-1); } } else { /* wait for i/o to be quiet */ if (_bmx_eovq(f) < 0) return(-1); } return(ioctl(f->bmx_fd, TPC_GABS, blockid)); }
_er90b_gettp(struct fdinfo *fio, long *pa, long palen, long synch) { ER90BYT *f; struct tsdata tsdata; int vsn[MAXVSN]; f = (ER90BYT *)fio->lyr_info; if ( f->tpos ) { if( _tape_tpwait( f->fd, &(f->tpos) ) != 0) return(-1); } if (synch == 1 && fio->rwflag == WRITIN) { if(_tape_sync(f->fd) != 0) return(-1); } if( _tape_tptsi (&(f->tsireq), &tsdata, vsn) != 0) return(-1); _tape_gtpos(&tsdata, vsn, 0, pa, palen); return(0); }
int _er90b_pos(struct fdinfo *fio, int cmd, long *arg, int len, struct ffsw *stat) { int ret; ER90BYT *f; struct dmn_comm pos; struct ctl_abspos ctl; struct ffp_settp_s *spos; f = (ER90BYT *)fio->lyr_info; /* The caller is responsible for waiting for outstanding I/O */ if (f->tpos) { if ((ret = _tape_tpwait(f->fd, &(f->tpos))) != 0) return(-1); } switch(cmd) { #ifdef _CRAYMPP case FP_SETTP: spos = (struct ffp_settp_s *)arg; if (_er90b_stpos(fio, spos->ffp_nbs_p, spos->ffp_nb, spos->ffp_nvs_p, spos->ffp_nv, spos->ffp_vi)) ERETURN(stat,errno,0); fio->rwflag = POSITIN; break; #endif #ifndef _CRAYMPP case FP_GETPOS: if (len < 4) { ERETURN(stat, FEBIOSNT, 0); } if (fio->rwflag == WRITIN) { if (_tape_sync(f->fd) != 0) { ERETURN(stat, errno, 0); } } else if (fio->rwflag == READIN) { /* The TPC_GABS ioctl does account for */ /* data in the controller buffer, but does */ /* not account for data in the system buffer */ /* So, we do a position request to take care */ /* of that. */ if (_er90b_relpos(f->fd,0) < 0) ERETURN(stat, errno, 0); fio->rwflag = POSITIN; } if (ioctl(f->fd, TPC_GABS, &ctl) < 0) ERETURN(stat, errno, 0); *arg = ctl.datablock; *(arg+1) = ctl.absaddr; *(arg+2) = ctl.partition; *(arg+3) = ctl.filesec; break; case FP_SETPOS: if (len < 4) { ERETURN(stat, FEBIOSNT, 0); } ctl.datablock = *arg; ctl.absaddr = *(arg+1); ctl.partition = *(arg+2); ctl.filesec = *(arg+3); pos.POS_REQ = TR_PABS; pos.POS_ABSADDR = (int)&ctl; if (ioctl(f->fd, TPC_DMN_REQ, &pos) < 0) ERETURN(stat, errno, 0); if (ioctl(f->fd, TPC_DMN_REP, &pos) < 0) ERETURN(stat, errno, 0); if (pos.POS_REP != 0) { ERETURN(stat, pos.POS_REP, 0); } fio->rwflag = POSITIN; break; case FP_RSEEK: if (_er90b_relpos(f->fd,*(arg)) < 0) ERETURN(stat, errno, 0); fio->rwflag = POSITIN; break; case FP_GABS: /* This relies on struct ffp_pos matching ctl_abspos */ if (fio->rwflag == WRITIN) { if (_tape_sync(f->fd) != 0) { ERETURN(stat, errno, 0); } } if (ioctl(f->fd, TPC_GABS, arg) < 0) ERETURN(stat, errno, 0); break; case FP_SABS: pos.POS_REQ = TR_PABS; pos.POS_ABSADDR = (int)arg; if (ioctl(f->fd, TPC_DMN_REQ, &pos) < 0) ERETURN(stat, errno, 0); if (ioctl(f->fd, TPC_DMN_REP, &pos) < 0) ERETURN(stat, errno, 0); if (pos.POS_REP != 0) { ERETURN(stat, pos.POS_REP, 0); } fio->rwflag = POSITIN; break; #endif default: ERETURN(stat, FDC_ERR_NOSUP, 0); } return(0); }