Nut/OS  4.10.3
API Reference
phatio.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00062 #include <errno.h>
00063 
00064 #include <fs/fs.h>
00065 
00066 #include <fs/phatfs.h>
00067 #include <fs/phatvol.h>
00068 #include <dev/blockdev.h>
00069 #include <fs/phatio.h>
00070 
00071 #include <sys/event.h>
00072 
00073 #if 0
00074 /* Use for local debugging. */
00075 #define NUTDEBUG
00076 #include <stdio.h>
00077 #endif
00078 
00083 
00094 int PhatSectorFlush(NUTDEVICE * dev, int bufnum)
00095 {
00096     BLKPAR_SEEK pars;
00097     int sbn;
00098     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00099     NUTFILE *blkmnt = dev->dev_icb;
00100     NUTDEVICE *blkdev = blkmnt->nf_dev;
00101 
00102     if (bufnum < 0) {
00103         sbn = 0;
00104 #if PHAT_SECTOR_BUFFERS
00105         bufnum = PHAT_SECTOR_BUFFERS - 1;
00106 #else
00107         bufnum = 0;
00108 #endif
00109     }
00110     else {
00111         sbn = bufnum;
00112     }
00113 
00114     while (sbn <= bufnum) {
00115         if (vol->vol_buf[sbn].sect_dirty) {
00116             pars.par_nfp = blkmnt;
00117             pars.par_blknum = vol->vol_buf[sbn].sect_num;
00118             if ((*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_SEEK, &pars)) {
00119                 errno = EIO;
00120                 return -1;
00121             }
00122             if ((*blkdev->dev_write) (blkmnt, vol->vol_buf[sbn].sect_data, 1) != 1) {
00123                 errno = EIO;
00124                 return -1;
00125             }
00126             vol->vol_buf[sbn].sect_dirty = 0;
00127         }
00128         sbn++;
00129     }
00130     return 0;
00131 }
00132 
00144 int PhatSectorRead(NUTFILE * blkmnt, uint32_t sect, uint8_t * buf)
00145 {
00146     BLKPAR_SEEK pars;
00147     NUTDEVICE *blkdev = blkmnt->nf_dev;
00148 
00149     /* Set the block device's sector position. */
00150     pars.par_nfp = blkmnt;
00151     pars.par_blknum = sect;
00152     if ((*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_SEEK, &pars)) {
00153         errno = EIO;
00154         return -1;
00155     }
00156 
00157     /* Read a single block from the device. */
00158     if ((*blkdev->dev_read) (blkmnt, buf, 1) != 1) {
00159         errno = EIO;
00160         return -1;
00161     }
00162     return 0;
00163 }
00164 
00165 /*
00166  * \param dev Specifies the file system device.
00167  * \return Buffer number on success, -1 on failures.
00168  */
00169 int PhatSectorLoad(NUTDEVICE * dev, uint32_t sect)
00170 {
00171     int sbn;
00172     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00173 
00174     /* Gain mutex access. */
00175     NutEventWait(&vol->vol_iomutex, 0);
00176 
00177 #if PHAT_SECTOR_BUFFERS
00178     for (sbn = 0; sbn < PHAT_SECTOR_BUFFERS; sbn++) {
00179         if (vol->vol_buf[sbn].sect_num == sect) {
00180             vol->vol_usenext = sbn;
00181             /* Release mutex access. */
00182             NutEventPostAsync(&vol->vol_iomutex);
00183             return sbn;
00184         }
00185     }
00186 
00187     /* Sector not loaded. Use round robin to select a buffer. */
00188     vol->vol_usenext++;
00189     if (vol->vol_usenext >= PHAT_SECTOR_BUFFERS) {
00190         vol->vol_usenext = 0;
00191     }
00192     sbn = vol->vol_usenext;
00193 #else
00194     sbn = 0;
00195     if (vol->vol_buf[sbn].sect_num == sect) {
00196         /* Release mutex access. */
00197         NutEventPostAsync(&vol->vol_iomutex);
00198         return sbn;
00199     }
00200 #endif
00201 
00202     if (PhatSectorFlush(dev, sbn)) {
00203         sbn = -1;
00204     }
00205     else if (PhatSectorRead(dev->dev_icb, sect, vol->vol_buf[sbn].sect_data)) {
00206         sbn = -1;
00207     }
00208     else {
00209         vol->vol_buf[sbn].sect_num = sect;
00210     }
00211 
00212     /* Release mutex access. */
00213     NutEventPostAsync(&vol->vol_iomutex);
00214 
00215     return sbn;
00216 }
00217