home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / disk / diskIO.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-10  |  10.2 KB  |  327 lines

  1. /* 
  2.  * diskIO.c --
  3.  *
  4.  *    Routines to do I/O to a raw disk.
  5.  *
  6.  * Copyright (C) 1987 Regents of the University of California
  7.  * All rights reserved.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/lib/disk/RCS/diskIO.c,v 1.10 91/12/16 19:29:55 voelker Exp Locker: eklee $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21. #include "disk.h"
  22. #include <stdio.h>
  23. #include <errno.h>
  24. #include <sys/file.h>
  25.  
  26.  
  27. /*
  28.  *----------------------------------------------------------------------
  29.  *
  30.  * Disk_SectorRead --
  31.  *    Read sectors from the disk file at a specified offset.  This combines
  32.  *    an Ioc_Reposition with the read.
  33.  *
  34.  * Results:
  35.  *    0 if could read the sector, -1 if could not.  If couldn't read
  36.  *    the disk then the error is stored in errno.
  37.  *
  38.  * Side effects:
  39.  *    Reposition the disk file's stream pointer and *buffer filled
  40.  *    with data from the disk.
  41.  *
  42.  *----------------------------------------------------------------------
  43.  */
  44. int
  45. Disk_SectorRead(openFileID, firstSector, numSectors, buffer)
  46.     int        openFileID;    /* Handle on raw disk */
  47.     int        firstSector;    /* First sector to read */
  48.     int        numSectors;    /* The number of sectors to read */
  49.     Address    buffer;        /* The buffer to read into */
  50. {
  51.     int amountRead;
  52.  
  53.     if (lseek(openFileID, (long) (firstSector * DEV_BYTES_PER_SECTOR), L_SET) 
  54.     < (long) 0) {
  55.     perror("Disk_SectorRead: lseek failed");
  56.     return(-1);
  57.     }
  58.     amountRead = read(openFileID, buffer, DEV_BYTES_PER_SECTOR * numSectors);
  59.     if (amountRead < 0) {
  60.     perror("Disk_SectorRead: failed");
  61.     fprintf(stderr, "Disk_SectorRead: %d = read(%d, 0x%x, %d)\n",
  62.         amountRead, openFileID, buffer,
  63.         DEV_BYTES_PER_SECTOR * numSectors);
  64.     return(-1);
  65.     } else if (amountRead != DEV_BYTES_PER_SECTOR * numSectors) {
  66.     /*
  67.      * short read or EOF
  68.      */
  69.     fprintf(stderr, "Disk_SectorRead: %d = read(%d, 0x%x, %d)\n",
  70.         amountRead, openFileID, buffer,
  71.         DEV_BYTES_PER_SECTOR * numSectors);
  72.     errno = 0;
  73.     return(-1);
  74.     }
  75.     return(0);
  76. }
  77.  
  78. /*
  79.  *----------------------------------------------------------------------
  80.  *
  81.  * Disk_SectorWrite --
  82.  *    Write sectors to the disk file at a specified offset.  This combines
  83.  *    an Ioc_Reposition with the write.
  84.  *
  85.  * Results:
  86.  *    0 if could write the disk, -1 if could not.  If couldn't read the
  87.  *    disk then the error number is stored in errno.
  88.  *
  89.  * Side effects:
  90.  *    The write.
  91.  *
  92.  *----------------------------------------------------------------------
  93.  */
  94. int
  95. Disk_SectorWrite(openFileID, firstSector, numSectors, buffer)
  96.     int        openFileID;    /* Handle on raw disk */
  97.     int        firstSector;    /* First sector to read */
  98.     int        numSectors;    /* The number of sectors to read */
  99.     Address    buffer;        /* The buffer to read into */
  100. {
  101.     int amountWritten;
  102.  
  103.     if (lseek(openFileID, (long) (firstSector * DEV_BYTES_PER_SECTOR), L_SET) 
  104.     == (long) -1) {
  105.     perror("Disk_SectorWrite: lseek failed");
  106.     fprintf(stderr, "fd = %d, offset = %ld, whence= %d\n",
  107.         openFileID, firstSector * DEV_BYTES_PER_SECTOR, L_SET);
  108.     return(-1);
  109.     }
  110.     amountWritten = write(openFileID, buffer, 
  111.               DEV_BYTES_PER_SECTOR * numSectors);
  112.     if (amountWritten < 0) {
  113.     perror("Disk_SectorWrite: write failed");
  114.     fprintf(stderr, "fd = %d, buffer= 0x%08x, cnt = %d firstSector = %d\n",
  115.         openFileID, buffer, DEV_BYTES_PER_SECTOR * numSectors,
  116.         firstSector);
  117.  
  118.     return(-1);
  119.     } else if (amountWritten != DEV_BYTES_PER_SECTOR * numSectors) {
  120.     /*
  121.      * short write or EOF
  122.      */
  123.     errno = 0;
  124.     return(-1);
  125.     }
  126.     return(0);
  127. }
  128.  
  129.  
  130. /*
  131.  *----------------------------------------------------------------------
  132.  *
  133.  * Disk_BlockRead --
  134.  *    Read blocks to the disk file at a specified block offset.
  135.  *    This has to use the disk geometry information to figure out
  136.  *    what disk sectors correspond to the block.
  137.  *
  138.  * Results:
  139.  *    0 if could read the block, -1 if could not.  If couldn't read the block
  140.  *    the the error is stored in errno.
  141.  *
  142.  * Side effects:
  143.  *    *buffer is filled with the data from the disk.
  144.  *
  145.  *----------------------------------------------------------------------
  146.  */
  147. int
  148. Disk_BlockRead(openFileID, headerPtr, firstBlock, numBlocks, buffer)
  149.     int            openFileID;    /* Handle on raw disk */
  150.     Ofs_DomainHeader    *headerPtr;    /* Domain header with geometry
  151.                      * information */
  152.     int            firstBlock;    /* First block to read */
  153.     int            numBlocks;    /* The number of blocks to read */
  154.     Address        buffer;        /* The buffer to read into */
  155. {
  156.     register Ofs_Geometry *geoPtr;
  157.     register int blockIndex;
  158.     register int cylinder;
  159.     register int rotationalSet;
  160.     register int blockNumber;
  161.     int firstSector;
  162.  
  163.     geoPtr = &headerPtr->geometry;
  164.     for (blockIndex = 0 ; blockIndex < numBlocks ; blockIndex++) {
  165.     blockNumber    = firstBlock + blockIndex;
  166.     cylinder    = blockNumber / geoPtr->blocksPerCylinder;
  167.     if (geoPtr->rotSetsPerCyl > 0) {
  168.         /*
  169.          * Original mapping scheme using rotational sets.
  170.          */
  171.         blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  172.         rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  173.         blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  174.     
  175.         firstSector = geoPtr->sectorsPerTrack * geoPtr->numHeads * 
  176.              cylinder +
  177.              geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  178.              rotationalSet + geoPtr->blockOffset[blockNumber];
  179.     } else if (geoPtr->rotSetsPerCyl == OFS_SCSI_MAPPING){
  180.         /*
  181.          * New mapping for scsi devices.
  182.          */
  183.         firstSector = geoPtr->sectorsPerTrack * geoPtr->numHeads * 
  184.             cylinder +
  185.             blockNumber * DISK_SECTORS_PER_BLOCK - 
  186.             cylinder * 
  187.             geoPtr->blocksPerCylinder * DISK_SECTORS_PER_BLOCK;
  188.     } else {
  189.         return -1;
  190.     }
  191.     if (Disk_SectorRead(openFileID, firstSector,
  192.                  DISK_SECTORS_PER_BLOCK, buffer) < 0) {
  193.         return(-1);
  194.     }
  195.     buffer += FS_BLOCK_SIZE;
  196.     }
  197.     return(0);
  198. }
  199.  
  200. /*
  201.  *----------------------------------------------------------------------
  202.  *
  203.  * Disk_BadBlockRead --
  204.  *    Read 1 block a sector at a time, returning a bitmap corresponding
  205.  *    to the blocks that were read successfully.
  206.  *    This has to use the disk geometry information to figure out
  207.  *    what disk sectors correspond to the block.
  208.  *
  209.  * Results:
  210.  *    The bitmask of valid sectors is returned.
  211.  *
  212.  * Side effects:
  213.  *    None.
  214.  *
  215.  *----------------------------------------------------------------------
  216.  */
  217. int
  218. Disk_BadBlockRead(openFileID, headerPtr, blockNumber, buffer)
  219.     int openFileID;    /* Handle on raw disk */
  220.     Ofs_DomainHeader *headerPtr;/* Domain header with geometry information */
  221.     int blockNumber;    /* Block to read */
  222.     Address buffer;    /* The buffer to read into */
  223. {
  224.     ReturnStatus status;
  225.     register Ofs_Geometry *geoPtr;
  226.     register int sectorIndex;
  227.     register int cylinder;
  228.     register int rotationalSet;
  229.     int firstSector;
  230.     int valid = 0;        /* Assumes <= 32 sectors/block */
  231.  
  232.     geoPtr = &headerPtr->geometry;
  233.     cylinder    = blockNumber / geoPtr->blocksPerCylinder;
  234.     blockNumber    -= cylinder * geoPtr->blocksPerCylinder;
  235.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  236.     blockNumber    -= rotationalSet * geoPtr->blocksPerRotSet;
  237.  
  238.     firstSector = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder + 
  239.         geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet * rotationalSet +
  240.         geoPtr->blockOffset[blockNumber];
  241.     for (sectorIndex = 0; sectorIndex < DISK_SECTORS_PER_BLOCK; sectorIndex++) {
  242.     if (Disk_SectorRead(openFileID, firstSector + sectorIndex, 
  243.                 1, buffer) >= 0) {
  244.         valid |= (1 << sectorIndex);
  245.     }
  246.         buffer += DEV_BYTES_PER_SECTOR;
  247.     }
  248.     return(valid);
  249. }
  250.  
  251. /*
  252.  *----------------------------------------------------------------------
  253.  *
  254.  * Disk_BlockWrite --
  255.  *    Write blocks to the disk file at a specified block offset.
  256.  *    This has to use the disk geometry information to figure out
  257.  *    what disk sectors correspond to the block.
  258.  *    Write blocks individually if a hard error occurs during the write
  259.  *    of the entire block.
  260.  *
  261.  *    Note: ignores the error condition otherwise, so if two blocks
  262.  *    are to be written, everything but unwritable sectors will be written
  263.  *    and the error for the unwritable sector(s) would be returned.
  264.  *
  265.  * Results:
  266.  *    0 if could write the block, -1 if could not.  If couldn't write the
  267.  *    block then the error is stored in errno.
  268.  *
  269.  * Side effects:
  270.  *    None.
  271.  *
  272.  *----------------------------------------------------------------------
  273.  */
  274. int
  275. Disk_BlockWrite(openFileID, headerPtr, firstBlock, numBlocks, buffer)
  276.     int            openFileID;    /* Handle on raw disk */
  277.     Ofs_DomainHeader    *headerPtr;    /* Domain header with geometry
  278.                      * information */
  279.     int            firstBlock;    /* First block to read */
  280.     int            numBlocks;    /* The number of blocks to read */
  281.     Address        buffer;        /* The buffer to read into */
  282. {
  283.     register Ofs_Geometry *geoPtr;
  284.     register int blockIndex;    /* Loop counter */
  285.     register int cylinder;    /* Cylinder within domain */
  286.     register int rotationalSet;    /* Rotational Set within cylinder */
  287.     register int blockNumber;    /* Block number within rotational set */
  288.     int firstSector;
  289.  
  290.     geoPtr = &headerPtr->geometry;
  291.     for (blockIndex = 0 ; blockIndex < numBlocks ; blockIndex++) {
  292.     blockNumber    = firstBlock + blockIndex;
  293.     cylinder    = blockNumber / geoPtr->blocksPerCylinder;
  294.     if (geoPtr->rotSetsPerCyl > 0) {
  295.         /*
  296.          * Original mapping scheme using rotational sets.
  297.          */
  298.         blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  299.         rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  300.         blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  301.     
  302.         firstSector = geoPtr->sectorsPerTrack * geoPtr->numHeads * 
  303.              cylinder +
  304.              geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  305.              rotationalSet + geoPtr->blockOffset[blockNumber];
  306.     } else if (geoPtr->rotSetsPerCyl == OFS_SCSI_MAPPING){
  307.         /*
  308.          * New mapping for scsi devices.
  309.          */
  310.         firstSector = geoPtr->sectorsPerTrack * geoPtr->numHeads * 
  311.             cylinder +
  312.             blockNumber * DISK_SECTORS_PER_BLOCK - 
  313.             cylinder * 
  314.             geoPtr->blocksPerCylinder * DISK_SECTORS_PER_BLOCK;
  315.     } else {
  316.         return -1;
  317.     }
  318.     if (Disk_SectorWrite(openFileID, firstSector,
  319.                  DISK_SECTORS_PER_BLOCK, buffer) < 0) {
  320.         return(-1);
  321.     }
  322.     buffer += FS_BLOCK_SIZE;
  323.     }
  324.     return(0);
  325. }
  326.  
  327.