| 1 | /*!
 | 
|---|
| 2 |    \file write_block.c
 | 
|---|
| 3 |    \ingroup (PSIO)
 | 
|---|
| 4 | */
 | 
|---|
| 5 |  
 | 
|---|
| 6 | #include <stdlib.h>
 | 
|---|
| 7 | #include <string.h>
 | 
|---|
| 8 | #include <util/psi3/libpsio/psio.h>
 | 
|---|
| 9 | 
 | 
|---|
| 10 | namespace psi3 {
 | 
|---|
| 11 | namespace libpsio {
 | 
|---|
| 12 | 
 | 
|---|
| 13 | /*!
 | 
|---|
| 14 | ** PSIO_WRITE_BLOCK(): 
 | 
|---|
| 15 | **
 | 
|---|
| 16 | ** \ingroup (PSIO)
 | 
|---|
| 17 | */
 | 
|---|
| 18 | 
 | 
|---|
| 19 | int psio_write_block(unsigned int unit, char *key, char *buffer, ULI blksiz,
 | 
|---|
| 20 |                      ULI start_blk, ULI  end_blk)
 | 
|---|
| 21 | {
 | 
|---|
| 22 |   ULI size, shift;
 | 
|---|
| 23 |   psio_ud *this_unit;
 | 
|---|
| 24 |   psio_tocentry *this_entry, *last_entry;
 | 
|---|
| 25 |   psio_address sadd, eadd;
 | 
|---|
| 26 | 
 | 
|---|
| 27 |   this_unit = &(psio_unit[unit]);
 | 
|---|
| 28 | 
 | 
|---|
| 29 |   /* Find the entry in the TOC */
 | 
|---|
| 30 |   this_entry = psio_tocscan(unit, key);
 | 
|---|
| 31 | 
 | 
|---|
| 32 |   if(this_entry == NULL) { /* New TOC entry */
 | 
|---|
| 33 |       if(start_blk) psio_error(unit,PSIO_ERROR_BLKSTART);
 | 
|---|
| 34 | 
 | 
|---|
| 35 |       this_entry = (psio_tocentry *) malloc(sizeof(psio_tocentry));
 | 
|---|
| 36 |       strcpy(this_entry->key,key);
 | 
|---|
| 37 |       this_entry->next = NULL;
 | 
|---|
| 38 |       this_entry->last = NULL;
 | 
|---|
| 39 | 
 | 
|---|
| 40 |       /* Compute the address of the entry */
 | 
|---|
| 41 |       if(!(this_unit->toclen)) { /* First TOC entry */
 | 
|---|
| 42 |           this_entry->sadd.page = 0;
 | 
|---|
| 43 |           this_entry->sadd.offset = 3*sizeof(ULI);
 | 
|---|
| 44 | 
 | 
|---|
| 45 |           this_unit->toc = this_entry;
 | 
|---|
| 46 |         }
 | 
|---|
| 47 |       else {  /* Use ending address from last TOC entry */
 | 
|---|
| 48 |           last_entry = psio_toclast(unit);
 | 
|---|
| 49 |           this_entry->sadd = last_entry->eadd;
 | 
|---|
| 50 | 
 | 
|---|
| 51 |           last_entry->next = this_entry;
 | 
|---|
| 52 |           this_entry->last = last_entry;
 | 
|---|
| 53 |         }
 | 
|---|
| 54 | 
 | 
|---|
| 55 |       /* Data for the write call */
 | 
|---|
| 56 |       size = (end_blk - start_blk + 1)*blksiz;
 | 
|---|
| 57 |       sadd = this_entry->sadd;
 | 
|---|
| 58 | 
 | 
|---|
| 59 |       /* Set end address for this_entry */
 | 
|---|
| 60 |       this_entry->eadd = psio_get_address(this_entry->sadd, size);
 | 
|---|
| 61 | 
 | 
|---|
| 62 |       /* Update the unit's TOC stats */
 | 
|---|
| 63 |       this_unit->toclen++;
 | 
|---|
| 64 |       this_unit->tocaddress = this_entry->eadd;
 | 
|---|
| 65 |     }
 | 
|---|
| 66 |   else { /* Old TOC entry */
 | 
|---|
| 67 | 
 | 
|---|
| 68 |       size = (end_blk - start_blk + 1) * blksiz; /* The total buffer size */
 | 
|---|
| 69 |       shift = start_blk * blksiz; /* Number of bytes to shift from start */
 | 
|---|
| 70 | 
 | 
|---|
| 71 |       /* Compute the starting page and offset for the block */
 | 
|---|
| 72 |       sadd = psio_get_address(this_entry->sadd, shift);
 | 
|---|
| 73 | 
 | 
|---|
| 74 |       /* Make sure this block doesn't start past the end of the entry */
 | 
|---|
| 75 |       if(sadd.page > this_entry->eadd.page)
 | 
|---|
| 76 |           psio_error(unit,PSIO_ERROR_BLKSTART);
 | 
|---|
| 77 |       else if((sadd.page == this_entry->eadd.page) &&
 | 
|---|
| 78 |               (sadd.offset > this_entry->eadd.offset))
 | 
|---|
| 79 |           psio_error(unit,PSIO_ERROR_BLKSTART);
 | 
|---|
| 80 | 
 | 
|---|
| 81 |       /* Compute the new ending address for the entry, if necessary */
 | 
|---|
| 82 |       eadd = psio_get_address(sadd, size);
 | 
|---|
| 83 |       if(eadd.page > this_entry->eadd.page) {
 | 
|---|
| 84 |           this_entry->eadd = this_unit->tocaddress = eadd;
 | 
|---|
| 85 |         }
 | 
|---|
| 86 |       else if((eadd.page == this_entry->eadd.page) &&
 | 
|---|
| 87 |               (eadd.offset > this_entry->eadd.offset))
 | 
|---|
| 88 |           {
 | 
|---|
| 89 |             this_entry->eadd = eadd;
 | 
|---|
| 90 |             this_unit->tocaddress = eadd;
 | 
|---|
| 91 |           }
 | 
|---|
| 92 |     }
 | 
|---|
| 93 | 
 | 
|---|
| 94 |   /* Now write the actual data to the unit */
 | 
|---|
| 95 |   psio_rw(unit, buffer, sadd, size, 1);
 | 
|---|
| 96 | 
 | 
|---|
| 97 |   return(0);
 | 
|---|
| 98 | }
 | 
|---|
| 99 | 
 | 
|---|
| 100 | }
 | 
|---|
| 101 | }
 | 
|---|