| 1 | /*!
 | 
|---|
| 2 |    \file rw.c
 | 
|---|
| 3 |    \ingroup (PSIO)
 | 
|---|
| 4 | */
 | 
|---|
| 5 | 
 | 
|---|
| 6 | #include <stdio.h>
 | 
|---|
| 7 | #include <unistd.h>
 | 
|---|
| 8 | #include <util/psi3/libpsio/psio.h>
 | 
|---|
| 9 | 
 | 
|---|
| 10 | namespace psi3 {
 | 
|---|
| 11 | namespace libpsio {
 | 
|---|
| 12 | 
 | 
|---|
| 13 | /*!
 | 
|---|
| 14 | ** PSIO_RW()
 | 
|---|
| 15 | **
 | 
|---|
| 16 | ** \ingroup (PSIO)
 | 
|---|
| 17 | */
 | 
|---|
| 18 | int psio_rw(unsigned int unit, char *buffer, psio_address address, ULI size, int wrt)
 | 
|---|
| 19 | {
 | 
|---|
| 20 |   int errcod;
 | 
|---|
| 21 |   unsigned int i;
 | 
|---|
| 22 |   ULI errcod_uli;
 | 
|---|
| 23 |   ULI page, offset;
 | 
|---|
| 24 |   ULI buf_offset;
 | 
|---|
| 25 |   ULI this_page, this_page_max, this_page_total;
 | 
|---|
| 26 |   unsigned int first_vol, this_vol, numvols;
 | 
|---|
| 27 |   ULI bytes_left, num_full_pages;
 | 
|---|
| 28 |   psio_ud *this_unit;
 | 
|---|
| 29 | 
 | 
|---|
| 30 |   this_unit = &(psio_unit[unit]);
 | 
|---|
| 31 |   numvols = this_unit->numvols;
 | 
|---|
| 32 |   page = address.page;
 | 
|---|
| 33 |   offset = address.offset;
 | 
|---|
| 34 |   
 | 
|---|
| 35 |   /* Seek all volumes to correct starting positions */
 | 
|---|
| 36 |   first_vol = page % numvols;
 | 
|---|
| 37 |   errcod = psio_volseek(&(this_unit->vol[first_vol]), page, offset, numvols);
 | 
|---|
| 38 |   if(errcod == -1) psio_error(unit,PSIO_ERROR_LSEEK);
 | 
|---|
| 39 |   for(i=1,this_page=page+1; i < numvols; i++,this_page++) {
 | 
|---|
| 40 |       this_vol = this_page % numvols;
 | 
|---|
| 41 |       errcod = psio_volseek(&(this_unit->vol[this_vol]), this_page, 
 | 
|---|
| 42 |                             (ULI) 0, numvols);
 | 
|---|
| 43 |       if(errcod == -1) psio_error(unit,PSIO_ERROR_LSEEK);
 | 
|---|
| 44 |     }
 | 
|---|
| 45 | 
 | 
|---|
| 46 |   /* Number of bytes left on the first page */
 | 
|---|
| 47 |   this_page_max = PSIO_PAGELEN - offset;
 | 
|---|
| 48 | 
 | 
|---|
| 49 |   /* If we have enough room on this page, use it */
 | 
|---|
| 50 |   if(size <= this_page_max)  this_page_total = size;
 | 
|---|
| 51 |   else this_page_total = this_page_max;
 | 
|---|
| 52 | 
 | 
|---|
| 53 |   buf_offset = 0;
 | 
|---|
| 54 |   if(wrt) {
 | 
|---|
| 55 |       errcod_uli = write(this_unit->vol[first_vol].stream, &(buffer[buf_offset]),
 | 
|---|
| 56 |                      this_page_total);
 | 
|---|
| 57 |       if(errcod_uli != this_page_total) psio_error(unit,PSIO_ERROR_WRITE);
 | 
|---|
| 58 |     }
 | 
|---|
| 59 |   else {
 | 
|---|
| 60 |       errcod_uli = read(this_unit->vol[first_vol].stream, &(buffer[buf_offset]),
 | 
|---|
| 61 |                     this_page_total);
 | 
|---|
| 62 |       if(errcod_uli != this_page_total) psio_error(unit,PSIO_ERROR_READ);
 | 
|---|
| 63 |     }
 | 
|---|
| 64 | 
 | 
|---|
| 65 |   /* Total number of bytes remaining to be read/written */
 | 
|---|
| 66 |   bytes_left = size - this_page_total;
 | 
|---|
| 67 | 
 | 
|---|
| 68 |   /* Read/Write all the full pages */
 | 
|---|
| 69 |   num_full_pages = bytes_left/PSIO_PAGELEN;  
 | 
|---|
| 70 |   buf_offset += this_page_total;
 | 
|---|
| 71 |   for(i=0,this_page=page+1; i < num_full_pages; i++,this_page++) {
 | 
|---|
| 72 |       this_vol = this_page % numvols;
 | 
|---|
| 73 |       this_page_total = PSIO_PAGELEN;
 | 
|---|
| 74 |       if(wrt) {
 | 
|---|
| 75 |           errcod_uli = write(this_unit->vol[this_vol].stream, &(buffer[buf_offset]),
 | 
|---|
| 76 |                          this_page_total);
 | 
|---|
| 77 |           if(errcod_uli != this_page_total) psio_error(unit,PSIO_ERROR_WRITE);
 | 
|---|
| 78 |         }
 | 
|---|
| 79 |       else {
 | 
|---|
| 80 |           errcod_uli = read(this_unit->vol[this_vol].stream, &(buffer[buf_offset]),
 | 
|---|
| 81 |                         this_page_total);
 | 
|---|
| 82 |           if(errcod_uli != this_page_total) psio_error(unit,PSIO_ERROR_READ);
 | 
|---|
| 83 |         }
 | 
|---|
| 84 |       buf_offset += this_page_total;
 | 
|---|
| 85 |     }
 | 
|---|
| 86 | 
 | 
|---|
| 87 |   /* Read/Write the final partial page */
 | 
|---|
| 88 |   bytes_left -= num_full_pages * PSIO_PAGELEN;
 | 
|---|
| 89 |   this_vol = this_page % numvols;
 | 
|---|
| 90 |   if(bytes_left) {
 | 
|---|
| 91 |       if(wrt) {
 | 
|---|
| 92 |           errcod_uli = write(this_unit->vol[this_vol].stream, &(buffer[buf_offset]),
 | 
|---|
| 93 |                          bytes_left);
 | 
|---|
| 94 |           if(errcod_uli != bytes_left) psio_error(unit,PSIO_ERROR_WRITE);
 | 
|---|
| 95 |         }
 | 
|---|
| 96 |       else {
 | 
|---|
| 97 |           errcod_uli = read(this_unit->vol[this_vol].stream, &(buffer[buf_offset]),
 | 
|---|
| 98 |                          bytes_left);
 | 
|---|
| 99 |           if(errcod_uli != bytes_left) psio_error(unit,PSIO_ERROR_READ);
 | 
|---|
| 100 |         }
 | 
|---|
| 101 |     }
 | 
|---|
| 102 | 
 | 
|---|
| 103 |   return(0);
 | 
|---|
| 104 | }
 | 
|---|
| 105 | 
 | 
|---|
| 106 | }
 | 
|---|
| 107 | }
 | 
|---|