Changeset 1787e527 in mainline for uspace/srv


Ignore:
Timestamp:
2009-11-16T21:22:54Z (15 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5ebdf94
Parents:
fcbd1be (diff), 9c70ed6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merged with head (unstable)

Location:
uspace/srv
Files:
42 added
47 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/ata_bd/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
     32.PHONY: all clean
    3233
    33 LIBC_PREFIX = ../../../lib/libc
    34 SOFTINT_PREFIX = ../../../lib/softint
    35 
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 
    38 LIBS = $(LIBC_PREFIX)/libc.a
    39 
    40 ## Sources
    41 #
    42 
    43 OUTPUT = ata_bd
    44 SOURCES = \
    45         ata_bd.c
    46 
    47 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    48 
    49 .PHONY: all clean depend disasm
    50 
    51 all: $(OUTPUT) $(OUTPUT).disasm
    52 
    53 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5437
    5538clean:
    56         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    57 
    58 depend:
    59         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    60 
    61 $(OUTPUT): $(OBJECTS) $(LIBS)
    62         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    63 
    64 disasm: $(OUTPUT).disasm
    65 
    66 $(OUTPUT).disasm: $(OUTPUT)
    67         $(OBJDUMP) -d $< > $@
    68 
    69 %.o: %.S
    70         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    71 
    72 %.o: %.s
    73         $(AS) $(AFLAGS) $< -o $@
    74 
    75 %.o: %.c
    76         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/bd/ata_bd/ata_bd.c

    rfcbd1be r1787e527  
    3535 * @brief ATA disk driver
    3636 *
    37  * This driver currently works only with CHS addressing and uses PIO.
    38  * Currently based on the (now obsolete) ATA-1, ATA-2 standards.
     37 * This driver supports CHS, 28-bit and 48-bit LBA addressing. It only uses
     38 * PIO transfers. There is no support DMA, the PACKET feature set or any other
     39 * fancy features such as S.M.A.R.T, removable devices, etc.
     40 *
     41 * This driver is based on the ATA-1, ATA-2, ATA-3 and ATA/ATAPI-4 through 7
     42 * standards, as published by the ANSI, NCITS and INCITS standards bodies,
     43 * which are freely available. This driver contains no vendor-specific
     44 * code at this moment.
    3945 *
    4046 * The driver services a single controller which can have up to two disks
     
    5056#include <as.h>
    5157#include <fibril_sync.h>
     58#include <string.h>
    5259#include <devmap.h>
    5360#include <sys/types.h>
     
    5562#include <bool.h>
    5663#include <task.h>
     64#include <macros.h>
    5765
    5866#include "ata_bd.h"
     
    7987static int ata_bd_init(void);
    8088static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
    81 static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size,
     89static int ata_bd_read_blocks(int disk_id, uint64_t ba, size_t cnt,
    8290    void *buf);
    83 static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
     91static int ata_bd_write_blocks(int disk_id, uint64_t ba, size_t cnt,
     92    const void *buf);
     93static int ata_bd_read_block(int disk_id, uint64_t ba, size_t cnt,
    8494    void *buf);
    85 static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
     95static int ata_bd_write_block(int disk_id, uint64_t ba, size_t cnt,
    8696    const void *buf);
    87 static int drive_identify(int drive_id, disk_t *d);
     97static int disk_init(disk_t *d, int disk_id);
     98static int drive_identify(int drive_id, void *buf);
     99static void disk_print_summary(disk_t *d);
     100static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc);
     101static void coord_sc_program(const block_coord_t *bc, uint16_t scnt);
    88102static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus,
    89103    unsigned timeout);
     
    97111        printf(NAME ": ATA disk driver\n");
    98112
    99         printf("I/O address 0x%x\n", cmd_physical);
     113        printf("I/O address 0x%p/0x%p\n", ctl_physical, cmd_physical);
    100114
    101115        if (ata_bd_init() != EOK)
     
    106120                fflush(stdout);
    107121
    108                 rc = drive_identify(i, &disk[i]);
     122                rc = disk_init(&disk[i], i);
    109123
    110124                if (rc == EOK) {
    111                         printf("%u cylinders, %u heads, %u sectors\n",
    112                             disk[i].cylinders, disk[i].heads, disk[i].sectors);
     125                        disk_print_summary(&disk[i]);
    113126                } else {
    114127                        printf("Not found.\n");
     
    147160}
    148161
     162/** Print one-line device summary. */
     163static void disk_print_summary(disk_t *d)
     164{
     165        uint64_t mbytes;
     166
     167        printf("%s: ", d->model);
     168
     169        switch (d->amode) {
     170        case am_chs:
     171                printf("CHS %u cylinders, %u heads, %u sectors",
     172                    disk->geom.cylinders, disk->geom.heads, disk->geom.sectors);
     173                break;
     174        case am_lba28:
     175                printf("LBA-28");
     176                break;
     177        case am_lba48:
     178                printf("LBA-48");
     179                break;
     180        }
     181
     182        printf(" %llu blocks", d->blocks, d->blocks / (2 * 1024));
     183
     184        mbytes = d->blocks / (2 * 1024);
     185        if (mbytes > 0)
     186                printf(" %llu MB.", mbytes);
     187
     188        printf("\n");
     189}
    149190
    150191/** Register driver and enable device I/O. */
     
    190231        int flags;
    191232        int retval;
    192         off_t idx;
    193         size_t size;
     233        uint64_t ba;
     234        size_t cnt;
    194235        int disk_id, i;
    195236
     
    211252        ipc_answer_0(iid, EOK);
    212253
    213         if (!ipc_share_out_receive(&callid, &comm_size, &flags)) {
     254        if (!async_share_out_receive(&callid, &comm_size, &flags)) {
    214255                ipc_answer_0(callid, EHANGUP);
    215256                return;
     
    222263        }
    223264
    224         (void) ipc_share_out_finalize(callid, fs_va);
     265        (void) async_share_out_finalize(callid, fs_va);
    225266
    226267        while (1) {
     
    232273                        ipc_answer_0(callid, EOK);
    233274                        return;
    234                 case BD_READ_BLOCK:
    235                 case BD_WRITE_BLOCK:
    236                         idx = IPC_GET_ARG1(call);
    237                         size = IPC_GET_ARG2(call);
    238                         if (size > comm_size) {
    239                                 retval = EINVAL;
     275                case BD_READ_BLOCKS:
     276                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     277                            IPC_GET_ARG2(call));
     278                        cnt = IPC_GET_ARG3(call);
     279                        if (cnt * block_size > comm_size) {
     280                                retval = ELIMIT;
    240281                                break;
    241282                        }
    242                         retval = ata_bd_rdwr(disk_id, method, idx,
    243                             size, fs_va);
     283                        retval = ata_bd_read_blocks(disk_id, ba, cnt, fs_va);
    244284                        break;
     285                case BD_WRITE_BLOCKS:
     286                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     287                            IPC_GET_ARG2(call));
     288                        cnt = IPC_GET_ARG3(call);
     289                        if (cnt * block_size > comm_size) {
     290                                retval = ELIMIT;
     291                                break;
     292                        }
     293                        retval = ata_bd_write_blocks(disk_id, ba, cnt, fs_va);
     294                        break;
     295                case BD_GET_BLOCK_SIZE:
     296                        ipc_answer_1(callid, EOK, block_size);
     297                        continue;
    245298                default:
    246299                        retval = EINVAL;
     
    251304}
    252305
    253 /** Transfer a logical block from/to the device.
    254  *
    255  * @param disk_id       Device index (0 or 1)
    256  * @param method        @c BD_READ_BLOCK or @c BD_WRITE_BLOCK
    257  * @param blk_idx       Index of the first block.
    258  * @param size          Size of the logical block.
    259  * @param buf           Data buffer.
    260  *
    261  * @return EOK on success, EIO on error.
    262  */
    263 static int ata_bd_rdwr(int disk_id, ipcarg_t method, off_t blk_idx, size_t size,
    264     void *buf)
    265 {
     306/** Initialize a disk.
     307 *
     308 * Probes for a disk, determines its parameters and initializes
     309 * the disk structure.
     310 */
     311static int disk_init(disk_t *d, int disk_id)
     312{
     313        identify_data_t idata;
     314        uint8_t model[40];
     315        uint16_t w;
     316        uint8_t c;
     317        size_t pos, len;
    266318        int rc;
    267         size_t now;
    268 
    269         while (size > 0) {
    270                 now = size < block_size ? size : block_size;
    271                 if (now != block_size)
    272                         return EINVAL;
    273 
    274                 if (method == BD_READ_BLOCK)
    275                         rc = ata_bd_read_block(disk_id, blk_idx, 1, buf);
    276                 else
    277                         rc = ata_bd_write_block(disk_id, blk_idx, 1, buf);
    278 
     319        unsigned i;
     320
     321        rc = drive_identify(disk_id, &idata);
     322        if (rc != EOK) {
     323                d->present = false;
     324                return rc;
     325        }
     326
     327        if ((idata.caps & cap_lba) == 0) {
     328                /* Device only supports CHS addressing. */
     329                d->amode = am_chs;
     330
     331                d->geom.cylinders = idata.cylinders;
     332                d->geom.heads = idata.heads;
     333                d->geom.sectors = idata.sectors;
     334
     335                d->blocks = d->geom.cylinders * d->geom.heads * d->geom.sectors;
     336        } else if ((idata.cmd_set1 & cs1_addr48) == 0) {
     337                /* Device only supports LBA-28 addressing. */
     338                d->amode = am_lba28;
     339
     340                d->geom.cylinders = 0;
     341                d->geom.heads = 0;
     342                d->geom.sectors = 0;
     343
     344                d->blocks =
     345                     (uint32_t) idata.total_lba28_0 |
     346                    ((uint32_t) idata.total_lba28_1 << 16);
     347        } else {
     348                /* Device supports LBA-48 addressing. */
     349                d->amode = am_lba48;
     350
     351                d->geom.cylinders = 0;
     352                d->geom.heads = 0;
     353                d->geom.sectors = 0;
     354
     355                d->blocks =
     356                     (uint64_t) idata.total_lba48_0 |
     357                    ((uint64_t) idata.total_lba48_1 << 16) |
     358                    ((uint64_t) idata.total_lba48_2 << 32) |
     359                    ((uint64_t) idata.total_lba48_3 << 48);
     360        }
     361
     362        /*
     363         * Convert model name to string representation.
     364         */
     365        for (i = 0; i < 20; i++) {
     366                w = idata.model_name[i];
     367                model[2 * i] = w >> 8;
     368                model[2 * i + 1] = w & 0x00ff;
     369        }
     370
     371        len = 40;
     372        while (len > 0 && model[len - 1] == 0x20)
     373                --len;
     374
     375        pos = 0;
     376        for (i = 0; i < len; ++i) {
     377                c = model[i];
     378                if (c >= 0x80) c = '?';
     379
     380                chr_encode(c, d->model, &pos, 40);
     381        }
     382        d->model[pos] = '\0';
     383
     384        d->present = true;
     385        fibril_mutex_initialize(&d->lock);
     386
     387        return EOK;
     388}
     389
     390/** Read multiple blocks from the device. */
     391static int ata_bd_read_blocks(int disk_id, uint64_t ba, size_t cnt,
     392    void *buf) {
     393
     394        int rc;
     395
     396        while (cnt > 0) {
     397                rc = ata_bd_read_block(disk_id, ba, 1, buf);
    279398                if (rc != EOK)
    280399                        return rc;
    281400
     401                ++ba;
     402                --cnt;
    282403                buf += block_size;
    283                 blk_idx++;
    284 
    285                 if (size > block_size)
    286                         size -= block_size;
    287                 else
    288                         size = 0;
     404        }
     405
     406        return EOK;
     407}
     408
     409/** Write multiple blocks to the device. */
     410static int ata_bd_write_blocks(int disk_id, uint64_t ba, size_t cnt,
     411    const void *buf) {
     412
     413        int rc;
     414
     415        while (cnt > 0) {
     416                rc = ata_bd_write_block(disk_id, ba, 1, buf);
     417                if (rc != EOK)
     418                        return rc;
     419
     420                ++ba;
     421                --cnt;
     422                buf += block_size;
    289423        }
    290424
     
    294428/** Issue IDENTIFY command.
    295429 *
    296  * This is used to detect whether an ATA device is present and if so,
    297  * to determine its parameters. The parameters are written to @a d.
     430 * Reads @c identify data into the provided buffer. This is used to detect
     431 * whether an ATA device is present and if so, to determine its parameters.
    298432 *
    299433 * @param disk_id       Device ID, 0 or 1.
    300  * @param d             Device structure to store parameters in.
    301  */
    302 static int drive_identify(int disk_id, disk_t *d)
     434 * @param buf           Pointer to a 512-byte buffer.
     435 */
     436static int drive_identify(int disk_id, void *buf)
    303437{
    304438        uint16_t data;
     
    308442
    309443        drv_head = ((disk_id != 0) ? DHR_DRV : 0);
    310         d->present = false;
    311444
    312445        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
     
    330463
    331464        if ((status & SR_DRQ) != 0) {
    332 //              for (i = 0; i < block_size / 2; i++) {
    333 //                      data = pio_read_16(&cmd->data_port);
    334 //                      ((uint16_t *) buf)[i] = data;
    335 //              }
    336 
    337                 for (i = 0; i < block_size / 2; i++) {
    338                         data = pio_read_16(&cmd->data_port);
    339 
    340                         switch (i) {
    341                         case 1: d->cylinders = data; break;
    342                         case 3: d->heads = data; break;
    343                         case 6: d->sectors = data; break;
    344                         }
    345                 }
    346         }
    347 
    348         if ((status & SR_ERR) != 0)
    349                 return EIO;
    350 
    351         d->blocks = d->cylinders * d->heads * d->sectors;
    352 
    353         d->present = true;
    354         fibril_mutex_initialize(&d->lock);
    355 
    356         return EOK;
    357 }
    358 
    359 /** Read a physical from the device.
    360  *
    361  * @param disk_id       Device index (0 or 1)
    362  * @param blk_idx       Index of the first block.
    363  * @param blk_cnt       Number of blocks to transfer.
    364  * @param buf           Buffer for holding the data.
    365  *
    366  * @return EOK on success, EIO on error.
    367  */
    368 static int ata_bd_read_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
    369     void *buf)
    370 {
    371         size_t i;
    372         uint16_t data;
    373         uint8_t status;
    374         uint64_t c, h, s;
    375         uint64_t idx;
    376         uint8_t drv_head;
    377         disk_t *d;
    378 
    379         d = &disk[disk_id];
    380 
    381         /* Check device bounds. */
    382         if (blk_idx >= d->blocks)
    383                 return EINVAL;
    384 
    385         /* Compute CHS. */
    386         c = blk_idx / (d->heads * d->sectors);
    387         idx = blk_idx % (d->heads * d->sectors);
    388 
    389         h = idx / d->sectors;
    390         s = 1 + (idx % d->sectors);
    391 
    392         /* New value for Drive/Head register */
    393         drv_head =
    394             ((disk_id != 0) ? DHR_DRV : 0) |
    395             (h & 0x0f);
    396 
    397         fibril_mutex_lock(&d->lock);
    398 
    399         /* Program a Read Sectors operation. */
    400 
    401         if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
    402                 fibril_mutex_unlock(&d->lock);
    403                 return EIO;
    404         }
    405 
    406         pio_write_8(&cmd->drive_head, drv_head);
    407 
    408         if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
    409                 fibril_mutex_unlock(&d->lock);
    410                 return EIO;
    411         }
    412 
    413         pio_write_8(&cmd->sector_count, 1);
    414         pio_write_8(&cmd->sector_number, s);
    415         pio_write_8(&cmd->cylinder_low, c & 0xff);
    416         pio_write_8(&cmd->cylinder_high, c >> 16);
    417 
    418         pio_write_8(&cmd->command, CMD_READ_SECTORS);
    419 
    420         if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
    421                 fibril_mutex_unlock(&d->lock);
    422                 return EIO;
    423         }
    424 
    425         if ((status & SR_DRQ) != 0) {
    426                 /* Read data from the device buffer. */
    427 
    428465                for (i = 0; i < block_size / 2; i++) {
    429466                        data = pio_read_16(&cmd->data_port);
     
    435472                return EIO;
    436473
    437         fibril_mutex_unlock(&d->lock);
    438         return EOK;
    439 }
    440 
    441 /** Write a physical block to the device.
     474        return EOK;
     475}
     476
     477/** Read a physical from the device.
    442478 *
    443479 * @param disk_id       Device index (0 or 1)
    444  * @param blk_idx       Index of the first block.
    445  * @param blk_cnt       Number of blocks to transfer.
    446  * @param buf           Buffer holding the data to write.
     480 * @param ba            Address the first block.
     481 * @param cnt           Number of blocks to transfer.
     482 * @param buf           Buffer for holding the data.
    447483 *
    448484 * @return EOK on success, EIO on error.
    449485 */
    450 static int ata_bd_write_block(int disk_id, uint64_t blk_idx, size_t blk_cnt,
    451     const void *buf)
     486static int ata_bd_read_block(int disk_id, uint64_t ba, size_t blk_cnt,
     487    void *buf)
    452488{
    453489        size_t i;
     490        uint16_t data;
    454491        uint8_t status;
    455         uint64_t c, h, s;
    456         uint64_t idx;
    457492        uint8_t drv_head;
    458493        disk_t *d;
     494        block_coord_t bc;
    459495
    460496        d = &disk[disk_id];
    461 
    462         /* Check device bounds. */
    463         if (blk_idx >= d->blocks)
     497        bc.h = 0;       /* Silence warning. */
     498
     499        /* Compute block coordinates. */
     500        if (coord_calc(d, ba, &bc) != EOK)
    464501                return EINVAL;
    465 
    466         /* Compute CHS. */
    467         c = blk_idx / (d->heads * d->sectors);
    468         idx = blk_idx % (d->heads * d->sectors);
    469 
    470         h = idx / d->sectors;
    471         s = 1 + (idx % d->sectors);
    472502
    473503        /* New value for Drive/Head register */
    474504        drv_head =
    475505            ((disk_id != 0) ? DHR_DRV : 0) |
    476             (h & 0x0f);
     506            ((d->amode != am_chs) ? DHR_LBA : 0) |
     507            (bc.h & 0x0f);
    477508
    478509        fibril_mutex_lock(&d->lock);
    479510
    480         /* Program a Write Sectors operation. */
     511        /* Program a Read Sectors operation. */
    481512
    482513        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
     
    492523        }
    493524
    494         pio_write_8(&cmd->sector_count, 1);
    495         pio_write_8(&cmd->sector_number, s);
    496         pio_write_8(&cmd->cylinder_low, c & 0xff);
    497         pio_write_8(&cmd->cylinder_high, c >> 16);
    498 
    499         pio_write_8(&cmd->command, CMD_WRITE_SECTORS);
     525        /* Program block coordinates into the device. */
     526        coord_sc_program(&bc, 1);
     527
     528        pio_write_8(&cmd->command, d->amode == am_lba48 ?
     529            CMD_READ_SECTORS_EXT : CMD_READ_SECTORS);
     530
     531        if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
     532                fibril_mutex_unlock(&d->lock);
     533                return EIO;
     534        }
     535
     536        if ((status & SR_DRQ) != 0) {
     537                /* Read data from the device buffer. */
     538
     539                for (i = 0; i < block_size / 2; i++) {
     540                        data = pio_read_16(&cmd->data_port);
     541                        ((uint16_t *) buf)[i] = data;
     542                }
     543        }
     544
     545        if ((status & SR_ERR) != 0)
     546                return EIO;
     547
     548        fibril_mutex_unlock(&d->lock);
     549        return EOK;
     550}
     551
     552/** Write a physical block to the device.
     553 *
     554 * @param disk_id       Device index (0 or 1)
     555 * @param ba            Address of the first block.
     556 * @param cnt           Number of blocks to transfer.
     557 * @param buf           Buffer holding the data to write.
     558 *
     559 * @return EOK on success, EIO on error.
     560 */
     561static int ata_bd_write_block(int disk_id, uint64_t ba, size_t cnt,
     562    const void *buf)
     563{
     564        size_t i;
     565        uint8_t status;
     566        uint8_t drv_head;
     567        disk_t *d;
     568        block_coord_t bc;
     569
     570        d = &disk[disk_id];
     571        bc.h = 0;       /* Silence warning. */
     572
     573        /* Compute block coordinates. */
     574        if (coord_calc(d, ba, &bc) != EOK)
     575                return EINVAL;
     576
     577        /* New value for Drive/Head register */
     578        drv_head =
     579            ((disk_id != 0) ? DHR_DRV : 0) |
     580            ((d->amode != am_chs) ? DHR_LBA : 0) |
     581            (bc.h & 0x0f);
     582
     583        fibril_mutex_lock(&d->lock);
     584
     585        /* Program a Write Sectors operation. */
     586
     587        if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
     588                fibril_mutex_unlock(&d->lock);
     589                return EIO;
     590        }
     591
     592        pio_write_8(&cmd->drive_head, drv_head);
     593
     594        if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
     595                fibril_mutex_unlock(&d->lock);
     596                return EIO;
     597        }
     598
     599        /* Program block coordinates into the device. */
     600        coord_sc_program(&bc, 1);
     601
     602        pio_write_8(&cmd->command, d->amode == am_lba48 ?
     603            CMD_WRITE_SECTORS_EXT : CMD_WRITE_SECTORS);
    500604
    501605        if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
     
    518622
    519623        return EOK;
     624}
     625
     626/** Calculate block coordinates.
     627 *
     628 * Calculates block coordinates in the best coordinate system supported
     629 * by the device. These can be later programmed into the device using
     630 * @c coord_sc_program().
     631 *
     632 * @return EOK on success or EINVAL if block index is past end of device.
     633 */
     634static int coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc)
     635{
     636        uint64_t c;
     637        uint64_t idx;
     638
     639        /* Check device bounds. */
     640        if (ba >= d->blocks)
     641                return EINVAL;
     642
     643        bc->amode = d->amode;
     644
     645        switch (d->amode) {
     646        case am_chs:
     647                /* Compute CHS coordinates. */
     648                c = ba / (d->geom.heads * d->geom.sectors);
     649                idx = ba % (d->geom.heads * d->geom.sectors);
     650
     651                bc->cyl_lo = c & 0xff;
     652                bc->cyl_hi = (c >> 8) & 0xff;
     653                bc->h      = (idx / d->geom.sectors) & 0x0f;
     654                bc->sector = (1 + (idx % d->geom.sectors)) & 0xff;
     655                break;
     656
     657        case am_lba28:
     658                /* Compute LBA-28 coordinates. */
     659                bc->c0 = ba & 0xff;             /* bits 0-7 */
     660                bc->c1 = (ba >> 8) & 0xff;      /* bits 8-15 */
     661                bc->c2 = (ba >> 16) & 0xff;     /* bits 16-23 */
     662                bc->h  = (ba >> 24) & 0x0f;     /* bits 24-27 */
     663                break;
     664
     665        case am_lba48:
     666                /* Compute LBA-48 coordinates. */
     667                bc->c0 = ba & 0xff;             /* bits 0-7 */
     668                bc->c1 = (ba >> 8) & 0xff;      /* bits 8-15 */
     669                bc->c2 = (ba >> 16) & 0xff;     /* bits 16-23 */
     670                bc->c3 = (ba >> 24) & 0xff;     /* bits 24-31 */
     671                bc->c4 = (ba >> 32) & 0xff;     /* bits 32-39 */
     672                bc->c5 = (ba >> 40) & 0xff;     /* bits 40-47 */
     673                bc->h  = 0;
     674                break;
     675        }
     676
     677        return EOK;
     678}
     679
     680/** Program block coordinates and sector count into ATA registers.
     681 *
     682 * Note that bc->h must be programmed separately into the device/head register.
     683 */
     684static void coord_sc_program(const block_coord_t *bc, uint16_t scnt)
     685{
     686        if (bc->amode == am_lba48) {
     687                /* Write high-order bits. */
     688                pio_write_8(&cmd->sector_count, scnt >> 8);
     689                pio_write_8(&cmd->sector_number, bc->c3);
     690                pio_write_8(&cmd->cylinder_low, bc->c4);
     691                pio_write_8(&cmd->cylinder_high, bc->c5);
     692        }
     693
     694        /* Write low-order bits. */
     695        pio_write_8(&cmd->sector_count, scnt & 0x00ff);
     696        pio_write_8(&cmd->sector_number, bc->c0);
     697        pio_write_8(&cmd->cylinder_low, bc->c1);
     698        pio_write_8(&cmd->cylinder_high, bc->c2);
    520699}
    521700
  • uspace/srv/bd/ata_bd/ata_bd.h

    rfcbd1be r1787e527  
    3838#include <sys/types.h>
    3939#include <fibril_sync.h>
     40#include <string.h>
    4041
    4142enum {
     
    115116
    116117enum drive_head_bits {
    117         DHR_DRV         = 0x10
     118        DHR_LBA         = 0x40, /**< Use LBA addressing mode */
     119        DHR_DRV         = 0x10  /**< Select device 1 */
    118120};
    119121
     
    130132
    131133enum ata_command {
    132         CMD_IDENTIFY_DRIVE      = 0xEC,
    133134        CMD_READ_SECTORS        = 0x20,
    134         CMD_WRITE_SECTORS       = 0x30
     135        CMD_READ_SECTORS_EXT    = 0x24,
     136        CMD_WRITE_SECTORS       = 0x30,
     137        CMD_WRITE_SECTORS_EXT   = 0x34,
     138        CMD_IDENTIFY_DRIVE      = 0xEC
    135139};
    136140
     
    142146};
    143147
     148/** Data returned from @c identify command. */
     149typedef struct {
     150        uint16_t gen_conf;
     151        uint16_t cylinders;
     152        uint16_t _res2;
     153        uint16_t heads;
     154        uint16_t _vs4;
     155        uint16_t _vs5;
     156        uint16_t sectors;
     157        uint16_t _vs7;
     158        uint16_t _vs8;
     159        uint16_t _vs9;
     160
     161        uint16_t serial_number[10];
     162        uint16_t _vs20;
     163        uint16_t _vs21;
     164        uint16_t vs_bytes;
     165        uint16_t firmware_rev[4];
     166        uint16_t model_name[20];
     167
     168        uint16_t max_rw_multiple;
     169        uint16_t _res48;
     170        uint16_t caps;
     171        uint16_t _res50;
     172        uint16_t pio_timing;
     173        uint16_t dma_timing;
     174
     175        uint16_t validity;
     176        uint16_t cur_cyl;
     177        uint16_t cur_heads;
     178        uint16_t cur_sectors;
     179        uint16_t cur_capacity0;
     180        uint16_t cur_capacity1;
     181        uint16_t mss;
     182        uint16_t total_lba28_0;
     183        uint16_t total_lba28_1;
     184        uint16_t sw_dma;
     185        uint16_t mw_dma;
     186        uint16_t pio_modes;
     187        uint16_t min_mw_dma_cycle;
     188        uint16_t rec_mw_dma_cycle;
     189        uint16_t min_raw_pio_cycle;
     190        uint16_t min_iordy_pio_cycle;
     191
     192        uint16_t _res69;
     193        uint16_t _res70;
     194        uint16_t _res71;
     195        uint16_t _res72;
     196        uint16_t _res73;
     197        uint16_t _res74;
     198
     199        uint16_t queue_depth;
     200        uint16_t _res76[1 + 79 - 76];
     201        uint16_t version_maj;
     202        uint16_t version_min;
     203        uint16_t cmd_set0;
     204        uint16_t cmd_set1;
     205        uint16_t csf_sup_ext;
     206        uint16_t csf_enabled0;
     207        uint16_t csf_enabled1;
     208        uint16_t csf_default;
     209        uint16_t udma;
     210
     211        uint16_t _res89[1 + 99 - 89];
     212
     213        /* Total number of blocks in LBA-48 addressing */
     214        uint16_t total_lba48_0;
     215        uint16_t total_lba48_1;
     216        uint16_t total_lba48_2;
     217        uint16_t total_lba48_3;
     218
     219        /* Note: more fields are defined in ATA/ATAPI-7 */
     220        uint16_t _res104[1 + 127 - 104];
     221        uint16_t _vs128[1 + 159 - 128];
     222        uint16_t _res160[1 + 255 - 160];
     223} identify_data_t;
     224
     225enum ata_caps {
     226        cap_iordy       = 0x0800,
     227        cap_iordy_cbd   = 0x0400,
     228        cap_lba         = 0x0200,
     229        cap_dma         = 0x0100
     230};
     231
     232/** Bits of @c identify_data_t.cmd_set1 */
     233enum ata_cs1 {
     234        cs1_addr48      = 0x0400        /**< 48-bit address feature set */
     235};
     236
     237/** Block addressing mode. */
     238enum addr_mode {
     239        am_chs,         /**< CHS block addressing */
     240        am_lba28,       /**< LBA-28 block addressing */
     241        am_lba48        /**< LBA-48 block addressing */
     242};
     243
     244/** Block coordinates */
     245typedef struct {
     246        /** Addressing mode used */
     247        enum addr_mode amode;
     248
     249        union {
     250                /** CHS coordinates */
     251                struct {
     252                        uint8_t sector;
     253                        uint8_t cyl_lo;
     254                        uint8_t cyl_hi;
     255                };
     256                /** LBA coordinates */
     257                struct {
     258                        uint8_t c0;
     259                        uint8_t c1;
     260                        uint8_t c2;
     261                        uint8_t c3;
     262                        uint8_t c4;
     263                        uint8_t c5;
     264                };
     265        };
     266
     267        /** Lower 4 bits for device/head register */
     268        uint8_t h;
     269} block_coord_t;
     270
    144271typedef struct {
    145272        bool present;
    146         unsigned heads;
    147         unsigned cylinders;
    148         unsigned sectors;
     273        enum addr_mode amode;
     274
     275        /*
     276         * Geometry. Only valid if operating in CHS mode.
     277         */
     278        struct {
     279                unsigned heads;
     280                unsigned cylinders;
     281                unsigned sectors;
     282        } geom;
     283
    149284        uint64_t blocks;
     285
     286        char model[STR_BOUNDS(40) + 1];
    150287
    151288        fibril_mutex_t lock;
  • uspace/srv/bd/file_bd/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
     32.PHONY: all clean
    3233
    33 LIBC_PREFIX = ../../../lib/libc
    34 SOFTINT_PREFIX = ../../../lib/softint
    35 
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 
    38 LIBS = $(LIBC_PREFIX)/libc.a
    39 
    40 ## Sources
    41 #
    42 
    43 OUTPUT = file_bd
    44 SOURCES = \
    45         file_bd.c
    46 
    47 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    48 
    49 .PHONY: all clean depend disasm
    50 
    51 all: $(OUTPUT) $(OUTPUT).disasm
    52 
    53 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5437
    5538clean:
    56         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    57 
    58 depend:
    59         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    60 
    61 $(OUTPUT): $(OBJECTS) $(LIBS)
    62         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    63 
    64 disasm: $(OUTPUT).disasm
    65 
    66 $(OUTPUT).disasm: $(OUTPUT)
    67         $(OBJDUMP) -d $< > $@
    68 
    69 %.o: %.S
    70         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    71 
    72 %.o: %.s
    73         $(AS) $(AFLAGS) $< -o $@
    74 
    75 %.o: %.c
    76         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/bd/file_bd/file_bd.c

    rfcbd1be r1787e527  
    5151#include <bool.h>
    5252#include <task.h>
     53#include <macros.h>
    5354
    5455#define NAME "file_bd"
    5556
    56 static size_t comm_size;
     57static const size_t block_size = 512;
    5758static FILE *img;
    5859
     
    6263static int file_bd_init(const char *fname);
    6364static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
    64 static int file_bd_read(off_t blk_idx, size_t size, void *buf);
    65 static int file_bd_write(off_t blk_idx, size_t size, void *buf);
     65static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf);
     66static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
    6667
    6768int main(int argc, char **argv)
     
    120121        ipc_call_t call;
    121122        ipcarg_t method;
     123        size_t comm_size;
    122124        int flags;
    123125        int retval;
    124         off_t idx;
    125         size_t size;
     126        uint64_t ba;
     127        size_t cnt;
    126128
    127129        /* Answer the IPC_M_CONNECT_ME_TO call. */
    128130        ipc_answer_0(iid, EOK);
    129131
    130         if (!ipc_share_out_receive(&callid, &comm_size, &flags)) {
     132        if (!async_share_out_receive(&callid, &comm_size, &flags)) {
    131133                ipc_answer_0(callid, EHANGUP);
    132134                return;
     
    139141        }
    140142
    141         (void) ipc_share_out_finalize(callid, fs_va);
     143        (void) async_share_out_finalize(callid, fs_va);
    142144
    143145        while (1) {
     
    149151                        ipc_answer_0(callid, EOK);
    150152                        return;
    151                 case BD_READ_BLOCK:
    152                 case BD_WRITE_BLOCK:
    153                         idx = IPC_GET_ARG1(call);
    154                         size = IPC_GET_ARG2(call);
    155                         if (size > comm_size) {
    156                                 retval = EINVAL;
     153                case BD_READ_BLOCKS:
     154                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     155                            IPC_GET_ARG2(call));
     156                        cnt = IPC_GET_ARG3(call);
     157                        if (cnt * block_size > comm_size) {
     158                                retval = ELIMIT;
    157159                                break;
    158160                        }
    159                         if (method == BD_READ_BLOCK)
    160                                 retval = file_bd_read(idx, size, fs_va);
    161                         else
    162                                 retval = file_bd_write(idx, size, fs_va);
     161                        retval = file_bd_read_blocks(ba, cnt, fs_va);
    163162                        break;
     163                case BD_WRITE_BLOCKS:
     164                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     165                            IPC_GET_ARG2(call));
     166                        cnt = IPC_GET_ARG3(call);
     167                        if (cnt * block_size > comm_size) {
     168                                retval = ELIMIT;
     169                                break;
     170                        }
     171                        retval = file_bd_write_blocks(ba, cnt, fs_va);
     172                        break;
     173                case BD_GET_BLOCK_SIZE:
     174                        ipc_answer_1(callid, EOK, block_size);
     175                        continue;
    164176                default:
    165177                        retval = EINVAL;
     
    170182}
    171183
    172 static int file_bd_read(off_t blk_idx, size_t size, void *buf)
     184/** Read blocks from the device. */
     185static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf)
    173186{
    174187        size_t n_rd;
     
    176189        fibril_mutex_lock(&dev_lock);
    177190
    178         fseek(img, blk_idx * size, SEEK_SET);
    179         n_rd = fread(buf, 1, size, img);
     191        fseek(img, ba * block_size, SEEK_SET);
     192        n_rd = fread(buf, block_size, cnt, img);
    180193
    181194        if (ferror(img)) {
     
    186199        fibril_mutex_unlock(&dev_lock);
    187200
    188         if (n_rd < size)
    189                 return EINVAL;  /* Read beyond end of disk */
     201        if (n_rd < cnt)
     202                return EINVAL;  /* Read beyond end of device */
    190203
    191204        return EOK;
    192205}
    193206
    194 static int file_bd_write(off_t blk_idx, size_t size, void *buf)
     207/** Write blocks to the device. */
     208static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf)
    195209{
    196210        size_t n_wr;
     
    198212        fibril_mutex_lock(&dev_lock);
    199213
    200         fseek(img, blk_idx * size, SEEK_SET);
    201         n_wr = fread(buf, 1, size, img);
    202 
    203         if (ferror(img) || n_wr < size) {
     214        fseek(img, ba * block_size, SEEK_SET);
     215        n_wr = fread(buf, block_size, cnt, img);
     216
     217        if (ferror(img) || n_wr < cnt) {
    204218                fibril_mutex_unlock(&dev_lock);
    205219                return EIO;     /* Write error */
  • uspace/srv/bd/gxe_bd/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
     32.PHONY: all clean
    3233
    33 LIBC_PREFIX = ../../../lib/libc
    34 SOFTINT_PREFIX = ../../../lib/softint
    35 
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 
    38 LIBS = $(LIBC_PREFIX)/libc.a
    39 
    40 ## Sources
    41 #
    42 
    43 OUTPUT = gxe_bd
    44 SOURCES = \
    45         gxe_bd.c
    46 
    47 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    48 
    49 .PHONY: all clean depend disasm
    50 
    51 all: $(OUTPUT) $(OUTPUT).disasm
    52 
    53 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5437
    5538clean:
    56         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    57 
    58 depend:
    59         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    60 
    61 $(OUTPUT): $(OBJECTS) $(LIBS)
    62         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    63 
    64 disasm: $(OUTPUT).disasm
    65 
    66 $(OUTPUT).disasm: $(OUTPUT)
    67         $(OBJDUMP) -d $< > $@
    68 
    69 %.o: %.S
    70         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    71 
    72 %.o: %.s
    73         $(AS) $(AFLAGS) $< -o $@
    74 
    75 %.o: %.c
    76         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/bd/gxe_bd/gxe_bd.c

    rfcbd1be r1787e527  
    4747#include <sys/types.h>
    4848#include <errno.h>
     49#include <macros.h>
    4950#include <task.h>
    5051
     
    9798static int gxe_bd_init(void);
    9899static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
    99 static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size,
     100static int gxe_bd_read_blocks(int disk_id, uint64_t ba, unsigned cnt,
    100101    void *buf);
    101 static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size,
    102     void *buf);
    103 static int gxe_bd_write_block(int disk_id, uint64_t offset, size_t size,
     102static int gxe_bd_write_blocks(int disk_id, uint64_t ba, unsigned cnt,
    104103    const void *buf);
     104static int gxe_bd_read_block(int disk_id, uint64_t ba, void *buf);
     105static int gxe_bd_write_block(int disk_id, uint64_t ba, const void *buf);
    105106
    106107int main(int argc, char **argv)
     
    163164        int flags;
    164165        int retval;
    165         off_t idx;
    166         size_t size;
     166        uint64_t ba;
     167        unsigned cnt;
    167168        int disk_id, i;
    168169
     
    184185        ipc_answer_0(iid, EOK);
    185186
    186         if (!ipc_share_out_receive(&callid, &comm_size, &flags)) {
     187        if (!async_share_out_receive(&callid, &comm_size, &flags)) {
     188                ipc_answer_0(callid, EHANGUP);
     189                return;
     190        }
     191
     192        if (comm_size < block_size) {
    187193                ipc_answer_0(callid, EHANGUP);
    188194                return;
     
    195201        }
    196202
    197         (void) ipc_share_out_finalize(callid, fs_va);
     203        (void) async_share_out_finalize(callid, fs_va);
    198204
    199205        while (1) {
     
    205211                        ipc_answer_0(callid, EOK);
    206212                        return;
    207                 case BD_READ_BLOCK:
    208                 case BD_WRITE_BLOCK:
    209                         idx = IPC_GET_ARG1(call);
    210                         size = IPC_GET_ARG2(call);
    211                         if (size > comm_size) {
    212                                 retval = EINVAL;
     213                case BD_READ_BLOCKS:
     214                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     215                            IPC_GET_ARG2(call));
     216                        cnt = IPC_GET_ARG3(call);
     217                        if (cnt * block_size > comm_size) {
     218                                retval = ELIMIT;
    213219                                break;
    214220                        }
    215                         retval = gx_bd_rdwr(disk_id, method, idx * size,
    216                             size, fs_va);
     221                        retval = gxe_bd_read_blocks(disk_id, ba, cnt, fs_va);
    217222                        break;
     223                case BD_WRITE_BLOCKS:
     224                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     225                            IPC_GET_ARG2(call));
     226                        cnt = IPC_GET_ARG3(call);
     227                        if (cnt * block_size > comm_size) {
     228                                retval = ELIMIT;
     229                                break;
     230                        }
     231                        retval = gxe_bd_write_blocks(disk_id, ba, cnt, fs_va);
     232                        break;
     233                case BD_GET_BLOCK_SIZE:
     234                        ipc_answer_1(callid, EOK, block_size);
     235                        continue;
    218236                default:
    219237                        retval = EINVAL;
     
    224242}
    225243
    226 static int gx_bd_rdwr(int disk_id, ipcarg_t method, off_t offset, size_t size,
    227     void *buf)
    228 {
     244/** Read multiple blocks from the device. */
     245static int gxe_bd_read_blocks(int disk_id, uint64_t ba, unsigned cnt,
     246    void *buf) {
     247
    229248        int rc;
    230         size_t now;
    231 
    232         while (size > 0) {
    233                 now = size < block_size ? size : block_size;
    234 
    235                 if (method == BD_READ_BLOCK)
    236                         rc = gxe_bd_read_block(disk_id, offset, now, buf);
    237                 else
    238                         rc = gxe_bd_write_block(disk_id, offset, now, buf);
    239 
     249
     250        while (cnt > 0) {
     251                rc = gxe_bd_read_block(disk_id, ba, buf);
    240252                if (rc != EOK)
    241253                        return rc;
    242254
     255                ++ba;
     256                --cnt;
    243257                buf += block_size;
    244                 offset += block_size;
    245 
    246                 if (size > block_size)
    247                         size -= block_size;
    248                 else
    249                         size = 0;
    250         }
    251 
    252         return EOK;
    253 }
    254 
    255 static int gxe_bd_read_block(int disk_id, uint64_t offset, size_t size,
    256     void *buf)
     258        }
     259
     260        return EOK;
     261}
     262
     263/** Write multiple blocks to the device. */
     264static int gxe_bd_write_blocks(int disk_id, uint64_t ba, unsigned cnt,
     265    const void *buf) {
     266
     267        int rc;
     268
     269        while (cnt > 0) {
     270                rc = gxe_bd_write_block(disk_id, ba, buf);
     271                if (rc != EOK)
     272                        return rc;
     273
     274                ++ba;
     275                --cnt;
     276                buf += block_size;
     277        }
     278
     279        return EOK;
     280}
     281
     282/** Read a block from the device. */
     283static int gxe_bd_read_block(int disk_id, uint64_t ba, void *buf)
    257284{
    258285        uint32_t status;
     286        uint64_t byte_addr;
    259287        size_t i;
    260288        uint32_t w;
    261289
     290        byte_addr = ba * block_size;
     291
    262292        fibril_mutex_lock(&dev_lock[disk_id]);
    263         pio_write_32(&dev->offset_lo, (uint32_t) offset);
    264         pio_write_32(&dev->offset_hi, offset >> 32);
     293        pio_write_32(&dev->offset_lo, (uint32_t) byte_addr);
     294        pio_write_32(&dev->offset_hi, byte_addr >> 32);
    265295        pio_write_32(&dev->disk_id, disk_id);
    266296        pio_write_32(&dev->control, CTL_READ_START);
     
    272302        }
    273303
    274         for (i = 0; i < size; i++) {
     304        for (i = 0; i < block_size; i++) {
    275305                ((uint8_t *) buf)[i] = w = pio_read_8(&dev->buffer[i]);
    276306        }
     
    280310}
    281311
    282 static int gxe_bd_write_block(int disk_id, uint64_t offset, size_t size,
    283     const void *buf)
     312/** Write a block to the device. */
     313static int gxe_bd_write_block(int disk_id, uint64_t ba, const void *buf)
    284314{
    285315        uint32_t status;
     316        uint64_t byte_addr;
    286317        size_t i;
    287318
    288         for (i = 0; i < size; i++) {
     319        byte_addr = ba * block_size;
     320
     321        fibril_mutex_lock(&dev_lock[disk_id]);
     322
     323        for (i = 0; i < block_size; i++) {
    289324                pio_write_8(&dev->buffer[i], ((const uint8_t *) buf)[i]);
    290325        }
    291326
    292         fibril_mutex_lock(&dev_lock[disk_id]);
    293         pio_write_32(&dev->offset_lo, (uint32_t) offset);
    294         pio_write_32(&dev->offset_hi, offset >> 32);
     327        pio_write_32(&dev->offset_lo, (uint32_t) byte_addr);
     328        pio_write_32(&dev->offset_hi, byte_addr >> 32);
    295329        pio_write_32(&dev->disk_id, disk_id);
    296330        pio_write_32(&dev->control, CTL_WRITE_START);
  • uspace/srv/bd/rd/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
     32.PHONY: all clean
    3233
    33 LIBC_PREFIX = ../../../lib/libc
    34 SOFTINT_PREFIX = ../../../lib/softint
    35 
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 
    38 LIBS = $(LIBC_PREFIX)/libc.a
    39 
    40 ## Sources
    41 #
    42 
    43 OUTPUT = rd
    44 SOURCES = \
    45         rd.c
    46 
    47 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    48 
    49 .PHONY: all clean depend disasm
    50 
    51 all: $(OUTPUT) $(OUTPUT).disasm
    52 
    53 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5437
    5538clean:
    56         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    57 
    58 depend:
    59         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    60 
    61 $(OUTPUT): $(OBJECTS) $(LIBS)
    62         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    63 
    64 disasm: $(OUTPUT).disasm
    65 
    66 $(OUTPUT).disasm: $(OUTPUT)
    67         $(OBJDUMP) -d $< > $@
    68 
    69 %.o: %.S
    70         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    71 
    72 %.o: %.s
    73         $(AS) $(AFLAGS) $< -o $@
    74 
    75 %.o: %.c
    76         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/bd/rd/rd.c

    rfcbd1be r1787e527  
    5555#include <devmap.h>
    5656#include <ipc/bd.h>
     57#include <macros.h>
    5758
    5859#define NAME "rd"
    5960
    60 /** Pointer to the ramdisk's image. */
     61/** Pointer to the ramdisk's image */
    6162static void *rd_addr;
    62 /** Size of the ramdisk. */
     63/** Size of the ramdisk */
    6364static size_t rd_size;
     65
     66/** Block size */
     67static const size_t block_size = 512;
     68
     69static int rd_read_blocks(uint64_t ba, size_t cnt, void *buf);
     70static int rd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
    6471
    6572/**
     
    8289        int retval;
    8390        void *fs_va = NULL;
    84         off_t offset;
    85         size_t block_size;
    86         size_t maxblock_size;
     91        uint64_t ba;
     92        size_t cnt;
     93        size_t comm_size;
    8794
    8895        /*
     
    95102         */
    96103        int flags;
    97         if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) {
    98                 fs_va = as_get_mappable_page(maxblock_size);
     104        if (async_share_out_receive(&callid, &comm_size, &flags)) {
     105                fs_va = as_get_mappable_page(comm_size);
    99106                if (fs_va) {
    100                         (void) ipc_share_out_finalize(callid, fs_va);
     107                        (void) async_share_out_finalize(callid, fs_va);
    101108                } else {
    102109                        ipc_answer_0(callid, EHANGUP);
     
    123130                        ipc_answer_0(callid, EOK);
    124131                        return;
    125                 case BD_READ_BLOCK:
    126                         offset = IPC_GET_ARG1(call);
    127                         block_size = IPC_GET_ARG2(call);
    128                         if (block_size > maxblock_size) {
    129                                 /*
    130                                  * Maximum block size exceeded.
    131                                  */
     132                case BD_READ_BLOCKS:
     133                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     134                            IPC_GET_ARG2(call));
     135                        cnt = IPC_GET_ARG3(call);
     136                        if (cnt * block_size > comm_size) {
    132137                                retval = ELIMIT;
    133138                                break;
    134139                        }
    135                         if (offset * block_size > rd_size - block_size) {
    136                                 /*
    137                                  * Reading past the end of the device.
    138                                  */
     140                        retval = rd_read_blocks(ba, cnt, fs_va);
     141                        break;
     142                case BD_WRITE_BLOCKS:
     143                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
     144                            IPC_GET_ARG2(call));
     145                        cnt = IPC_GET_ARG3(call);
     146                        if (cnt * block_size > comm_size) {
    139147                                retval = ELIMIT;
    140148                                break;
    141149                        }
    142                         fibril_rwlock_read_lock(&rd_lock);
    143                         memcpy(fs_va, rd_addr + offset * block_size, block_size);
    144                         fibril_rwlock_read_unlock(&rd_lock);
    145                         retval = EOK;
     150                        retval = rd_write_blocks(ba, cnt, fs_va);
    146151                        break;
    147                 case BD_WRITE_BLOCK:
    148                         offset = IPC_GET_ARG1(call);
    149                         block_size = IPC_GET_ARG2(call);
    150                         if (block_size > maxblock_size) {
    151                                 /*
    152                                  * Maximum block size exceeded.
    153                                  */
    154                                 retval = ELIMIT;
    155                                 break;
    156                         }
    157                         if (offset * block_size > rd_size - block_size) {
    158                                 /*
    159                                  * Writing past the end of the device.
    160                                  */
    161                                 retval = ELIMIT;
    162                                 break;
    163                         }
    164                         fibril_rwlock_write_lock(&rd_lock);
    165                         memcpy(rd_addr + offset * block_size, fs_va, block_size);
    166                         fibril_rwlock_write_unlock(&rd_lock);
    167                         retval = EOK;
    168                         break;
     152                case BD_GET_BLOCK_SIZE:
     153                        ipc_answer_1(callid, EOK, block_size);
     154                        continue;
    169155                default:
    170156                        /*
     
    181167}
    182168
     169/** Read blocks from the device. */
     170static int rd_read_blocks(uint64_t ba, size_t cnt, void *buf)
     171{
     172        if ((ba + cnt) * block_size > rd_size) {
     173                /* Reading past the end of the device. */
     174                return ELIMIT;
     175        }
     176
     177        fibril_rwlock_read_lock(&rd_lock);
     178        memcpy(buf, rd_addr + ba * block_size, block_size * cnt);
     179        fibril_rwlock_read_unlock(&rd_lock);
     180
     181        return EOK;
     182}
     183
     184/** Write blocks to the device. */
     185static int rd_write_blocks(uint64_t ba, size_t cnt, const void *buf)
     186{
     187        if ((ba + cnt) * block_size > rd_size) {
     188                /* Writing past the end of the device. */
     189                return ELIMIT;
     190        }
     191
     192        fibril_rwlock_write_lock(&rd_lock);
     193        memcpy(rd_addr + ba * block_size, buf, block_size * cnt);
     194        fibril_rwlock_write_unlock(&rd_lock);
     195
     196        return EOK;
     197}
     198
    183199/** Prepare the ramdisk image for operation. */
    184200static bool rd_init(void)
  • uspace/srv/cir/fhc/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
     32.PHONY: all clean
    3233
    33 LIBC_PREFIX = ../../../lib/libc
    34 SOFTINT_PREFIX = ../../../lib/softint
    35 
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 
    38 LIBS = $(LIBC_PREFIX)/libc.a
    39 
    40 ## Sources
    41 #
    42 
    43 OUTPUT = fhc
    44 SOURCES = \
    45         fhc.c
    46 
    47 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    48 
    49 .PHONY: all clean depend disasm
    50 
    51 all: $(OUTPUT) $(OUTPUT).disasm
    52 
    53 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5437
    5538clean:
    56         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    57 
    58 depend:
    59         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    60 
    61 $(OUTPUT): $(OBJECTS) $(LIBS)
    62         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    63 
    64 disasm: $(OUTPUT).disasm
    65 
    66 $(OUTPUT).disasm: $(OUTPUT)
    67         $(OBJDUMP) -d $< > $@
    68 
    69 %.o: %.S
    70         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    71 
    72 %.o: %.s
    73         $(AS) $(AFLAGS) $< -o $@
    74 
    75 %.o: %.c
    76         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/cir/obio/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
     32.PHONY: all clean
    3233
    33 LIBC_PREFIX = ../../../lib/libc
    34 SOFTINT_PREFIX = ../../../lib/softint
    35 
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 
    38 LIBS = $(LIBC_PREFIX)/libc.a
    39 
    40 ## Sources
    41 #
    42 
    43 OUTPUT = obio
    44 SOURCES = \
    45         obio.c
    46 
    47 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    48 
    49 .PHONY: all clean depend disasm
    50 
    51 all: $(OUTPUT) $(OUTPUT).disasm
    52 
    53 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5437
    5538clean:
    56         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    57 
    58 depend:
    59         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    60 
    61 $(OUTPUT): $(OBJECTS) $(LIBS)
    62         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    63 
    64 disasm: $(OUTPUT).disasm
    65 
    66 $(OUTPUT).disasm: $(OUTPUT)
    67         $(OBJDUMP) -d $< > $@
    68 
    69 %.o: %.S
    70         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    71 
    72 %.o: %.s
    73         $(AS) $(AFLAGS) $< -o $@
    74 
    75 %.o: %.c
    76         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/console/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../../lib/libc
    33 SOFTINT_PREFIX = ../../lib/softint
     32.PHONY: all clean
    3433
    35 include $(LIBC_PREFIX)/Makefile.toolchain
    36 
    37 CFLAGS += -I.
    38 
    39 LIBS = $(LIBC_PREFIX)/libc.a
    40 
    41 ## Sources
    42 #
    43 
    44 OUTPUT = console
    45 
    46 GENERIC_SOURCES = \
    47         console.c \
    48         screenbuffer.c \
    49         keybuffer.c \
    50         gcons.c
    51 
    52 IMAGES = \
    53         gfx/helenos.ppm \
    54         gfx/nameic.ppm \
    55         gfx/cons_selected.ppm \
    56         gfx/cons_idle.ppm \
    57         gfx/cons_has_data.ppm \
    58         gfx/cons_kernel.ppm \
    59         gfx/anim_1.ppm \
    60         gfx/anim_2.ppm \
    61         gfx/anim_3.ppm \
    62         gfx/anim_4.ppm
    63 
    64 GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) \
    65         $(addsuffix .o,$(basename $(IMAGES)))
    66 
    67 OBJECTS := $(GENERIC_OBJECTS)
    68 
    69 .PHONY: all clean depend disasm
    70 
    71 all: $(OUTPUT) $(OUTPUT).disasm
    72 
    73 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    7437
    7538clean:
    76         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    77 
    78 depend:
    79         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    80 
    81 $(OUTPUT): $(OBJECTS) $(LIBS)
    82         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    83 
    84 disasm: $(OUTPUT).disasm
    85 
    86 $(OUTPUT).disasm: $(OUTPUT)
    87         $(OBJDUMP) -d $< > $@
    88 
    89 %.o: %.S
    90         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    91 
    92 %.o: %.s
    93         $(AS) $(AFLAGS) $< -o $@
    94 
    95 %.o: %.c
    96         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
    97 
    98 %.o: %.ppm
    99         $(OBJCOPY) -I binary -O $(BFD_NAME) -B $(BFD_ARCH) $< $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/console/console.c

    rfcbd1be r1787e527  
    4040#include <ipc/services.h>
    4141#include <errno.h>
    42 #include <keybuffer.h>
    4342#include <ipc/console.h>
    4443#include <unistd.h>
     
    5554#include "console.h"
    5655#include "gcons.h"
     56#include "keybuffer.h"
    5757#include "screenbuffer.h"
    5858
     
    429429        ipc_callid_t callid;
    430430        size_t size;
    431         if (!ipc_data_write_receive(&callid, &size)) {
     431        if (!async_data_write_receive(&callid, &size)) {
    432432                ipc_answer_0(callid, EINVAL);
    433433                ipc_answer_0(rid, EINVAL);
     
    442442        }
    443443       
    444         (void) ipc_data_write_finalize(callid, buf, size);
     444        (void) async_data_write_finalize(callid, buf, size);
    445445       
    446446        async_serialize_start();
     
    464464        ipc_callid_t callid;
    465465        size_t size;
    466         if (!ipc_data_read_receive(&callid, &size)) {
     466        if (!async_data_read_receive(&callid, &size)) {
    467467                ipc_answer_0(callid, EINVAL);
    468468                ipc_answer_0(rid, EINVAL);
     
    489489       
    490490        if (pos == size) {
    491                 (void) ipc_data_read_finalize(callid, buf, size);
     491                (void) async_data_read_finalize(callid, buf, size);
    492492                ipc_answer_1(rid, EOK, size);
    493493                free(buf);
     
    713713       
    714714        if (interbuffer) {
    715                 if (ipc_share_out_start(fb_info.phone, interbuffer,
     715                if (async_share_out_start(fb_info.phone, interbuffer,
    716716                    AS_AREA_READ) != EOK) {
    717717                        as_area_destroy(interbuffer);
  • uspace/srv/console/gcons.c

    rfcbd1be r1787e527  
    339339                goto exit;
    340340       
    341         rc = ipc_share_out_start(fbphone, shm, PROTO_READ);
     341        rc = async_share_out_start(fbphone, shm, PROTO_READ);
    342342        if (rc)
    343343                goto drop;
     
    409409                goto exit;
    410410       
    411         rc = ipc_share_out_start(fbphone, shm, PROTO_READ);
     411        rc = async_share_out_start(fbphone, shm, PROTO_READ);
    412412        if (rc)
    413413                goto drop;
  • uspace/srv/console/keybuffer.c

    rfcbd1be r1787e527  
    3535 */
    3636
    37 #include <keybuffer.h>
    3837#include <futex.h>
     38#include "keybuffer.h"
    3939
    4040atomic_t keybuffer_futex = FUTEX_INITIALIZER;
  • uspace/srv/console/screenbuffer.c

    rfcbd1be r1787e527  
    3333 */
    3434
    35 #include <screenbuffer.h>
    3635#include <io/style.h>
    3736#include <malloc.h>
    3837#include <unistd.h>
     38#include "screenbuffer.h"
    3939
    4040/** Store one character to screenbuffer.
  • uspace/srv/devmap/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../../lib/libc
    33 SOFTINT_PREFIX = ../../lib/softint
     32.PHONY: all clean
    3433
    35 include $(LIBC_PREFIX)/Makefile.toolchain
    36 
    37 LIBS = $(LIBC_PREFIX)/libc.a
    38 
    39 ## Sources
    40 #
    41 
    42 OUTPUT = devmap
    43 SOURCES = \
    44         devmap.c
    45 
    46 CFLAGS += -D$(UARCH)
    47 
    48 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    49 
    50 .PHONY: all clean depend disasm
    51 
    52 all: $(OUTPUT) $(OUTPUT).disasm
    53 
    54 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5537
    5638clean:
    57         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    58 
    59 depend:
    60         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    61 
    62 $(OUTPUT): $(OBJECTS) $(LIBS)
    63         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    64 
    65 disasm: $(OUTPUT).disasm
    66 
    67 $(OUTPUT).disasm: $(OUTPUT)
    68         $(OBJDUMP) -d $< > $@
    69 
    70 %.o: %.S
    71         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    72 
    73 %.o: %.s
    74         $(AS) $(AFLAGS) $< -o $@
    75 
    76 %.o: %.c
    77         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/devmap/devmap.c

    rfcbd1be r1787e527  
    213213        ipc_callid_t callid;
    214214        size_t name_size;
    215         if (!ipc_data_write_receive(&callid, &name_size)) {
     215        if (!async_data_write_receive(&callid, &name_size)) {
    216216                free(driver);
    217217                ipc_answer_0(callid, EREFUSED);
     
    241241         * Send confirmation to sender and get data into buffer.
    242242         */
    243         if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
     243        if (async_data_write_finalize(callid, driver->name, name_size) != EOK) {
    244244                free(driver->name);
    245245                free(driver);
     
    358358        ipc_callid_t callid;
    359359        size_t size;
    360         if (!ipc_data_write_receive(&callid, &size)) {
     360        if (!async_data_write_receive(&callid, &size)) {
    361361                free(device);
    362362                ipc_answer_0(iid, EREFUSED);
     
    381381        }
    382382       
    383         ipc_data_write_finalize(callid, device->name, size);
     383        async_data_write_finalize(callid, device->name, size);
    384384        device->name[size] = 0;
    385385       
     
    466466        ipc_callid_t callid;
    467467        size_t size;
    468         if (!ipc_data_write_receive(&callid, &size)) {
     468        if (!async_data_write_receive(&callid, &size)) {
    469469                ipc_answer_0(callid, EREFUSED);
    470470                ipc_answer_0(iid, EREFUSED);
     
    491491         * Send confirmation to sender and get data into buffer.
    492492         */
    493         ipcarg_t retval = ipc_data_write_finalize(callid, name, size);
     493        ipcarg_t retval = async_data_write_finalize(callid, name, size);
    494494        if (retval != EOK) {
    495495                ipc_answer_0(iid, EREFUSED);
     
    553553         * size_t name_size = str_size(device->name);
    554554         *
    555          * int rc = ipc_data_write_send(phone, device->name, name_size);
     555         * int rc = async_data_write_send(phone, device->name, name_size);
    556556         * if (rc != EOK) {
    557557         *     async_wait_for(req, NULL);
     
    576576        ipc_callid_t callid;
    577577        size_t size;
    578         if (!ipc_data_read_receive(&callid, &size)) {
     578        if (!async_data_read_receive(&callid, &size)) {
    579579                ipc_answer_0(callid, EREFUSED);
    580580                ipc_answer_0(iid, EREFUSED);
     
    608608        }
    609609       
    610         ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
     610        ipcarg_t retval = async_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
    611611        if (retval != EOK) {
    612612                ipc_answer_0(iid, EREFUSED);
  • uspace/srv/fb/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../../lib/libc
    33 SOFTINT_PREFIX = ../../lib/softint
     32.PHONY: all clean
    3433
    35 include $(LIBC_PREFIX)/Makefile.toolchain
    36 
    37 LIBS = $(LIBC_PREFIX)/libc.a
    38 
    39 ## Sources
    40 #
    41 
    42 OUTPUT = fb
    43 SOURCES = \
    44         main.c \
    45         ppm.c
    46 
    47 ifneq ($(UARCH),ia64)
    48         SOURCES += fb.c \
    49                 font-8x16.c
    50         CFLAGS += -DFB_ENABLED
    51 endif
    52 
    53 ifeq ($(UARCH),ia32)
    54         SOURCES += ega.c
    55         CFLAGS += -DEGA_ENABLED
    56 endif
    57 
    58 ifeq ($(UARCH),ia64)
    59         SOURCES += ega.c \
    60                 ski.c \
    61                 serial_console.c
    62         CFLAGS += -DSKI_ENABLED
    63         CFLAGS += -DEGA_ENABLED
    64 endif
    65 
    66 ifeq ($(UARCH),amd64)
    67         SOURCES += ega.c
    68         CFLAGS += -DEGA_ENABLED
    69 endif
    70 
    71 ifeq ($(UARCH),mips32)
    72         SOURCES += msim.c \
    73                 serial_console.c
    74         CFLAGS += -DMSIM_ENABLED
    75 endif
    76 
    77 ifeq ($(UARCH),sparc64)
    78         SOURCES += sgcn.c \
    79                 serial_console.c
    80         CFLAGS += -DSGCN_ENABLED
    81 endif
    82 
    83 CFLAGS += -D$(UARCH)
    84 
    85 
    86 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    87 
    88 .PHONY: all clean depend disasm
    89 
    90 all: $(OUTPUT) $(OUTPUT).disasm
    91 
    92 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    9337
    9438clean:
    95         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    96 
    97 depend:
    98         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    99 
    100 $(OUTPUT): $(OBJECTS) $(LIBS)
    101         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    102 
    103 disasm: $(OUTPUT).disasm
    104 
    105 $(OUTPUT).disasm: $(OUTPUT)
    106         $(OBJDUMP) -d $< > $@
    107 
    108 %.o: %.S
    109         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    110 
    111 %.o: %.s
    112         $(AS) $(AFLAGS) $< -o $@
    113 
    114 %.o: %.c
    115         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/fs/devfs/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../../../lib/libc
    33 LIBFS_PREFIX = ../../../lib/libfs
    34 SOFTINT_PREFIX = ../../../lib/softint
     32.PHONY: all clean
    3533
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 
    38 CFLAGS += -I $(LIBFS_PREFIX)
    39 
    40 LIBS = \
    41         $(LIBFS_PREFIX)/libfs.a \
    42         $(LIBC_PREFIX)/libc.a
    43 
    44 ## Sources
    45 #
    46 
    47 OUTPUT = devfs
    48 SOURCES = \
    49         devfs.c \
    50         devfs_ops.c
    51 
    52 
    53 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    54 
    55 .PHONY: all clean depend disasm
    56 
    57 all: $(OUTPUT) $(OUTPUT).disasm
    58 
    59 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    6037
    6138clean:
    62         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    63 
    64 depend:
    65         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    66 
    67 $(OUTPUT): $(OBJECTS) $(LIBS)
    68         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    69 
    70 disasm: $(OUTPUT).disasm
    71 
    72 $(OUTPUT).disasm: $(OUTPUT)
    73         $(OBJDUMP) -d $< > $@
    74 
    75 %.o: %.S
    76         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    77 
    78 %.o: %.s
    79         $(AS) $(AFLAGS) $< -o $@
    80 
    81 %.o: %.c
    82         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/fs/devfs/devfs.c

    rfcbd1be r1787e527  
    4444#include <async.h>
    4545#include <errno.h>
     46#include <task.h>
    4647#include <libfs.h>
    4748#include "devfs.h"
     
    5152
    5253static vfs_info_t devfs_vfs_info = {
    53         .name = "devfs",
     54        .name = NAME,
    5455};
    5556
     
    131132       
    132133        printf(NAME ": Accepting connections\n");
     134        task_retval(0);
    133135        async_manager();
    134136       
  • uspace/srv/fs/devfs/devfs_ops.c

    rfcbd1be r1787e527  
    108108        ipc_callid_t callid;
    109109        size_t size;
    110         if (!ipc_data_write_receive(&callid, &size)) {
     110        if (!async_data_write_receive(&callid, &size)) {
    111111                ipc_answer_0(callid, EINVAL);
    112112                ipc_answer_0(rid, EINVAL);
     
    121121        }
    122122       
    123         ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);
     123        ipcarg_t retval = async_data_write_finalize(callid, opts, size);
    124124        if (retval != EOK) {
    125125                ipc_answer_0(rid, retval);
     
    286286        ipc_callid_t callid;
    287287        size_t size;
    288         if (!ipc_data_read_receive(&callid, &size) ||
     288        if (!async_data_read_receive(&callid, &size) ||
    289289            size != sizeof(struct stat)) {
    290290                ipc_answer_0(callid, EINVAL);
     
    315315        }
    316316
    317         ipc_data_read_finalize(callid, &stat, sizeof(struct stat));
     317        async_data_read_finalize(callid, &stat, sizeof(struct stat));
    318318        ipc_answer_0(rid, EOK);
    319319}
     
    340340               
    341341                ipc_callid_t callid;
    342                 if (!ipc_data_read_receive(&callid, NULL)) {
     342                if (!async_data_read_receive(&callid, NULL)) {
    343343                        fibril_mutex_unlock(&devices_mutex);
    344344                        ipc_answer_0(callid, EINVAL);
     
    367367                ipc_callid_t callid;
    368368                size_t size;
    369                 if (!ipc_data_read_receive(&callid, &size)) {
     369                if (!async_data_read_receive(&callid, &size)) {
    370370                        ipc_answer_0(callid, EINVAL);
    371371                        ipc_answer_0(rid, EINVAL);
     
    384384               
    385385                if (pos < max) {
    386                         ipc_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
     386                        async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    387387                } else {
    388388                        ipc_answer_0(callid, ENOENT);
     
    418418               
    419419                ipc_callid_t callid;
    420                 if (!ipc_data_write_receive(&callid, NULL)) {
     420                if (!async_data_write_receive(&callid, NULL)) {
    421421                        fibril_mutex_unlock(&devices_mutex);
    422422                        ipc_answer_0(callid, EINVAL);
  • uspace/srv/fs/fat/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../../../lib/libc
    33 LIBFS_PREFIX = ../../../lib/libfs
    34 LIBBLOCK_PREFIX = ../../../lib/libblock
    35 SOFTINT_PREFIX = ../../../lib/softint
     32.PHONY: all clean
    3633
    37 include $(LIBC_PREFIX)/Makefile.toolchain
    38 
    39 CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX)
    40 
    41 LIBS = \
    42         $(LIBFS_PREFIX)/libfs.a \
    43         $(LIBBLOCK_PREFIX)/libblock.a \
    44         $(LIBC_PREFIX)/libc.a
    45 
    46 ## Sources
    47 #
    48 
    49 OUTPUT = fat
    50 SOURCES = \
    51         fat.c \
    52         fat_ops.c \
    53         fat_idx.c \
    54         fat_dentry.c \
    55         fat_fat.c
    56 
    57 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    58 
    59 .PHONY: all clean depend disasm
    60 
    61 all: $(OUTPUT) $(OUTPUT).disasm
    62 
    63 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    6437
    6538clean:
    66         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    67 
    68 depend:
    69         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    70 
    71 $(OUTPUT): $(OBJECTS) $(LIBS)
    72         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    73 
    74 disasm: $(OUTPUT).disasm
    75 
    76 $(OUTPUT).disasm: $(OUTPUT)
    77         $(OBJDUMP) -d $< > $@
    78 
    79 %.o: %.S
    80         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    81 
    82 %.o: %.s
    83         $(AS) $(AFLAGS) $< -o $@
    84 
    85 %.o: %.c
    86         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/fs/fat/fat.c

    rfcbd1be r1787e527  
    4343#include <errno.h>
    4444#include <unistd.h>
     45#include <task.h>
    4546#include <stdio.h>
    4647#include <libfs.h>
    4748#include "../../vfs/vfs.h"
    4849
     50#define NAME    "fat"
    4951
    5052vfs_info_t fat_vfs_info = {
    51         .name = "fat",
     53        .name = NAME,
    5254};
    5355
     
    8385        }
    8486       
    85         dprintf("VFS-FAT connection established.\n");
     87        dprintf(NAME ": connection opened\n");
    8688        while (1) {
    8789                ipc_callid_t callid;
     
    137139        int rc;
    138140
    139         printf("fat: HelenOS FAT file system server.\n");
     141        printf(NAME ": HelenOS FAT file system server\n");
    140142
    141143        rc = fat_idx_init();
     
    145147        vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
    146148        if (vfs_phone < EOK) {
    147                 printf("fat: failed to connect to VFS\n");
     149                printf(NAME ": failed to connect to VFS\n");
    148150                return -1;
    149151        }
     
    155157        }
    156158       
    157         dprintf("FAT filesystem registered, fs_handle=%d.\n",
    158             fat_reg.fs_handle);
    159 
     159        printf(NAME ": Accepting connections\n");
     160        task_retval(0);
    160161        async_manager();
    161162        /* not reached */
     
    163164
    164165err:
    165         printf("Failed to register the FAT file system (%d)\n", rc);
     166        printf(NAME ": Failed to register file system (%d)\n", rc);
    166167        return rc;
    167168}
  • uspace/srv/fs/fat/fat.h

    rfcbd1be r1787e527  
    8989                        uint16_t        signature;
    9090                } __attribute__ ((packed));
    91                 struct {
     91                struct fat32 {
    9292                        /* FAT32 only */
    9393                        /** Sectors per FAT. */
     
    215215extern void fat_sync(ipc_callid_t, ipc_call_t *);
    216216
    217 extern fat_idx_t *fat_idx_get_new(dev_handle_t);
     217extern int fat_idx_get_new(fat_idx_t **, dev_handle_t);
    218218extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
    219219extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t);
  • uspace/srv/fs/fat/fat_fat.c

    rfcbd1be r1787e527  
    6161 * @param dev_handle    Device handle of the device with the file.
    6262 * @param firstc        First cluster to start the walk with.
    63  * @param lastc         If non-NULL, output argument hodling the last cluster number visited.
     63 * @param lastc         If non-NULL, output argument hodling the last cluster
     64 *                      number visited.
     65 * @param numc          If non-NULL, output argument holding the number of
     66 *                      clusters seen during the walk.
    6467 * @param max_clusters  Maximum number of clusters to visit.   
    6568 *
    66  * @return              Number of clusters seen during the walk.
    67  */
    68 uint16_t
     69 * @return              EOK on success or a negative error code.
     70 */
     71int
    6972fat_cluster_walk(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
    70     fat_cluster_t *lastc, uint16_t max_clusters)
     73    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    7174{
    7275        block_t *b;
     
    7578        uint16_t clusters = 0;
    7679        fat_cluster_t clst = firstc;
     80        int rc;
    7781
    7882        bps = uint16_t_le2host(bs->bps);
     
    8387                if (lastc)
    8488                        *lastc = firstc;
    85                 return 0;
     89                if (numc)
     90                        *numc = 0;
     91                return EOK;
    8692        }
    8793
     
    96102                fidx = clst % (bps / sizeof(fat_cluster_t));
    97103                /* read FAT1 */
    98                 b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE);
     104                rc = block_get(&b, dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE);
     105                if (rc != EOK)
     106                        return rc;
    99107                clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    100108                assert(clst != FAT_CLST_BAD);
    101                 block_put(b);
     109                rc = block_put(b);
     110                if (rc != EOK)
     111                        return rc;
    102112                clusters++;
    103113        }
     
    105115        if (lastc && clst < FAT_CLST_LAST1)
    106116                *lastc = clst;
    107 
    108         return clusters;
     117        if (numc)
     118                *numc = clusters;
     119
     120        return EOK;
    109121}
    110122
    111123/** Read block from file located on a FAT file system.
    112124 *
     125 * @param block         Pointer to a block pointer for storing result.
    113126 * @param bs            Buffer holding the boot sector of the file system.
    114127 * @param dev_handle    Device handle of the file system.
     
    118131 * @param flags         Flags passed to libblock.
    119132 *
    120  * @return              Block structure holding the requested block.
    121  */
    122 block_t *
    123 _fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
    124     bn_t bn, int flags)
    125 {
    126         block_t *b;
     133 * @return              EOK on success or a negative error code.
     134 */
     135int
     136_fat_block_get(block_t **block, fat_bs_t *bs, dev_handle_t dev_handle,
     137    fat_cluster_t firstc, bn_t bn, int flags)
     138{
    127139        unsigned bps;
    128140        unsigned rscnt;         /* block address of the first FAT */
     
    131143        unsigned sf;
    132144        unsigned ssa;           /* size of the system area */
    133         unsigned clusters, max_clusters;
     145        uint16_t clusters;
     146        unsigned max_clusters;
    134147        fat_cluster_t lastc;
     148        int rc;
    135149
    136150        bps = uint16_t_le2host(bs->bps);
     
    146160                /* root directory special case */
    147161                assert(bn < rds);
    148                 b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags);
    149                 return b;
     162                rc = block_get(block, dev_handle, rscnt + bs->fatcnt * sf + bn,
     163                    flags);
     164                return rc;
    150165        }
    151166
    152167        max_clusters = bn / bs->spc;
    153         clusters = fat_cluster_walk(bs, dev_handle, firstc, &lastc,
     168        rc = fat_cluster_walk(bs, dev_handle, firstc, &lastc, &clusters,
    154169            max_clusters);
     170        if (rc != EOK)
     171                return rc;
    155172        assert(clusters == max_clusters);
    156173
    157         b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc +
    158             bn % bs->spc, flags);
    159 
    160         return b;
     174        rc = block_get(block, dev_handle,
     175            ssa + (lastc - FAT_CLST_FIRST) * bs->spc + bn % bs->spc, flags);
     176
     177        return rc;
    161178}
    162179
     
    170187 *                      this argument is ignored.
    171188 * @param pos           Position in the last node block.
    172  */
    173 void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
     189 *
     190 * @return              EOK on success or a negative error code.
     191 */
     192int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
    174193{
    175194        uint16_t bps;
     
    177196        block_t *b;
    178197        off_t o, boundary;
     198        int rc;
    179199
    180200        bps = uint16_t_le2host(bs->bps);
     
    188208                int flags = (o % bps == 0) ?
    189209                    BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE;
    190                 b = fat_block_get(bs, nodep, o / bps, flags);
     210                rc = fat_block_get(&b, bs, nodep, o / bps, flags);
     211                if (rc != EOK)
     212                        return rc;
    191213                memset(b->data + o % bps, 0, bps - o % bps);
    192214                b->dirty = true;                /* need to sync node */
    193                 block_put(b);
     215                rc = block_put(b);
     216                if (rc != EOK)
     217                        return rc;
    194218        }
    195219       
    196220        if (o >= pos)
    197                 return;
     221                return EOK;
    198222       
    199223        /* zero out the initial part of the new cluster chain */
    200224        for (o = boundary; o < pos; o += bps) {
    201                 b = _fat_block_get(bs, nodep->idx->dev_handle, mcl,
     225                rc = _fat_block_get(&b, bs, nodep->idx->dev_handle, mcl,
    202226                    (o - boundary) / bps, BLOCK_FLAGS_NOREAD);
     227                if (rc != EOK)
     228                        return rc;
    203229                memset(b->data, 0, min(bps, pos - o));
    204230                b->dirty = true;                /* need to sync node */
    205                 block_put(b);
    206         }
     231                rc = block_put(b);
     232                if (rc != EOK)
     233                        return rc;
     234        }
     235
     236        return EOK;
    207237}
    208238
     
    212242 * @param dev_handle    Device handle for the file system.
    213243 * @param clst          Cluster which to get.
    214  *
    215  * @return              Value found in the cluster.
    216  */
    217 fat_cluster_t
    218 fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst)
     244 * @param value         Output argument holding the value of the cluster.
     245 *
     246 * @return              EOK or a negative error code.
     247 */
     248int
     249fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst,
     250    fat_cluster_t *value)
    219251{
    220252        block_t *b;
    221253        uint16_t bps;
    222254        uint16_t rscnt;
    223         fat_cluster_t *cp, value;
     255        fat_cluster_t *cp;
     256        int rc;
    224257
    225258        bps = uint16_t_le2host(bs->bps);
    226259        rscnt = uint16_t_le2host(bs->rscnt);
    227260
    228         b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps,
    229             BLOCK_FLAGS_NONE);
     261        rc = block_get(&b, dev_handle, rscnt +
     262            (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);
     263        if (rc != EOK)
     264                return rc;
    230265        cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
    231         value = uint16_t_le2host(*cp);
    232         block_put(b);
    233        
    234         return value;
     266        *value = uint16_t_le2host(*cp);
     267        rc = block_put(b);
     268       
     269        return rc;
    235270}
    236271
     
    242277 * @param clst          Cluster which is to be set.
    243278 * @param value         Value to set the cluster with.
    244  */
    245 void
     279 *
     280 * @return              EOK on success or a negative error code.
     281 */
     282int
    246283fat_set_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno,
    247284    fat_cluster_t clst, fat_cluster_t value)
     
    252289        uint16_t sf;
    253290        fat_cluster_t *cp;
     291        int rc;
    254292
    255293        bps = uint16_t_le2host(bs->bps);
     
    258296
    259297        assert(fatno < bs->fatcnt);
    260         b = block_get(dev_handle, rscnt + sf * fatno +
     298        rc = block_get(&b, dev_handle, rscnt + sf * fatno +
    261299            (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);
     300        if (rc != EOK)
     301                return rc;
    262302        cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
    263303        *cp = host2uint16_t_le(value);
    264304        b->dirty = true;                /* need to sync block */
    265         block_put(b);
     305        rc = block_put(b);
     306        return rc;
    266307}
    267308
     
    272313 * @param lifo          Chain of allocated clusters.
    273314 * @param nclsts        Number of clusters in the lifo chain.
    274  */
    275 void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle,
     315 *
     316 * @return              EOK on success or a negative error code.
     317 */
     318int fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle,
    276319    fat_cluster_t *lifo, unsigned nclsts)
    277320{
    278321        uint8_t fatno;
    279322        unsigned c;
     323        int rc;
    280324
    281325        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
    282326                for (c = 0; c < nclsts; c++) {
    283                         fat_set_cluster(bs, dev_handle, fatno, lifo[c],
     327                        rc = fat_set_cluster(bs, dev_handle, fatno, lifo[c],
    284328                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     329                        if (rc != EOK)
     330                                return rc;
    285331                }
    286332        }
     333
     334        return EOK;
    287335}
    288336
     
    311359        uint16_t rscnt;
    312360        uint16_t sf;
     361        uint16_t ts;
     362        unsigned rde;
     363        unsigned rds;
     364        unsigned ssa;
    313365        block_t *blk;
    314366        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    315367        unsigned found = 0;     /* top of the free cluster number stack */
    316368        unsigned b, c, cl;
     369        int rc;
    317370
    318371        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     
    323376        rscnt = uint16_t_le2host(bs->rscnt);
    324377        sf = uint16_t_le2host(bs->sec_per_fat);
     378        rde = uint16_t_le2host(bs->root_ent_max);
     379        ts = uint16_t_le2host(bs->totsec16);
     380
     381        rds = (sizeof(fat_dentry_t) * rde) / bps;
     382        rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
     383        ssa = rscnt + bs->fatcnt * sf + rds;
    325384       
    326385        /*
     
    329388        fibril_mutex_lock(&fat_alloc_lock);
    330389        for (b = 0, cl = 0; b < sf; b++) {
    331                 blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
     390                rc = block_get(&blk, dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
     391                if (rc != EOK)
     392                        goto error;
    332393                for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
     394                        /*
     395                         * Check if the cluster is physically there. This check
     396                         * becomes necessary when the file system is created
     397                         * with fewer total sectors than how many is inferred
     398                         * from the size of the file allocation table.
     399                         */
     400                        if ((cl - 2) * bs->spc + ssa >= ts) {
     401                                rc = block_put(blk);
     402                                if (rc != EOK)
     403                                        goto error;
     404                                goto out;
     405                        }
     406
    333407                        fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    334408                        if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
     
    344418                                if (++found == nclsts) {
    345419                                        /* we are almost done */
    346                                         block_put(blk);
     420                                        rc = block_put(blk);
     421                                        if (rc != EOK)
     422                                                goto error;
    347423                                        /* update the shadow copies of FAT */
    348                                         fat_alloc_shadow_clusters(bs,
     424                                        rc = fat_alloc_shadow_clusters(bs,
    349425                                            dev_handle, lifo, nclsts);
     426                                        if (rc != EOK)
     427                                                goto error;
    350428                                        *mcl = lifo[found - 1];
    351429                                        *lcl = lifo[0];
     
    356434                        }
    357435                }
    358                 block_put(blk);
    359         }
     436                rc = block_put(blk);
     437                if (rc != EOK) {
     438error:
     439                        fibril_mutex_unlock(&fat_alloc_lock);
     440                        free(lifo);
     441                        return rc;
     442                }
     443        }
     444out:
    360445        fibril_mutex_unlock(&fat_alloc_lock);
    361446
     
    365450         */
    366451        while (found--) {
    367                 fat_set_cluster(bs, dev_handle, FAT1, lifo[found],
     452                rc = fat_set_cluster(bs, dev_handle, FAT1, lifo[found],
    368453                    FAT_CLST_RES0);
     454                if (rc != EOK) {
     455                        free(lifo);
     456                        return rc;
     457                }
    369458        }
    370459       
     
    378467 * @param dev_handle    Device handle of the file system.
    379468 * @param firstc        First cluster in the chain which is to be freed.
    380  */
    381 void
     469 *
     470 * @return              EOK on success or a negative return code.
     471 */
     472int
    382473fat_free_clusters(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc)
    383474{
    384475        unsigned fatno;
    385476        fat_cluster_t nextc;
     477        int rc;
    386478
    387479        /* Mark all clusters in the chain as free in all copies of FAT. */
    388480        while (firstc < FAT_CLST_LAST1) {
    389481                assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
    390                 nextc = fat_get_cluster(bs, dev_handle, firstc);
    391                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
    392                         fat_set_cluster(bs, dev_handle, fatno, firstc,
     482                rc = fat_get_cluster(bs, dev_handle, firstc, &nextc);
     483                if (rc != EOK)
     484                        return rc;
     485                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     486                        rc = fat_set_cluster(bs, dev_handle, fatno, firstc,
    393487                            FAT_CLST_RES0);
     488                        if (rc != EOK)
     489                                return rc;
     490                }
     491
    394492                firstc = nextc;
    395493        }
     494
     495        return EOK;
    396496}
    397497
     
    401501 * @param nodep         Node representing the file.
    402502 * @param mcl           First cluster of the cluster chain to append.
    403  */
    404 void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl)
     503 *
     504 * @return              EOK on success or a negative error code.
     505 */
     506int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl)
    405507{
    406508        dev_handle_t dev_handle = nodep->idx->dev_handle;
    407509        fat_cluster_t lcl;
     510        uint16_t numc;
    408511        uint8_t fatno;
    409 
    410         if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl,
    411             (uint16_t) -1) == 0) {
     512        int rc;
     513
     514        rc = fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl, &numc,
     515            (uint16_t) -1);
     516        if (rc != EOK)
     517                return rc;
     518
     519        if (numc == 0) {
    412520                /* No clusters allocated to the node yet. */
    413521                nodep->firstc = mcl;
    414522                nodep->dirty = true;            /* need to sync node */
    415                 return;
    416         }
    417 
    418         for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
    419                 fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl);
     523                return EOK;
     524        }
     525
     526        for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     527                rc = fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl,
     528                    mcl);
     529                if (rc != EOK)
     530                        return rc;
     531        }
     532
     533        return EOK;
    420534}
    421535
     
    427541 *                      argument is FAT_CLST_RES0, then all clusters will
    428542 *                      be chopped off.
    429  */
    430 void fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc)
    431 {
     543 *
     544 * @return              EOK on success or a negative return code.
     545 */
     546int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc)
     547{
     548        int rc;
     549
    432550        dev_handle_t dev_handle = nodep->idx->dev_handle;
    433551        if (lastc == FAT_CLST_RES0) {
    434552                /* The node will have zero size and no clusters allocated. */
    435                 fat_free_clusters(bs, dev_handle, nodep->firstc);
     553                rc = fat_free_clusters(bs, dev_handle, nodep->firstc);
     554                if (rc != EOK)
     555                        return rc;
    436556                nodep->firstc = FAT_CLST_RES0;
    437557                nodep->dirty = true;            /* need to sync node */
     
    440560                unsigned fatno;
    441561
    442                 nextc = fat_get_cluster(bs, dev_handle, lastc);
     562                rc = fat_get_cluster(bs, dev_handle, lastc, &nextc);
     563                if (rc != EOK)
     564                        return rc;
    443565
    444566                /* Terminate the cluster chain in all copies of FAT. */
    445                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
    446                         fat_set_cluster(bs, dev_handle, fatno, lastc, FAT_CLST_LAST1);
     567                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     568                        rc = fat_set_cluster(bs, dev_handle, fatno, lastc,
     569                            FAT_CLST_LAST1);
     570                        if (rc != EOK)
     571                                return rc;
     572                }
    447573
    448574                /* Free all following clusters. */
    449                 fat_free_clusters(bs, dev_handle, nextc);
    450         }
    451 }
    452 
    453 void
     575                rc = fat_free_clusters(bs, dev_handle, nextc);
     576                if (rc != EOK)
     577                        return rc;
     578        }
     579
     580        return EOK;
     581}
     582
     583int
    454584fat_zero_cluster(struct fat_bs *bs, dev_handle_t dev_handle, fat_cluster_t c)
    455585{
     
    457587        block_t *b;
    458588        unsigned bps;
     589        int rc;
    459590
    460591        bps = uint16_t_le2host(bs->bps);
    461592       
    462593        for (i = 0; i < bs->spc; i++) {
    463                 b = _fat_block_get(bs, dev_handle, c, i, BLOCK_FLAGS_NOREAD);
     594                rc = _fat_block_get(&b, bs, dev_handle, c, i,
     595                    BLOCK_FLAGS_NOREAD);
     596                if (rc != EOK)
     597                        return rc;
    464598                memset(b->data, 0, bps);
    465599                b->dirty = true;
    466                 block_put(b);
    467         }
     600                rc = block_put(b);
     601                if (rc != EOK)
     602                        return rc;
     603        }
     604
     605        return EOK;
    468606}
    469607
  • uspace/srv/fs/fat/fat_fat.h

    rfcbd1be r1787e527  
    5959typedef uint16_t fat_cluster_t;
    6060
    61 #define fat_clusters_get(bs, dh, fc) \
    62     fat_cluster_walk((bs), (dh), (fc), NULL, (uint16_t) -1)
    63 extern uint16_t fat_cluster_walk(struct fat_bs *, dev_handle_t, fat_cluster_t,
    64     fat_cluster_t *, uint16_t);
     61#define fat_clusters_get(numc, bs, dh, fc) \
     62    fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1)
     63extern int fat_cluster_walk(struct fat_bs *, dev_handle_t, fat_cluster_t,
     64    fat_cluster_t *, uint16_t *, uint16_t);
    6565
    66 #define fat_block_get(bs, np, bn, flags) \
    67     _fat_block_get((bs), (np)->idx->dev_handle, (np)->firstc, (bn), (flags))
     66#define fat_block_get(b, bs, np, bn, flags) \
     67    _fat_block_get((b), (bs), (np)->idx->dev_handle, (np)->firstc, (bn), \
     68    (flags))
    6869
    69 extern struct block *_fat_block_get(struct fat_bs *, dev_handle_t,
     70extern int _fat_block_get(block_t **, struct fat_bs *, dev_handle_t,
    7071    fat_cluster_t, bn_t, int);
    7172 
    72 extern void fat_append_clusters(struct fat_bs *, struct fat_node *,
     73extern int fat_append_clusters(struct fat_bs *, struct fat_node *,
    7374    fat_cluster_t);
    74 extern void fat_chop_clusters(struct fat_bs *, struct fat_node *,
     75extern int fat_chop_clusters(struct fat_bs *, struct fat_node *,
    7576    fat_cluster_t);
    7677extern int fat_alloc_clusters(struct fat_bs *, dev_handle_t, unsigned,
    7778    fat_cluster_t *, fat_cluster_t *);
    78 extern void fat_free_clusters(struct fat_bs *, dev_handle_t, fat_cluster_t);
    79 extern void fat_alloc_shadow_clusters(struct fat_bs *, dev_handle_t,
     79extern int fat_free_clusters(struct fat_bs *, dev_handle_t, fat_cluster_t);
     80extern int fat_alloc_shadow_clusters(struct fat_bs *, dev_handle_t,
    8081    fat_cluster_t *, unsigned);
    81 extern fat_cluster_t fat_get_cluster(struct fat_bs *, dev_handle_t, fat_cluster_t);
    82 extern void fat_set_cluster(struct fat_bs *, dev_handle_t, unsigned,
     82extern int fat_get_cluster(struct fat_bs *, dev_handle_t, fat_cluster_t,
     83    fat_cluster_t *);
     84extern int fat_set_cluster(struct fat_bs *, dev_handle_t, unsigned,
    8385    fat_cluster_t, fat_cluster_t);
    84 extern void fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t,
     86extern int fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t,
    8587    off_t);
    86 extern void fat_zero_cluster(struct fat_bs *, dev_handle_t, fat_cluster_t);
     88extern int fat_zero_cluster(struct fat_bs *, dev_handle_t, fat_cluster_t);
    8789
    8890#endif
  • uspace/srv/fs/fat/fat_idx.c

    rfcbd1be r1787e527  
    339339}
    340340
    341 static fat_idx_t *fat_idx_create(dev_handle_t dev_handle)
     341static int fat_idx_create(fat_idx_t **fidxp, dev_handle_t dev_handle)
    342342{
    343343        fat_idx_t *fidx;
     
    345345        fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t));
    346346        if (!fidx)
    347                 return NULL;
     347                return ENOMEM;
    348348        if (!fat_index_alloc(dev_handle, &fidx->index)) {
    349349                free(fidx);
    350                 return NULL;
     350                return ENOSPC;
    351351        }
    352352               
     
    359359        fidx->nodep = NULL;
    360360
    361         return fidx;
    362 }
    363 
    364 fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle)
     361        *fidxp = fidx;
     362        return EOK;
     363}
     364
     365int fat_idx_get_new(fat_idx_t **fidxp, dev_handle_t dev_handle)
    365366{
    366367        fat_idx_t *fidx;
     368        int rc;
    367369
    368370        fibril_mutex_lock(&used_lock);
    369         fidx = fat_idx_create(dev_handle);
    370         if (!fidx) {
     371        rc = fat_idx_create(&fidx, dev_handle);
     372        if (rc != EOK) {
    371373                fibril_mutex_unlock(&used_lock);
    372                 return NULL;
     374                return rc;
    373375        }
    374376               
     
    382384        fibril_mutex_unlock(&used_lock);
    383385
    384         return fidx;
     386        *fidxp = fidx;
     387        return EOK;
    385388}
    386389
     
    401404                fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
    402405        } else {
    403                 fidx = fat_idx_create(dev_handle);
    404                 if (!fidx) {
     406                int rc;
     407
     408                rc = fat_idx_create(&fidx, dev_handle);
     409                if (rc != EOK) {
    405410                        fibril_mutex_unlock(&used_lock);
    406411                        return NULL;
  • uspace/srv/fs/fat/fat_ops.c

    rfcbd1be r1787e527  
    6565static LIST_INITIALIZE(ffn_head);
    6666
     67/*
     68 * Forward declarations of FAT libfs operations.
     69 */
     70static int fat_root_get(fs_node_t **, dev_handle_t);
     71static int fat_match(fs_node_t **, fs_node_t *, const char *);
     72static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t);
     73static int fat_node_put(fs_node_t *);
     74static int fat_create_node(fs_node_t **, dev_handle_t, int);
     75static int fat_destroy_node(fs_node_t *);
     76static int fat_link(fs_node_t *, fs_node_t *, const char *);
     77static int fat_unlink(fs_node_t *, fs_node_t *, const char *);
     78static int fat_has_children(bool *, fs_node_t *);
     79static fs_index_t fat_index_get(fs_node_t *);
     80static size_t fat_size_get(fs_node_t *);
     81static unsigned fat_lnkcnt_get(fs_node_t *);
     82static char fat_plb_get_char(unsigned);
     83static bool fat_is_directory(fs_node_t *);
     84static bool fat_is_file(fs_node_t *node);
     85
     86/*
     87 * Helper functions.
     88 */
    6789static void fat_node_initialize(fat_node_t *node)
    6890{
     
    78100}
    79101
    80 static void fat_node_sync(fat_node_t *node)
     102static int fat_node_sync(fat_node_t *node)
    81103{
    82104        block_t *b;
     
    85107        uint16_t bps;
    86108        unsigned dps;
     109        int rc;
    87110       
    88111        assert(node->dirty);
     
    93116       
    94117        /* Read the block that contains the dentry of interest. */
    95         b = _fat_block_get(bs, node->idx->dev_handle, node->idx->pfc,
     118        rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc,
    96119            (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
     120        if (rc != EOK)
     121                return rc;
    97122
    98123        d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
     
    108133       
    109134        b->dirty = true;                /* need to sync block */
    110         block_put(b);
    111 }
    112 
    113 static fat_node_t *fat_node_get_new(void)
     135        rc = block_put(b);
     136        return rc;
     137}
     138
     139static int fat_node_get_new(fat_node_t **nodepp)
    114140{
    115141        fs_node_t *fn;
    116142        fat_node_t *nodep;
     143        int rc;
    117144
    118145        fibril_mutex_lock(&ffn_mutex);
     
    130157                list_remove(&nodep->ffn_link);
    131158                fibril_mutex_unlock(&ffn_mutex);
    132                 if (nodep->dirty)
    133                         fat_node_sync(nodep);
     159                if (nodep->dirty) {
     160                        rc = fat_node_sync(nodep);
     161                        if (rc != EOK) {
     162                                idxp_tmp->nodep = NULL;
     163                                fibril_mutex_unlock(&nodep->lock);
     164                                fibril_mutex_unlock(&idxp_tmp->lock);
     165                                free(nodep->bp);
     166                                free(nodep);
     167                                return rc;
     168                        }
     169                }
    134170                idxp_tmp->nodep = NULL;
    135171                fibril_mutex_unlock(&nodep->lock);
     
    142178                fn = (fs_node_t *)malloc(sizeof(fs_node_t));
    143179                if (!fn)
    144                         return NULL;
     180                        return ENOMEM;
    145181                nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
    146182                if (!nodep) {
    147183                        free(fn);
    148                         return NULL;
     184                        return ENOMEM;
    149185                }
    150186        }
     
    154190        nodep->bp = fn;
    155191       
    156         return nodep;
     192        *nodepp = nodep;
     193        return EOK;
    157194}
    158195
     
    161198 * @param idxp          Locked index structure.
    162199 */
    163 static fat_node_t *fat_node_get_core(fat_idx_t *idxp)
     200static int fat_node_get_core(fat_node_t **nodepp, fat_idx_t *idxp)
    164201{
    165202        block_t *b;
     
    170207        unsigned spc;
    171208        unsigned dps;
     209        int rc;
    172210
    173211        if (idxp->nodep) {
     
    177215                 */
    178216                fibril_mutex_lock(&idxp->nodep->lock);
    179                 if (!idxp->nodep->refcnt++)
     217                if (!idxp->nodep->refcnt++) {
     218                        fibril_mutex_lock(&ffn_mutex);
    180219                        list_remove(&idxp->nodep->ffn_link);
     220                        fibril_mutex_unlock(&ffn_mutex);
     221                }
    181222                fibril_mutex_unlock(&idxp->nodep->lock);
    182                 return idxp->nodep;
     223                *nodepp = idxp->nodep;
     224                return EOK;
    183225        }
    184226
     
    189231        assert(idxp->pfc);
    190232
    191         nodep = fat_node_get_new();
    192         if (!nodep)
    193                 return NULL;
     233        rc = fat_node_get_new(&nodep);
     234        if (rc != EOK)
     235                return rc;
    194236
    195237        bs = block_bb_get(idxp->dev_handle);
     
    199241
    200242        /* Read the block that contains the dentry of interest. */
    201         b = _fat_block_get(bs, idxp->dev_handle, idxp->pfc,
     243        rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc,
    202244            (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
    203         assert(b);
     245        if (rc != EOK) {
     246                (void) fat_node_put(FS_NODE(nodep));
     247                return rc;
     248        }
    204249
    205250        d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
     
    216261                 * size of the directory by walking the FAT.
    217262                 */
    218                 nodep->size = bps * spc * fat_clusters_get(bs, idxp->dev_handle,
     263                uint16_t clusters;
     264                rc = fat_clusters_get(&clusters, bs, idxp->dev_handle,
    219265                    uint16_t_le2host(d->firstc));
     266                if (rc != EOK) {
     267                        (void) fat_node_put(FS_NODE(nodep));
     268                        return rc;
     269                }
     270                nodep->size = bps * spc * clusters;
    220271        } else {
    221272                nodep->type = FAT_FILE;
     
    226277        nodep->refcnt = 1;
    227278
    228         block_put(b);
     279        rc = block_put(b);
     280        if (rc != EOK) {
     281                (void) fat_node_put(FS_NODE(nodep));
     282                return rc;
     283        }
    229284
    230285        /* Link the idx structure with the node structure. */
     
    232287        idxp->nodep = nodep;
    233288
    234         return nodep;
    235 }
    236 
    237 /*
    238  * Forward declarations of FAT libfs operations.
    239  */
    240 static fs_node_t *fat_node_get(dev_handle_t, fs_index_t);
    241 static void fat_node_put(fs_node_t *);
    242 static fs_node_t *fat_create_node(dev_handle_t, int);
    243 static int fat_destroy_node(fs_node_t *);
    244 static int fat_link(fs_node_t *, fs_node_t *, const char *);
    245 static int fat_unlink(fs_node_t *, fs_node_t *, const char *);
    246 static fs_node_t *fat_match(fs_node_t *, const char *);
    247 static fs_index_t fat_index_get(fs_node_t *);
    248 static size_t fat_size_get(fs_node_t *);
    249 static unsigned fat_lnkcnt_get(fs_node_t *);
    250 static bool fat_has_children(fs_node_t *);
    251 static fs_node_t *fat_root_get(dev_handle_t);
    252 static char fat_plb_get_char(unsigned);
    253 static bool fat_is_directory(fs_node_t *);
    254 static bool fat_is_file(fs_node_t *node);
     289        *nodepp = nodep;
     290        return EOK;
     291}
    255292
    256293/*
     
    258295 */
    259296
    260 /** Instantiate a FAT in-core node. */
    261 fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
    262 {
    263         fat_node_t *nodep;
    264         fat_idx_t *idxp;
    265 
    266         idxp = fat_idx_get_by_index(dev_handle, index);
    267         if (!idxp)
    268                 return NULL;
    269         /* idxp->lock held */
    270         nodep = fat_node_get_core(idxp);
    271         fibril_mutex_unlock(&idxp->lock);
    272         return FS_NODE(nodep);
    273 }
    274 
    275 void fat_node_put(fs_node_t *fn)
    276 {
    277         fat_node_t *nodep = FAT_NODE(fn);
    278         bool destroy = false;
    279 
    280         fibril_mutex_lock(&nodep->lock);
    281         if (!--nodep->refcnt) {
    282                 if (nodep->idx) {
    283                         fibril_mutex_lock(&ffn_mutex);
    284                         list_append(&nodep->ffn_link, &ffn_head);
    285                         fibril_mutex_unlock(&ffn_mutex);
    286                 } else {
    287                         /*
    288                          * The node does not have any index structure associated
    289                          * with itself. This can only mean that we are releasing
    290                          * the node after a failed attempt to allocate the index
    291                          * structure for it.
    292                          */
    293                         destroy = true;
    294                 }
    295         }
    296         fibril_mutex_unlock(&nodep->lock);
    297         if (destroy) {
    298                 free(nodep->bp);
    299                 free(nodep);
    300         }
    301 }
    302 
    303 fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags)
    304 {
    305         fat_idx_t *idxp;
    306         fat_node_t *nodep;
    307         fat_bs_t *bs;
    308         fat_cluster_t mcl, lcl;
    309         uint16_t bps;
    310         int rc;
    311 
    312         bs = block_bb_get(dev_handle);
    313         bps = uint16_t_le2host(bs->bps);
    314         if (flags & L_DIRECTORY) {
    315                 /* allocate a cluster */
    316                 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl);
    317                 if (rc != EOK)
    318                         return NULL;
    319         }
    320 
    321         nodep = fat_node_get_new();
    322         if (!nodep) {
    323                 fat_free_clusters(bs, dev_handle, mcl);
    324                 return NULL;
    325         }
    326         idxp = fat_idx_get_new(dev_handle);
    327         if (!idxp) {
    328                 fat_free_clusters(bs, dev_handle, mcl);
    329                 fat_node_put(FS_NODE(nodep));
    330                 return NULL;
    331         }
    332         /* idxp->lock held */
    333         if (flags & L_DIRECTORY) {
    334                 /* Populate the new cluster with unused dentries. */
    335                 fat_zero_cluster(bs, dev_handle, mcl);
    336                 nodep->type = FAT_DIRECTORY;
    337                 nodep->firstc = mcl;
    338                 nodep->size = bps * bs->spc;
    339         } else {
    340                 nodep->type = FAT_FILE;
    341                 nodep->firstc = FAT_CLST_RES0;
    342                 nodep->size = 0;
    343         }
    344         nodep->lnkcnt = 0;      /* not linked anywhere */
    345         nodep->refcnt = 1;
    346         nodep->dirty = true;
    347 
    348         nodep->idx = idxp;
    349         idxp->nodep = nodep;
    350 
    351         fibril_mutex_unlock(&idxp->lock);
    352         return FS_NODE(nodep);
    353 }
    354 
    355 int fat_destroy_node(fs_node_t *fn)
    356 {
    357         fat_node_t *nodep = FAT_NODE(fn);
    358         fat_bs_t *bs;
    359 
    360         /*
    361          * The node is not reachable from the file system. This means that the
    362          * link count should be zero and that the index structure cannot be
    363          * found in the position hash. Obviously, we don't need to lock the node
    364          * nor its index structure.
    365          */
    366         assert(nodep->lnkcnt == 0);
    367 
    368         /*
    369          * The node may not have any children.
    370          */
    371         assert(fat_has_children(fn) == false);
    372 
    373         bs = block_bb_get(nodep->idx->dev_handle);
    374         if (nodep->firstc != FAT_CLST_RES0) {
    375                 assert(nodep->size);
    376                 /* Free all clusters allocated to the node. */
    377                 fat_free_clusters(bs, nodep->idx->dev_handle, nodep->firstc);
    378         }
    379 
    380         fat_idx_destroy(nodep->idx);
    381         free(nodep->bp);
    382         free(nodep);
    383         return EOK;
    384 }
    385 
    386 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
    387 {
    388         fat_node_t *parentp = FAT_NODE(pfn);
    389         fat_node_t *childp = FAT_NODE(cfn);
    390         fat_dentry_t *d;
    391         fat_bs_t *bs;
    392         block_t *b;
    393         unsigned i, j;
    394         uint16_t bps;
    395         unsigned dps;
    396         unsigned blocks;
    397         fat_cluster_t mcl, lcl;
    398         int rc;
    399 
    400         fibril_mutex_lock(&childp->lock);
    401         if (childp->lnkcnt == 1) {
    402                 /*
    403                  * On FAT, we don't support multiple hard links.
    404                  */
    405                 fibril_mutex_unlock(&childp->lock);
    406                 return EMLINK;
    407         }
    408         assert(childp->lnkcnt == 0);
    409         fibril_mutex_unlock(&childp->lock);
    410 
    411         if (!fat_dentry_name_verify(name)) {
    412                 /*
    413                  * Attempt to create unsupported name.
    414                  */
    415                 return ENOTSUP;
    416         }
    417 
    418         /*
    419          * Get us an unused parent node's dentry or grow the parent and allocate
    420          * a new one.
    421          */
    422        
    423         fibril_mutex_lock(&parentp->idx->lock);
    424         bs = block_bb_get(parentp->idx->dev_handle);
    425         bps = uint16_t_le2host(bs->bps);
    426         dps = bps / sizeof(fat_dentry_t);
    427 
    428         blocks = parentp->size / bps;
    429 
    430         for (i = 0; i < blocks; i++) {
    431                 b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE);
    432                 for (j = 0; j < dps; j++) {
    433                         d = ((fat_dentry_t *)b->data) + j;
    434                         switch (fat_classify_dentry(d)) {
    435                         case FAT_DENTRY_SKIP:
    436                         case FAT_DENTRY_VALID:
    437                                 /* skipping used and meta entries */
    438                                 continue;
    439                         case FAT_DENTRY_FREE:
    440                         case FAT_DENTRY_LAST:
    441                                 /* found an empty slot */
    442                                 goto hit;
    443                         }
    444                 }
    445                 block_put(b);
    446         }
    447         j = 0;
    448        
    449         /*
    450          * We need to grow the parent in order to create a new unused dentry.
    451          */
    452         if (parentp->firstc == FAT_CLST_ROOT) {
    453                 /* Can't grow the root directory. */
    454                 fibril_mutex_unlock(&parentp->idx->lock);
    455                 return ENOSPC;
    456         }
    457         rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
    458         if (rc != EOK) {
    459                 fibril_mutex_unlock(&parentp->idx->lock);
    460                 return rc;
    461         }
    462         fat_zero_cluster(bs, parentp->idx->dev_handle, mcl);
    463         fat_append_clusters(bs, parentp, mcl);
    464         parentp->size += bps * bs->spc;
    465         parentp->dirty = true;          /* need to sync node */
    466         b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE);
    467         d = (fat_dentry_t *)b->data;
    468 
    469 hit:
    470         /*
    471          * At this point we only establish the link between the parent and the
    472          * child.  The dentry, except of the name and the extension, will remain
    473          * uninitialized until the corresponding node is synced. Thus the valid
    474          * dentry data is kept in the child node structure.
    475          */
    476         memset(d, 0, sizeof(fat_dentry_t));
    477         fat_dentry_name_set(d, name);
    478         b->dirty = true;                /* need to sync block */
    479         block_put(b);
    480         fibril_mutex_unlock(&parentp->idx->lock);
    481 
    482         fibril_mutex_lock(&childp->idx->lock);
    483        
    484         /*
    485          * If possible, create the Sub-directory Identifier Entry and the
    486          * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
    487          * are not mandatory according to Standard ECMA-107 and HelenOS VFS does
    488          * not use them anyway, so this is rather a sign of our good will.
    489          */
    490         b = fat_block_get(bs, childp, 0, BLOCK_FLAGS_NONE);
    491         d = (fat_dentry_t *)b->data;
    492         if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
    493             str_cmp(d->name, FAT_NAME_DOT) == 0) {
    494                 memset(d, 0, sizeof(fat_dentry_t));
    495                 str_cpy(d->name, 8, FAT_NAME_DOT);
    496                 str_cpy(d->ext, 3, FAT_EXT_PAD);
    497                 d->attr = FAT_ATTR_SUBDIR;
    498                 d->firstc = host2uint16_t_le(childp->firstc);
    499                 /* TODO: initialize also the date/time members. */
    500         }
    501         d++;
    502         if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
    503             str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) {
    504                 memset(d, 0, sizeof(fat_dentry_t));
    505                 str_cpy(d->name, 8, FAT_NAME_DOT_DOT);
    506                 str_cpy(d->ext, 3, FAT_EXT_PAD);
    507                 d->attr = FAT_ATTR_SUBDIR;
    508                 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    509                     host2uint16_t_le(FAT_CLST_RES0) :
    510                     host2uint16_t_le(parentp->firstc);
    511                 /* TODO: initialize also the date/time members. */
    512         }
    513         b->dirty = true;                /* need to sync block */
    514         block_put(b);
    515 
    516         childp->idx->pfc = parentp->firstc;
    517         childp->idx->pdi = i * dps + j;
    518         fibril_mutex_unlock(&childp->idx->lock);
    519 
    520         fibril_mutex_lock(&childp->lock);
    521         childp->lnkcnt = 1;
    522         childp->dirty = true;           /* need to sync node */
    523         fibril_mutex_unlock(&childp->lock);
    524 
    525         /*
    526          * Hash in the index structure into the position hash.
    527          */
    528         fat_idx_hashin(childp->idx);
    529 
    530         return EOK;
    531 }
    532 
    533 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
    534 {
    535         fat_node_t *parentp = FAT_NODE(pfn);
    536         fat_node_t *childp = FAT_NODE(cfn);
    537         fat_bs_t *bs;
    538         fat_dentry_t *d;
    539         uint16_t bps;
    540         block_t *b;
    541 
    542         if (!parentp)
    543                 return EBUSY;
    544        
    545         if (fat_has_children(cfn))
    546                 return ENOTEMPTY;
    547 
    548         fibril_mutex_lock(&parentp->lock);
    549         fibril_mutex_lock(&childp->lock);
    550         assert(childp->lnkcnt == 1);
    551         fibril_mutex_lock(&childp->idx->lock);
    552         bs = block_bb_get(childp->idx->dev_handle);
    553         bps = uint16_t_le2host(bs->bps);
    554 
    555         b = _fat_block_get(bs, childp->idx->dev_handle, childp->idx->pfc,
    556             (childp->idx->pdi * sizeof(fat_dentry_t)) / bps,
    557             BLOCK_FLAGS_NONE);
    558         d = (fat_dentry_t *)b->data +
    559             (childp->idx->pdi % (bps / sizeof(fat_dentry_t)));
    560         /* mark the dentry as not-currently-used */
    561         d->name[0] = FAT_DENTRY_ERASED;
    562         b->dirty = true;                /* need to sync block */
    563         block_put(b);
    564 
    565         /* remove the index structure from the position hash */
    566         fat_idx_hashout(childp->idx);
    567         /* clear position information */
    568         childp->idx->pfc = FAT_CLST_RES0;
    569         childp->idx->pdi = 0;
    570         fibril_mutex_unlock(&childp->idx->lock);
    571         childp->lnkcnt = 0;
    572         childp->dirty = true;
    573         fibril_mutex_unlock(&childp->lock);
    574         fibril_mutex_unlock(&parentp->lock);
    575 
    576         return EOK;
    577 }
    578 
    579 fs_node_t *fat_match(fs_node_t *pfn, const char *component)
     297int fat_root_get(fs_node_t **rfn, dev_handle_t dev_handle)
     298{
     299        return fat_node_get(rfn, dev_handle, 0);
     300}
     301
     302int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    580303{
    581304        fat_bs_t *bs;
     
    588311        fat_dentry_t *d;
    589312        block_t *b;
     313        int rc;
    590314
    591315        fibril_mutex_lock(&parentp->idx->lock);
     
    595319        blocks = parentp->size / bps;
    596320        for (i = 0; i < blocks; i++) {
    597                 b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE);
     321                rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     322                if (rc != EOK) {
     323                        fibril_mutex_unlock(&parentp->idx->lock);
     324                        return rc;
     325                }
    598326                for (j = 0; j < dps; j++) {
    599327                        d = ((fat_dentry_t *)b->data) + j;
     
    603331                                continue;
    604332                        case FAT_DENTRY_LAST:
    605                                 block_put(b);
     333                                /* miss */
     334                                rc = block_put(b);
    606335                                fibril_mutex_unlock(&parentp->idx->lock);
    607                                 return NULL;
     336                                *rfn = NULL;
     337                                return rc;
    608338                        default:
    609339                        case FAT_DENTRY_VALID:
     
    629359                                         * run out of 32-bit indices.
    630360                                         */
    631                                         block_put(b);
    632                                         return NULL;
     361                                        rc = block_put(b);
     362                                        return (rc == EOK) ? ENOMEM : rc;
    633363                                }
    634                                 nodep = fat_node_get_core(idx);
     364                                rc = fat_node_get_core(&nodep, idx);
    635365                                fibril_mutex_unlock(&idx->lock);
    636                                 block_put(b);
    637                                 return FS_NODE(nodep);
     366                                if (rc != EOK) {
     367                                        (void) block_put(b);
     368                                        return rc;
     369                                }
     370                                *rfn = FS_NODE(nodep);
     371                                rc = block_put(b);
     372                                if (rc != EOK)
     373                                        (void) fat_node_put(*rfn);
     374                                return rc;
    638375                        }
    639376                }
    640                 block_put(b);
     377                rc = block_put(b);
     378                if (rc != EOK) {
     379                        fibril_mutex_unlock(&parentp->idx->lock);
     380                        return rc;
     381                }
    641382        }
    642383
    643384        fibril_mutex_unlock(&parentp->idx->lock);
    644         return NULL;
    645 }
    646 
    647 fs_index_t fat_index_get(fs_node_t *fn)
    648 {
    649         return FAT_NODE(fn)->idx->index;
    650 }
    651 
    652 size_t fat_size_get(fs_node_t *fn)
    653 {
    654         return FAT_NODE(fn)->size;
    655 }
    656 
    657 unsigned fat_lnkcnt_get(fs_node_t *fn)
    658 {
    659         return FAT_NODE(fn)->lnkcnt;
    660 }
    661 
    662 bool fat_has_children(fs_node_t *fn)
     385        *rfn = NULL;
     386        return EOK;
     387}
     388
     389/** Instantiate a FAT in-core node. */
     390int fat_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index)
     391{
     392        fat_node_t *nodep;
     393        fat_idx_t *idxp;
     394        int rc;
     395
     396        idxp = fat_idx_get_by_index(dev_handle, index);
     397        if (!idxp) {
     398                *rfn = NULL;
     399                return EOK;
     400        }
     401        /* idxp->lock held */
     402        rc = fat_node_get_core(&nodep, idxp);
     403        fibril_mutex_unlock(&idxp->lock);
     404        if (rc == EOK)
     405                *rfn = FS_NODE(nodep);
     406        return rc;
     407}
     408
     409int fat_node_put(fs_node_t *fn)
     410{
     411        fat_node_t *nodep = FAT_NODE(fn);
     412        bool destroy = false;
     413
     414        fibril_mutex_lock(&nodep->lock);
     415        if (!--nodep->refcnt) {
     416                if (nodep->idx) {
     417                        fibril_mutex_lock(&ffn_mutex);
     418                        list_append(&nodep->ffn_link, &ffn_head);
     419                        fibril_mutex_unlock(&ffn_mutex);
     420                } else {
     421                        /*
     422                         * The node does not have any index structure associated
     423                         * with itself. This can only mean that we are releasing
     424                         * the node after a failed attempt to allocate the index
     425                         * structure for it.
     426                         */
     427                        destroy = true;
     428                }
     429        }
     430        fibril_mutex_unlock(&nodep->lock);
     431        if (destroy) {
     432                free(nodep->bp);
     433                free(nodep);
     434        }
     435        return EOK;
     436}
     437
     438int fat_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int flags)
     439{
     440        fat_idx_t *idxp;
     441        fat_node_t *nodep;
     442        fat_bs_t *bs;
     443        fat_cluster_t mcl, lcl;
     444        uint16_t bps;
     445        int rc;
     446
     447        bs = block_bb_get(dev_handle);
     448        bps = uint16_t_le2host(bs->bps);
     449        if (flags & L_DIRECTORY) {
     450                /* allocate a cluster */
     451                rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl);
     452                if (rc != EOK)
     453                        return rc;
     454                /* populate the new cluster with unused dentries */
     455                rc = fat_zero_cluster(bs, dev_handle, mcl);
     456                if (rc != EOK) {
     457                        (void) fat_free_clusters(bs, dev_handle, mcl);
     458                        return rc;
     459                }
     460        }
     461
     462        rc = fat_node_get_new(&nodep);
     463        if (rc != EOK) {
     464                (void) fat_free_clusters(bs, dev_handle, mcl);
     465                return rc;
     466        }
     467        rc = fat_idx_get_new(&idxp, dev_handle);
     468        if (rc != EOK) {
     469                (void) fat_free_clusters(bs, dev_handle, mcl); 
     470                (void) fat_node_put(FS_NODE(nodep));
     471                return rc;
     472        }
     473        /* idxp->lock held */
     474        if (flags & L_DIRECTORY) {
     475                nodep->type = FAT_DIRECTORY;
     476                nodep->firstc = mcl;
     477                nodep->size = bps * bs->spc;
     478        } else {
     479                nodep->type = FAT_FILE;
     480                nodep->firstc = FAT_CLST_RES0;
     481                nodep->size = 0;
     482        }
     483        nodep->lnkcnt = 0;      /* not linked anywhere */
     484        nodep->refcnt = 1;
     485        nodep->dirty = true;
     486
     487        nodep->idx = idxp;
     488        idxp->nodep = nodep;
     489
     490        fibril_mutex_unlock(&idxp->lock);
     491        *rfn = FS_NODE(nodep);
     492        return EOK;
     493}
     494
     495int fat_destroy_node(fs_node_t *fn)
     496{
     497        fat_node_t *nodep = FAT_NODE(fn);
     498        fat_bs_t *bs;
     499        bool has_children;
     500        int rc;
     501
     502        /*
     503         * The node is not reachable from the file system. This means that the
     504         * link count should be zero and that the index structure cannot be
     505         * found in the position hash. Obviously, we don't need to lock the node
     506         * nor its index structure.
     507         */
     508        assert(nodep->lnkcnt == 0);
     509
     510        /*
     511         * The node may not have any children.
     512         */
     513        rc = fat_has_children(&has_children, fn);
     514        if (rc != EOK)
     515                return rc;
     516        assert(!has_children);
     517
     518        bs = block_bb_get(nodep->idx->dev_handle);
     519        if (nodep->firstc != FAT_CLST_RES0) {
     520                assert(nodep->size);
     521                /* Free all clusters allocated to the node. */
     522                rc = fat_free_clusters(bs, nodep->idx->dev_handle,
     523                    nodep->firstc);
     524        }
     525
     526        fat_idx_destroy(nodep->idx);
     527        free(nodep->bp);
     528        free(nodep);
     529        return rc;
     530}
     531
     532int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
     533{
     534        fat_node_t *parentp = FAT_NODE(pfn);
     535        fat_node_t *childp = FAT_NODE(cfn);
     536        fat_dentry_t *d;
     537        fat_bs_t *bs;
     538        block_t *b;
     539        unsigned i, j;
     540        uint16_t bps;
     541        unsigned dps;
     542        unsigned blocks;
     543        fat_cluster_t mcl, lcl;
     544        int rc;
     545
     546        fibril_mutex_lock(&childp->lock);
     547        if (childp->lnkcnt == 1) {
     548                /*
     549                 * On FAT, we don't support multiple hard links.
     550                 */
     551                fibril_mutex_unlock(&childp->lock);
     552                return EMLINK;
     553        }
     554        assert(childp->lnkcnt == 0);
     555        fibril_mutex_unlock(&childp->lock);
     556
     557        if (!fat_dentry_name_verify(name)) {
     558                /*
     559                 * Attempt to create unsupported name.
     560                 */
     561                return ENOTSUP;
     562        }
     563
     564        /*
     565         * Get us an unused parent node's dentry or grow the parent and allocate
     566         * a new one.
     567         */
     568       
     569        fibril_mutex_lock(&parentp->idx->lock);
     570        bs = block_bb_get(parentp->idx->dev_handle);
     571        bps = uint16_t_le2host(bs->bps);
     572        dps = bps / sizeof(fat_dentry_t);
     573
     574        blocks = parentp->size / bps;
     575
     576        for (i = 0; i < blocks; i++) {
     577                rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     578                if (rc != EOK) {
     579                        fibril_mutex_unlock(&parentp->idx->lock);
     580                        return rc;
     581                }
     582                for (j = 0; j < dps; j++) {
     583                        d = ((fat_dentry_t *)b->data) + j;
     584                        switch (fat_classify_dentry(d)) {
     585                        case FAT_DENTRY_SKIP:
     586                        case FAT_DENTRY_VALID:
     587                                /* skipping used and meta entries */
     588                                continue;
     589                        case FAT_DENTRY_FREE:
     590                        case FAT_DENTRY_LAST:
     591                                /* found an empty slot */
     592                                goto hit;
     593                        }
     594                }
     595                rc = block_put(b);
     596                if (rc != EOK) {
     597                        fibril_mutex_unlock(&parentp->idx->lock);
     598                        return rc;
     599                }
     600        }
     601        j = 0;
     602       
     603        /*
     604         * We need to grow the parent in order to create a new unused dentry.
     605         */
     606        if (parentp->firstc == FAT_CLST_ROOT) {
     607                /* Can't grow the root directory. */
     608                fibril_mutex_unlock(&parentp->idx->lock);
     609                return ENOSPC;
     610        }
     611        rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
     612        if (rc != EOK) {
     613                fibril_mutex_unlock(&parentp->idx->lock);
     614                return rc;
     615        }
     616        rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl);
     617        if (rc != EOK) {
     618                (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl);
     619                fibril_mutex_unlock(&parentp->idx->lock);
     620                return rc;
     621        }
     622        rc = fat_append_clusters(bs, parentp, mcl);
     623        if (rc != EOK) {
     624                (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl);
     625                fibril_mutex_unlock(&parentp->idx->lock);
     626                return rc;
     627        }
     628        parentp->size += bps * bs->spc;
     629        parentp->dirty = true;          /* need to sync node */
     630        rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     631        if (rc != EOK) {
     632                fibril_mutex_unlock(&parentp->idx->lock);
     633                return rc;
     634        }
     635        d = (fat_dentry_t *)b->data;
     636
     637hit:
     638        /*
     639         * At this point we only establish the link between the parent and the
     640         * child.  The dentry, except of the name and the extension, will remain
     641         * uninitialized until the corresponding node is synced. Thus the valid
     642         * dentry data is kept in the child node structure.
     643         */
     644        memset(d, 0, sizeof(fat_dentry_t));
     645        fat_dentry_name_set(d, name);
     646        b->dirty = true;                /* need to sync block */
     647        rc = block_put(b);
     648        fibril_mutex_unlock(&parentp->idx->lock);
     649        if (rc != EOK)
     650                return rc;
     651
     652        fibril_mutex_lock(&childp->idx->lock);
     653       
     654        /*
     655         * If possible, create the Sub-directory Identifier Entry and the
     656         * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
     657         * are not mandatory according to Standard ECMA-107 and HelenOS VFS does
     658         * not use them anyway, so this is rather a sign of our good will.
     659         */
     660        rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
     661        if (rc != EOK) {
     662                /*
     663                 * Rather than returning an error, simply skip the creation of
     664                 * these two entries.
     665                 */
     666                goto skip_dots;
     667        }
     668        d = (fat_dentry_t *)b->data;
     669        if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
     670            str_cmp(d->name, FAT_NAME_DOT) == 0) {
     671                memset(d, 0, sizeof(fat_dentry_t));
     672                str_cpy(d->name, 8, FAT_NAME_DOT);
     673                str_cpy(d->ext, 3, FAT_EXT_PAD);
     674                d->attr = FAT_ATTR_SUBDIR;
     675                d->firstc = host2uint16_t_le(childp->firstc);
     676                /* TODO: initialize also the date/time members. */
     677        }
     678        d++;
     679        if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
     680            str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) {
     681                memset(d, 0, sizeof(fat_dentry_t));
     682                str_cpy(d->name, 8, FAT_NAME_DOT_DOT);
     683                str_cpy(d->ext, 3, FAT_EXT_PAD);
     684                d->attr = FAT_ATTR_SUBDIR;
     685                d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
     686                    host2uint16_t_le(FAT_CLST_RES0) :
     687                    host2uint16_t_le(parentp->firstc);
     688                /* TODO: initialize also the date/time members. */
     689        }
     690        b->dirty = true;                /* need to sync block */
     691        /*
     692         * Ignore the return value as we would have fallen through on error
     693         * anyway.
     694         */
     695        (void) block_put(b);
     696skip_dots:
     697
     698        childp->idx->pfc = parentp->firstc;
     699        childp->idx->pdi = i * dps + j;
     700        fibril_mutex_unlock(&childp->idx->lock);
     701
     702        fibril_mutex_lock(&childp->lock);
     703        childp->lnkcnt = 1;
     704        childp->dirty = true;           /* need to sync node */
     705        fibril_mutex_unlock(&childp->lock);
     706
     707        /*
     708         * Hash in the index structure into the position hash.
     709         */
     710        fat_idx_hashin(childp->idx);
     711
     712        return EOK;
     713}
     714
     715int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
     716{
     717        fat_node_t *parentp = FAT_NODE(pfn);
     718        fat_node_t *childp = FAT_NODE(cfn);
     719        fat_bs_t *bs;
     720        fat_dentry_t *d;
     721        uint16_t bps;
     722        block_t *b;
     723        bool has_children;
     724        int rc;
     725
     726        if (!parentp)
     727                return EBUSY;
     728       
     729        rc = fat_has_children(&has_children, cfn);
     730        if (rc != EOK)
     731                return rc;
     732        if (has_children)
     733                return ENOTEMPTY;
     734
     735        fibril_mutex_lock(&parentp->lock);
     736        fibril_mutex_lock(&childp->lock);
     737        assert(childp->lnkcnt == 1);
     738        fibril_mutex_lock(&childp->idx->lock);
     739        bs = block_bb_get(childp->idx->dev_handle);
     740        bps = uint16_t_le2host(bs->bps);
     741
     742        rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc,
     743            (childp->idx->pdi * sizeof(fat_dentry_t)) / bps,
     744            BLOCK_FLAGS_NONE);
     745        if (rc != EOK)
     746                goto error;
     747        d = (fat_dentry_t *)b->data +
     748            (childp->idx->pdi % (bps / sizeof(fat_dentry_t)));
     749        /* mark the dentry as not-currently-used */
     750        d->name[0] = FAT_DENTRY_ERASED;
     751        b->dirty = true;                /* need to sync block */
     752        rc = block_put(b);
     753        if (rc != EOK)
     754                goto error;
     755
     756        /* remove the index structure from the position hash */
     757        fat_idx_hashout(childp->idx);
     758        /* clear position information */
     759        childp->idx->pfc = FAT_CLST_RES0;
     760        childp->idx->pdi = 0;
     761        fibril_mutex_unlock(&childp->idx->lock);
     762        childp->lnkcnt = 0;
     763        childp->dirty = true;
     764        fibril_mutex_unlock(&childp->lock);
     765        fibril_mutex_unlock(&parentp->lock);
     766
     767        return EOK;
     768
     769error:
     770        fibril_mutex_unlock(&parentp->idx->lock);
     771        fibril_mutex_unlock(&childp->lock);
     772        fibril_mutex_unlock(&childp->idx->lock);
     773        return rc;
     774}
     775
     776int fat_has_children(bool *has_children, fs_node_t *fn)
    663777{
    664778        fat_bs_t *bs;
     
    669783        block_t *b;
    670784        unsigned i, j;
    671 
    672         if (nodep->type != FAT_DIRECTORY)
    673                 return false;
     785        int rc;
     786
     787        if (nodep->type != FAT_DIRECTORY) {
     788                *has_children = false;
     789                return EOK;
     790        }
    674791       
    675792        fibril_mutex_lock(&nodep->idx->lock);
     
    683800                fat_dentry_t *d;
    684801       
    685                 b = fat_block_get(bs, nodep, i, BLOCK_FLAGS_NONE);
     802                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
     803                if (rc != EOK) {
     804                        fibril_mutex_unlock(&nodep->idx->lock);
     805                        return rc;
     806                }
    686807                for (j = 0; j < dps; j++) {
    687808                        d = ((fat_dentry_t *)b->data) + j;
     
    691812                                continue;
    692813                        case FAT_DENTRY_LAST:
    693                                 block_put(b);
     814                                rc = block_put(b);
    694815                                fibril_mutex_unlock(&nodep->idx->lock);
    695                                 return false;
     816                                *has_children = false;
     817                                return rc;
    696818                        default:
    697819                        case FAT_DENTRY_VALID:
    698                                 block_put(b);
     820                                rc = block_put(b);
    699821                                fibril_mutex_unlock(&nodep->idx->lock);
    700                                 return true;
     822                                *has_children = true;
     823                                return rc;
    701824                        }
    702                         block_put(b);
     825                }
     826                rc = block_put(b);
     827                if (rc != EOK) {
    703828                        fibril_mutex_unlock(&nodep->idx->lock);
    704                         return true;
    705                 }
    706                 block_put(b);
     829                        return rc;     
     830                }
    707831        }
    708832
    709833        fibril_mutex_unlock(&nodep->idx->lock);
    710         return false;
    711 }
    712 
    713 fs_node_t *fat_root_get(dev_handle_t dev_handle)
    714 {
    715         return fat_node_get(dev_handle, 0);
     834        *has_children = false;
     835        return EOK;
     836}
     837
     838
     839fs_index_t fat_index_get(fs_node_t *fn)
     840{
     841        return FAT_NODE(fn)->idx->index;
     842}
     843
     844size_t fat_size_get(fs_node_t *fn)
     845{
     846        return FAT_NODE(fn)->size;
     847}
     848
     849unsigned fat_lnkcnt_get(fs_node_t *fn)
     850{
     851        return FAT_NODE(fn)->lnkcnt;
    716852}
    717853
     
    733869/** libfs operations */
    734870libfs_ops_t fat_libfs_ops = {
     871        .root_get = fat_root_get,
    735872        .match = fat_match,
    736873        .node_get = fat_node_get,
     
    740877        .link = fat_link,
    741878        .unlink = fat_unlink,
     879        .has_children = fat_has_children,
    742880        .index_get = fat_index_get,
    743881        .size_get = fat_size_get,
    744882        .lnkcnt_get = fat_lnkcnt_get,
    745         .has_children = fat_has_children,
    746         .root_get = fat_root_get,
    747883        .plb_get_char = fat_plb_get_char,
    748884        .is_directory = fat_is_directory,
     
    766902        ipc_callid_t callid;
    767903        size_t size;
    768         if (!ipc_data_write_receive(&callid, &size)) {
     904        if (!async_data_write_receive(&callid, &size)) {
    769905                ipc_answer_0(callid, EINVAL);
    770906                ipc_answer_0(rid, EINVAL);
     
    777913                return;
    778914        }
    779         ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);
     915        ipcarg_t retval = async_data_write_finalize(callid, opts, size);
    780916        if (retval != EOK) {
    781917                ipc_answer_0(rid, retval);
     
    799935
    800936        /* prepare the boot block */
    801         rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE);
     937        rc = block_bb_read(dev_handle, BS_BLOCK);
    802938        if (rc != EOK) {
    803939                block_fini(dev_handle);
     
    8951031        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    8961032        off_t pos = (off_t)IPC_GET_ARG3(*request);
    897         fs_node_t *fn = fat_node_get(dev_handle, index);
     1033        fs_node_t *fn;
    8981034        fat_node_t *nodep;
    8991035        fat_bs_t *bs;
     
    9011037        size_t bytes;
    9021038        block_t *b;
    903 
     1039        int rc;
     1040
     1041        rc = fat_node_get(&fn, dev_handle, index);
     1042        if (rc != EOK) {
     1043                ipc_answer_0(rid, rc);
     1044                return;
     1045        }
    9041046        if (!fn) {
    9051047                ipc_answer_0(rid, ENOENT);
     
    9101052        ipc_callid_t callid;
    9111053        size_t len;
    912         if (!ipc_data_read_receive(&callid, &len)) {
     1054        if (!async_data_read_receive(&callid, &len)) {
    9131055                fat_node_put(fn);
    9141056                ipc_answer_0(callid, EINVAL);
     
    9291071                        /* reading beyond the EOF */
    9301072                        bytes = 0;
    931                         (void) ipc_data_read_finalize(callid, NULL, 0);
     1073                        (void) async_data_read_finalize(callid, NULL, 0);
    9321074                } else {
    9331075                        bytes = min(len, bps - pos % bps);
    9341076                        bytes = min(bytes, nodep->size - pos);
    935                         b = fat_block_get(bs, nodep, pos / bps,
     1077                        rc = fat_block_get(&b, bs, nodep, pos / bps,
    9361078                            BLOCK_FLAGS_NONE);
    937                         (void) ipc_data_read_finalize(callid, b->data + pos % bps,
     1079                        if (rc != EOK) {
     1080                                fat_node_put(fn);
     1081                                ipc_answer_0(callid, rc);
     1082                                ipc_answer_0(rid, rc);
     1083                                return;
     1084                        }
     1085                        (void) async_data_read_finalize(callid, b->data + pos % bps,
    9381086                            bytes);
    939                         block_put(b);
     1087                        rc = block_put(b);
     1088                        if (rc != EOK) {
     1089                                fat_node_put(fn);
     1090                                ipc_answer_0(rid, rc);
     1091                                return;
     1092                        }
    9401093                }
    9411094        } else {
     
    9591112                        off_t o;
    9601113
    961                         b = fat_block_get(bs, nodep, bnum, BLOCK_FLAGS_NONE);
     1114                        rc = fat_block_get(&b, bs, nodep, bnum,
     1115                            BLOCK_FLAGS_NONE);
     1116                        if (rc != EOK)
     1117                                goto err;
    9621118                        for (o = pos % (bps / sizeof(fat_dentry_t));
    9631119                            o < bps / sizeof(fat_dentry_t);
     
    9691125                                        continue;
    9701126                                case FAT_DENTRY_LAST:
    971                                         block_put(b);
     1127                                        rc = block_put(b);
     1128                                        if (rc != EOK)
     1129                                                goto err;
    9721130                                        goto miss;
    9731131                                default:
    9741132                                case FAT_DENTRY_VALID:
    9751133                                        fat_dentry_name_get(d, name);
    976                                         block_put(b);
     1134                                        rc = block_put(b);
     1135                                        if (rc != EOK)
     1136                                                goto err;
    9771137                                        goto hit;
    9781138                                }
    9791139                        }
    980                         block_put(b);
     1140                        rc = block_put(b);
     1141                        if (rc != EOK)
     1142                                goto err;
    9811143                        bnum++;
    9821144                }
    9831145miss:
    984                 fat_node_put(fn);
    985                 ipc_answer_0(callid, ENOENT);
    986                 ipc_answer_1(rid, ENOENT, 0);
    987                 return;
     1146                rc = fat_node_put(fn);
     1147                ipc_answer_0(callid, rc != EOK ? rc : ENOENT);
     1148                ipc_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
     1149                return;
     1150
     1151err:
     1152                (void) fat_node_put(fn);
     1153                ipc_answer_0(callid, rc);
     1154                ipc_answer_0(rid, rc);
     1155                return;
     1156
    9881157hit:
    989                 (void) ipc_data_read_finalize(callid, name, str_size(name) + 1);
     1158                (void) async_data_read_finalize(callid, name, str_size(name) + 1);
    9901159                bytes = (pos - spos) + 1;
    9911160        }
    9921161
    993         fat_node_put(fn);
    994         ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
     1162        rc = fat_node_put(fn);
     1163        ipc_answer_1(rid, rc, (ipcarg_t)bytes);
    9951164}
    9961165
     
    10001169        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    10011170        off_t pos = (off_t)IPC_GET_ARG3(*request);
    1002         fs_node_t *fn = fat_node_get(dev_handle, index);
     1171        fs_node_t *fn;
    10031172        fat_node_t *nodep;
    10041173        fat_bs_t *bs;
    1005         size_t bytes;
     1174        size_t bytes, size;
    10061175        block_t *b;
    10071176        uint16_t bps;
     
    10101179        off_t boundary;
    10111180        int flags = BLOCK_FLAGS_NONE;
    1012        
     1181        int rc;
     1182       
     1183        rc = fat_node_get(&fn, dev_handle, index);
     1184        if (rc != EOK) {
     1185                ipc_answer_0(rid, rc);
     1186                return;
     1187        }
    10131188        if (!fn) {
    10141189                ipc_answer_0(rid, ENOENT);
     
    10191194        ipc_callid_t callid;
    10201195        size_t len;
    1021         if (!ipc_data_write_receive(&callid, &len)) {
    1022                 fat_node_put(fn);
     1196        if (!async_data_write_receive(&callid, &len)) {
     1197                (void) fat_node_put(fn);
    10231198                ipc_answer_0(callid, EINVAL);
    10241199                ipc_answer_0(rid, EINVAL);
     
    10501225                 * next block size boundary.
    10511226                 */
    1052                 fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos);
    1053                 b = fat_block_get(bs, nodep, pos / bps, flags);
    1054                 (void) ipc_data_write_finalize(callid, b->data + pos % bps,
     1227                rc = fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos);
     1228                if (rc != EOK) {
     1229                        (void) fat_node_put(fn);
     1230                        ipc_answer_0(callid, rc);
     1231                        ipc_answer_0(rid, rc);
     1232                        return;
     1233                }
     1234                rc = fat_block_get(&b, bs, nodep, pos / bps, flags);
     1235                if (rc != EOK) {
     1236                        (void) fat_node_put(fn);
     1237                        ipc_answer_0(callid, rc);
     1238                        ipc_answer_0(rid, rc);
     1239                        return;
     1240                }
     1241                (void) async_data_write_finalize(callid, b->data + pos % bps,
    10551242                    bytes);
    10561243                b->dirty = true;                /* need to sync block */
    1057                 block_put(b);
     1244                rc = block_put(b);
     1245                if (rc != EOK) {
     1246                        (void) fat_node_put(fn);
     1247                        ipc_answer_0(rid, rc);
     1248                        return;
     1249                }
    10581250                if (pos + bytes > nodep->size) {
    10591251                        nodep->size = pos + bytes;
    10601252                        nodep->dirty = true;    /* need to sync node */
    10611253                }
    1062                 ipc_answer_2(rid, EOK, bytes, nodep->size);     
    1063                 fat_node_put(fn);
     1254                size = nodep->size;
     1255                rc = fat_node_put(fn);
     1256                ipc_answer_2(rid, rc, bytes, nodep->size);
    10641257                return;
    10651258        } else {
     
    10681261                 * clusters for the node and zero them out.
    10691262                 */
    1070                 int status;
    10711263                unsigned nclsts;
    10721264                fat_cluster_t mcl, lcl;
     
    10741266                nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc;
    10751267                /* create an independent chain of nclsts clusters in all FATs */
    1076                 status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);
    1077                 if (status != EOK) {
     1268                rc = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);
     1269                if (rc != EOK) {
    10781270                        /* could not allocate a chain of nclsts clusters */
    1079                         fat_node_put(fn);
    1080                         ipc_answer_0(callid, status);
    1081                         ipc_answer_0(rid, status);
     1271                        (void) fat_node_put(fn);
     1272                        ipc_answer_0(callid, rc);
     1273                        ipc_answer_0(rid, rc);
    10821274                        return;
    10831275                }
    10841276                /* zero fill any gaps */
    1085                 fat_fill_gap(bs, nodep, mcl, pos);
    1086                 b = _fat_block_get(bs, dev_handle, lcl, (pos / bps) % spc,
     1277                rc = fat_fill_gap(bs, nodep, mcl, pos);
     1278                if (rc != EOK) {
     1279                        (void) fat_free_clusters(bs, dev_handle, mcl);
     1280                        (void) fat_node_put(fn);
     1281                        ipc_answer_0(callid, rc);
     1282                        ipc_answer_0(rid, rc);
     1283                        return;
     1284                }
     1285                rc = _fat_block_get(&b, bs, dev_handle, lcl, (pos / bps) % spc,
    10871286                    flags);
    1088                 (void) ipc_data_write_finalize(callid, b->data + pos % bps,
     1287                if (rc != EOK) {
     1288                        (void) fat_free_clusters(bs, dev_handle, mcl);
     1289                        (void) fat_node_put(fn);
     1290                        ipc_answer_0(callid, rc);
     1291                        ipc_answer_0(rid, rc);
     1292                        return;
     1293                }
     1294                (void) async_data_write_finalize(callid, b->data + pos % bps,
    10891295                    bytes);
    10901296                b->dirty = true;                /* need to sync block */
    1091                 block_put(b);
     1297                rc = block_put(b);
     1298                if (rc != EOK) {
     1299                        (void) fat_free_clusters(bs, dev_handle, mcl);
     1300                        (void) fat_node_put(fn);
     1301                        ipc_answer_0(rid, rc);
     1302                        return;
     1303                }
    10921304                /*
    10931305                 * Append the cluster chain starting in mcl to the end of the
    10941306                 * node's cluster chain.
    10951307                 */
    1096                 fat_append_clusters(bs, nodep, mcl);
    1097                 nodep->size = pos + bytes;
     1308                rc = fat_append_clusters(bs, nodep, mcl);
     1309                if (rc != EOK) {
     1310                        (void) fat_free_clusters(bs, dev_handle, mcl);
     1311                        (void) fat_node_put(fn);
     1312                        ipc_answer_0(rid, rc);
     1313                        return;
     1314                }
     1315                nodep->size = size = pos + bytes;
    10981316                nodep->dirty = true;            /* need to sync node */
    1099                 ipc_answer_2(rid, EOK, bytes, nodep->size);
    1100                 fat_node_put(fn);
     1317                rc = fat_node_put(fn);
     1318                ipc_answer_2(rid, rc, bytes, size);
    11011319                return;
    11021320        }
     
    11081326        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    11091327        size_t size = (off_t)IPC_GET_ARG3(*request);
    1110         fs_node_t *fn = fat_node_get(dev_handle, index);
     1328        fs_node_t *fn;
    11111329        fat_node_t *nodep;
    11121330        fat_bs_t *bs;
     
    11161334        int rc;
    11171335
     1336        rc = fat_node_get(&fn, dev_handle, index);
     1337        if (rc != EOK) {
     1338                ipc_answer_0(rid, rc);
     1339                return;
     1340        }
    11181341        if (!fn) {
    11191342                ipc_answer_0(rid, ENOENT);
     
    11471370                 */
    11481371                if (size == 0) {
    1149                         fat_chop_clusters(bs, nodep, FAT_CLST_RES0);
     1372                        rc = fat_chop_clusters(bs, nodep, FAT_CLST_RES0);
     1373                        if (rc != EOK)
     1374                                goto out;
    11501375                } else {
    11511376                        fat_cluster_t lastc;
    1152                         (void) fat_cluster_walk(bs, dev_handle, nodep->firstc,
    1153                             &lastc, (size - 1) / bpc);
    1154                         fat_chop_clusters(bs, nodep, lastc);
     1377                        rc = fat_cluster_walk(bs, dev_handle, nodep->firstc,
     1378                            &lastc, NULL, (size - 1) / bpc);
     1379                        if (rc != EOK)
     1380                                goto out;
     1381                        rc = fat_chop_clusters(bs, nodep, lastc);
     1382                        if (rc != EOK)
     1383                                goto out;
    11551384                }
    11561385                nodep->size = size;
     
    11581387                rc = EOK;       
    11591388        }
     1389out:
    11601390        fat_node_put(fn);
    11611391        ipc_answer_0(rid, rc);
     
    11721402        dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    11731403        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
     1404        fs_node_t *fn;
    11741405        int rc;
    11751406
    1176         fs_node_t *fn = fat_node_get(dev_handle, index);
     1407        rc = fat_node_get(&fn, dev_handle, index);
     1408        if (rc != EOK) {
     1409                ipc_answer_0(rid, rc);
     1410                return;
     1411        }
    11771412        if (!fn) {
    11781413                ipc_answer_0(rid, ENOENT);
  • uspace/srv/fs/tmpfs/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../../../lib/libc
    33 LIBFS_PREFIX = ../../../lib/libfs
    34 LIBBLOCK_PREFIX = ../../../lib/libblock
    35 SOFTINT_PREFIX = ../../../lib/softint
     32.PHONY: all clean
    3633
    37 include $(LIBC_PREFIX)/Makefile.toolchain
    38 
    39 CFLAGS += -I $(LIBFS_PREFIX) -I $(LIBBLOCK_PREFIX)
    40 
    41 LIBS = \
    42         $(LIBFS_PREFIX)/libfs.a \
    43         $(LIBBLOCK_PREFIX)/libblock.a \
    44         $(LIBC_PREFIX)/libc.a
    45 
    46 ## Sources
    47 #
    48 
    49 OUTPUT = tmpfs
    50 SOURCES = \
    51         tmpfs.c \
    52         tmpfs_ops.c \
    53         tmpfs_dump.c
    54 
    55 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    56 
    57 .PHONY: all clean depend disasm
    58 
    59 all: $(OUTPUT) $(OUTPUT).disasm
    60 
    61 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    6237
    6338clean:
    64         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    65 
    66 depend:
    67         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    68 
    69 $(OUTPUT): $(OBJECTS) $(LIBS)
    70         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    71 
    72 disasm: $(OUTPUT).disasm
    73 
    74 $(OUTPUT).disasm: $(OUTPUT)
    75         $(OBJDUMP) -d $< > $@
    76 
    77 %.o: %.S
    78         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    79 
    80 %.o: %.s
    81         $(AS) $(AFLAGS) $< -o $@
    82 
    83 %.o: %.c
    84         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/fs/tmpfs/tmpfs.c

    rfcbd1be r1787e527  
    4848#include <unistd.h>
    4949#include <stdio.h>
     50#include <task.h>
    5051#include <libfs.h>
    5152#include "../../vfs/vfs.h"
     
    5556
    5657vfs_info_t tmpfs_vfs_info = {
    57         .name = "tmpfs",
     58        .name = NAME,
    5859};
    5960
     
    9091        }
    9192       
    92         dprintf("VFS-TMPFS connection established.\n");
     93        dprintf(NAME ": connection opened\n");
    9394        while (1) {
    9495                ipc_callid_t callid;
     
    162163
    163164        printf(NAME ": Accepting connections\n");
     165        task_retval(0);
    164166        async_manager();
    165167        /* not reached */
  • uspace/srv/fs/tmpfs/tmpfs_dump.c

    rfcbd1be r1787e527  
    4747#include <byteorder.h>
    4848
    49 #define TMPFS_BLOCK_SIZE        1024
     49#define TMPFS_COMM_SIZE         1024
    5050
    5151struct rdentry {
     
    6969               
    7070                if (block_seqread(dev, bufpos, buflen, pos, &entry,
    71                     sizeof(entry), TMPFS_BLOCK_SIZE) != EOK)
     71                    sizeof(entry)) != EOK)
    7272                        return false;
    7373               
     
    8282                                return false;
    8383                       
    84                         fn = ops->create(dev, L_FILE);
    85                         if (fn == NULL) {
     84                        rc = ops->create(&fn, dev, L_FILE);
     85                        if (rc != EOK || fn == NULL) {
    8686                                free(fname);
    8787                                return false;
     
    8989                       
    9090                        if (block_seqread(dev, bufpos, buflen, pos, fname,
    91                             entry.len, TMPFS_BLOCK_SIZE) != EOK) {
    92                                 ops->destroy(fn);
     91                            entry.len) != EOK) {
     92                                (void) ops->destroy(fn);
    9393                                free(fname);
    9494                                return false;
     
    9898                        rc = ops->link(pfn, fn, fname);
    9999                        if (rc != EOK) {
    100                                 ops->destroy(fn);
     100                                (void) ops->destroy(fn);
    101101                                free(fname);
    102102                                return false;
     
    105105                       
    106106                        if (block_seqread(dev, bufpos, buflen, pos, &size,
    107                             sizeof(size), TMPFS_BLOCK_SIZE) != EOK)
     107                            sizeof(size)) != EOK)
    108108                                return false;
    109109                       
     
    117117                        nodep->size = size;
    118118                        if (block_seqread(dev, bufpos, buflen, pos, nodep->data,
    119                             size, TMPFS_BLOCK_SIZE) != EOK)
     119                            size) != EOK)
    120120                                return false;
    121121                       
     
    126126                                return false;
    127127                       
    128                         fn = ops->create(dev, L_DIRECTORY);
    129                         if (fn == NULL) {
     128                        rc = ops->create(&fn, dev, L_DIRECTORY);
     129                        if (rc != EOK || fn == NULL) {
    130130                                free(fname);
    131131                                return false;
     
    133133                       
    134134                        if (block_seqread(dev, bufpos, buflen, pos, fname,
    135                             entry.len, TMPFS_BLOCK_SIZE) != EOK) {
    136                                 ops->destroy(fn);
     135                            entry.len) != EOK) {
     136                                (void) ops->destroy(fn);
    137137                                free(fname);
    138138                                return false;
     
    142142                        rc = ops->link(pfn, fn, fname);
    143143                        if (rc != EOK) {
    144                                 ops->destroy(fn);
     144                                (void) ops->destroy(fn);
    145145                                free(fname);
    146146                                return false;
     
    164164{
    165165        libfs_ops_t *ops = &tmpfs_libfs_ops;
     166        fs_node_t *fn;
    166167        int rc;
    167168
    168         rc = block_init(dev, TMPFS_BLOCK_SIZE);
     169        rc = block_init(dev, TMPFS_COMM_SIZE);
    169170        if (rc != EOK)
    170171                return false;
     
    175176       
    176177        char tag[6];
    177         if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5,
    178             TMPFS_BLOCK_SIZE) != EOK)
     178        if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5) != EOK)
    179179                goto error;
    180180       
     
    183183                goto error;
    184184       
    185         if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos,
    186             ops->root_get(dev)))
     185        rc = ops->root_get(&fn, dev);
     186        if (rc != EOK)
     187                goto error;
     188
     189        if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, fn))
    187190                goto error;
    188191               
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    rfcbd1be r1787e527  
    6767
    6868/* Forward declarations of static functions. */
    69 static fs_node_t *tmpfs_match(fs_node_t *, const char *);
    70 static fs_node_t *tmpfs_node_get(dev_handle_t, fs_index_t);
    71 static void tmpfs_node_put(fs_node_t *);
    72 static fs_node_t *tmpfs_create_node(dev_handle_t, int);
     69static int tmpfs_match(fs_node_t **, fs_node_t *, const char *);
     70static int tmpfs_node_get(fs_node_t **, dev_handle_t, fs_index_t);
     71static int tmpfs_node_put(fs_node_t *);
     72static int tmpfs_create_node(fs_node_t **, dev_handle_t, int);
     73static int tmpfs_destroy_node(fs_node_t *);
    7374static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *);
    7475static int tmpfs_unlink_node(fs_node_t *, fs_node_t *, const char *);
    75 static int tmpfs_destroy_node(fs_node_t *);
    7676
    7777/* Implementation of helper functions. */
     78static int tmpfs_root_get(fs_node_t **rfn, dev_handle_t dev_handle)
     79{
     80        return tmpfs_node_get(rfn, dev_handle, TMPFS_SOME_ROOT);
     81}
     82
     83static int tmpfs_has_children(bool *has_children, fs_node_t *fn)
     84{
     85        *has_children = !list_empty(&TMPFS_NODE(fn)->cs_head);
     86        return EOK;
     87}
     88
    7889static fs_index_t tmpfs_index_get(fs_node_t *fn)
    7990{
     
    89100{
    90101        return TMPFS_NODE(fn)->lnkcnt;
    91 }
    92 
    93 static bool tmpfs_has_children(fs_node_t *fn)
    94 {
    95         return !list_empty(&TMPFS_NODE(fn)->cs_head);
    96 }
    97 
    98 static fs_node_t *tmpfs_root_get(dev_handle_t dev_handle)
    99 {
    100         return tmpfs_node_get(dev_handle, TMPFS_SOME_ROOT);
    101102}
    102103
     
    118119/** libfs operations */
    119120libfs_ops_t tmpfs_libfs_ops = {
     121        .root_get = tmpfs_root_get,
    120122        .match = tmpfs_match,
    121123        .node_get = tmpfs_node_get,
     
    125127        .link = tmpfs_link_node,
    126128        .unlink = tmpfs_unlink_node,
     129        .has_children = tmpfs_has_children,
    127130        .index_get = tmpfs_index_get,
    128131        .size_get = tmpfs_size_get,
    129132        .lnkcnt_get = tmpfs_lnkcnt_get,
    130         .has_children = tmpfs_has_children,
    131         .root_get = tmpfs_root_get,
    132133        .plb_get_char = tmpfs_plb_get_char,
    133134        .is_directory = tmpfs_is_directory,
     
    197198{
    198199        fs_node_t *rfn;
     200        int rc;
    199201       
    200         rfn = tmpfs_create_node(dev_handle, L_DIRECTORY);
    201         if (!rfn)
     202        rc = tmpfs_create_node(&rfn, dev_handle, L_DIRECTORY);
     203        if (rc != EOK || !rfn)
    202204                return false;
    203205        TMPFS_NODE(rfn)->lnkcnt = 0;    /* FS root is not linked */
     
    205207}
    206208
    207 fs_node_t *tmpfs_match(fs_node_t *pfn, const char *component)
     209int tmpfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    208210{
    209211        tmpfs_node_t *parentp = TMPFS_NODE(pfn);
     
    212214        for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
    213215            lnk = lnk->next) {
    214                 tmpfs_dentry_t *dentryp = list_get_instance(lnk, tmpfs_dentry_t,
    215                     link);
    216                 if (!str_cmp(dentryp->name, component))
    217                         return FS_NODE(dentryp->node);
    218         }
    219 
    220         return NULL;
    221 }
    222 
    223 fs_node_t *tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index)
     216                tmpfs_dentry_t *dentryp;
     217                dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
     218                if (!str_cmp(dentryp->name, component)) {
     219                        *rfn = FS_NODE(dentryp->node);
     220                        return EOK;
     221                }
     222        }
     223
     224        *rfn = NULL;
     225        return EOK;
     226}
     227
     228int tmpfs_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index)
    224229{
    225230        unsigned long key[] = {
     
    228233        };
    229234        link_t *lnk = hash_table_find(&nodes, key);
    230         if (!lnk)
    231                 return NULL;
    232         return FS_NODE(hash_table_get_instance(lnk, tmpfs_node_t, nh_link));
    233 }
    234 
    235 void tmpfs_node_put(fs_node_t *fn)
     235        if (lnk) {
     236                tmpfs_node_t *nodep;
     237                nodep = hash_table_get_instance(lnk, tmpfs_node_t, nh_link);
     238                *rfn = FS_NODE(nodep);
     239        } else {
     240                *rfn = NULL;
     241        }
     242        return EOK;     
     243}
     244
     245int tmpfs_node_put(fs_node_t *fn)
    236246{
    237247        /* nothing to do */
    238 }
    239 
    240 fs_node_t *tmpfs_create_node(dev_handle_t dev_handle, int lflag)
    241 {
     248        return EOK;
     249}
     250
     251int tmpfs_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int lflag)
     252{
     253        fs_node_t *rootfn;
     254        int rc;
     255
    242256        assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
    243257
    244258        tmpfs_node_t *nodep = malloc(sizeof(tmpfs_node_t));
    245259        if (!nodep)
    246                 return NULL;
     260                return ENOMEM;
    247261        tmpfs_node_initialize(nodep);
    248262        nodep->bp = malloc(sizeof(fs_node_t));
    249263        if (!nodep->bp) {
    250264                free(nodep);
    251                 return NULL;
     265                return ENOMEM;
    252266        }
    253267        fs_node_initialize(nodep->bp);
    254268        nodep->bp->data = nodep;        /* link the FS and TMPFS nodes */
    255         if (!tmpfs_root_get(dev_handle))
     269
     270        rc = tmpfs_root_get(&rootfn, dev_handle);
     271        assert(rc == EOK);
     272        if (!rootfn)
    256273                nodep->index = TMPFS_SOME_ROOT;
    257274        else
     
    269286        };
    270287        hash_table_insert(&nodes, key, &nodep->nh_link);
    271         return FS_NODE(nodep);
     288        *rfn = FS_NODE(nodep);
     289        return EOK;
     290}
     291
     292int tmpfs_destroy_node(fs_node_t *fn)
     293{
     294        tmpfs_node_t *nodep = TMPFS_NODE(fn);
     295       
     296        assert(!nodep->lnkcnt);
     297        assert(list_empty(&nodep->cs_head));
     298
     299        unsigned long key[] = {
     300                [NODES_KEY_INDEX] = nodep->index,
     301                [NODES_KEY_DEV] = nodep->dev_handle
     302        };
     303        hash_table_remove(&nodes, key, 2);
     304
     305        if (nodep->type == TMPFS_FILE)
     306                free(nodep->data);
     307        free(nodep->bp);
     308        free(nodep);
     309        return EOK;
    272310}
    273311
     
    343381}
    344382
    345 int tmpfs_destroy_node(fs_node_t *fn)
    346 {
    347         tmpfs_node_t *nodep = TMPFS_NODE(fn);
    348        
    349         assert(!nodep->lnkcnt);
    350         assert(list_empty(&nodep->cs_head));
    351 
    352         unsigned long key[] = {
    353                 [NODES_KEY_INDEX] = nodep->index,
    354                 [NODES_KEY_DEV] = nodep->dev_handle
    355         };
    356         hash_table_remove(&nodes, key, 2);
    357 
    358         if (nodep->type == TMPFS_FILE)
    359                 free(nodep->data);
    360         free(nodep->bp);
    361         free(nodep);
    362         return EOK;
    363 }
    364 
    365383void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
    366384{
    367385        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     386        int rc;
    368387
    369388        /* accept the mount options */
    370389        ipc_callid_t callid;
    371390        size_t size;
    372         if (!ipc_data_write_receive(&callid, &size)) {
     391        if (!async_data_write_receive(&callid, &size)) {
    373392                ipc_answer_0(callid, EINVAL);
    374393                ipc_answer_0(rid, EINVAL);
     
    381400                return;
    382401        }
    383         ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);
     402        ipcarg_t retval = async_data_write_finalize(callid, opts, size);
    384403        if (retval != EOK) {
    385404                ipc_answer_0(rid, retval);
     
    395414        }
    396415
    397         tmpfs_node_t *rootp = TMPFS_NODE(tmpfs_root_get(dev_handle));
     416        fs_node_t *rootfn;
     417        rc = tmpfs_root_get(&rootfn, dev_handle);
     418        assert(rc == EOK);
     419        tmpfs_node_t *rootp = TMPFS_NODE(rootfn);
    398420        if (str_cmp(opts, "restore") == 0) {
    399421                if (tmpfs_restore(dev_handle))
     
    445467        ipc_callid_t callid;
    446468        size_t size;
    447         if (!ipc_data_read_receive(&callid, &size)) {
     469        if (!async_data_read_receive(&callid, &size)) {
    448470                ipc_answer_0(callid, EINVAL);   
    449471                ipc_answer_0(rid, EINVAL);
     
    454476        if (nodep->type == TMPFS_FILE) {
    455477                bytes = max(0, min(nodep->size - pos, size));
    456                 (void) ipc_data_read_finalize(callid, nodep->data + pos,
     478                (void) async_data_read_finalize(callid, nodep->data + pos,
    457479                    bytes);
    458480        } else {
     
    481503                dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
    482504
    483                 (void) ipc_data_read_finalize(callid, dentryp->name,
     505                (void) async_data_read_finalize(callid, dentryp->name,
    484506                    str_size(dentryp->name) + 1);
    485507                bytes = 1;
     
    519541        ipc_callid_t callid;
    520542        size_t size;
    521         if (!ipc_data_write_receive(&callid, &size)) {
     543        if (!async_data_write_receive(&callid, &size)) {
    522544                ipc_answer_0(callid, EINVAL);   
    523545                ipc_answer_0(rid, EINVAL);
     
    530552        if (pos + size <= nodep->size) {
    531553                /* The file size is not changing. */
    532                 (void) ipc_data_write_finalize(callid, nodep->data + pos, size);
     554                (void) async_data_write_finalize(callid, nodep->data + pos, size);
    533555                ipc_answer_2(rid, EOK, size, nodep->size);
    534556                return;
     
    552574        nodep->size += delta;
    553575        nodep->data = newdata;
    554         (void) ipc_data_write_finalize(callid, nodep->data + pos, size);
     576        (void) async_data_write_finalize(callid, nodep->data + pos, size);
    555577        ipc_answer_2(rid, EOK, size, nodep->size);
    556578}
  • uspace/srv/kbd/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../../lib/libc
    33 SOFTINT_PREFIX = ../../lib/softint
     32.PHONY: all clean
    3433
    35 include $(LIBC_PREFIX)/Makefile.toolchain
    36 
    37 CFLAGS += -Iinclude
    38 
    39 LIBS = $(LIBC_PREFIX)/libc.a
    40 
    41 ## Sources
    42 #
    43 
    44 OUTPUT = kbd
    45 GENERIC_SOURCES = \
    46         generic/kbd.c \
    47         genarch/gsp.c \
    48         genarch/stroke.c
    49 
    50 ARCH_SOURCES =
    51 GENARCH_SOURCES = \
    52         layout/cz.c \
    53         layout/us_qwerty.c \
    54         layout/us_dvorak.c
    55 
    56 ifeq ($(UARCH), amd64)
    57         GENARCH_SOURCES += \
    58                 port/i8042.c \
    59                 ctl/pc.c
    60 endif
    61 
    62 ifeq ($(UARCH), arm32)
    63 ifeq ($(MACHINE), testarm)
    64         GENARCH_SOURCES += \
    65                 port/gxemul.c
    66        
    67         ifeq ($(CONFIG_FB), y)
    68                 GENARCH_SOURCES += \
    69                         ctl/gxe_fb.c
    70         else
    71                 GENARCH_SOURCES += \
    72                         ctl/stty.c
    73         endif
    74 endif
    75 ifeq ($(MACHINE), integratorcp)
    76          GENARCH_SOURCES += \
    77                 port/pl050.c \
    78                 ctl/pl050.c
    79 endif
    80 endif
    81 
    82 ifeq ($(UARCH), ia32)
    83         GENARCH_SOURCES += \
    84                 port/i8042.c \
    85                 ctl/pc.c
    86 endif
    87 
    88 ifeq ($(MACHINE), i460GX)
    89         GENARCH_SOURCES += \
    90                 port/i8042.c \
    91                 ctl/pc.c
    92 endif
    93 
    94 ifeq ($(MACHINE), ski)
    95         GENARCH_SOURCES += \
    96                 port/ski.c \
    97                 ctl/stty.c
    98 endif
    99 
    100 ifeq ($(MACHINE), msim)
    101         GENARCH_SOURCES += \
    102                 port/msim.c \
    103                 ctl/stty.c
    104 endif
    105 
    106 ifeq ($(MACHINE), lgxemul)
    107         GENARCH_SOURCES += \
    108                 port/gxemul.c
    109        
    110         ifeq ($(CONFIG_FB), y)
    111                 GENARCH_SOURCES += \
    112                         ctl/gxe_fb.c
    113         else
    114                 GENARCH_SOURCES += \
    115                         ctl/stty.c
    116         endif
    117 endif
    118 
    119 ifeq ($(MACHINE), bgxemul)
    120         GENARCH_SOURCES += \
    121                 port/gxemul.c
    122        
    123         ifeq ($(CONFIG_FB), y)
    124                 GENARCH_SOURCES += \
    125                         ctl/gxe_fb.c
    126         else
    127                 GENARCH_SOURCES += \
    128                         ctl/stty.c
    129         endif
    130 endif
    131 
    132 ifeq ($(UARCH), ppc32)
    133         GENARCH_SOURCES += \
    134                 port/dummy.c \
    135                 ctl/stty.c
    136 endif
    137 
    138 ifeq ($(UARCH), sparc64)
    139         ifeq ($(MACHINE),serengeti)
    140                 GENARCH_SOURCES += \
    141                         port/sgcn.c \
    142                         ctl/stty.c
    143         else
    144                 GENARCH_SOURCES += \
    145                         port/sun.c \
    146                         port/z8530.c \
    147                         port/ns16550.c \
    148                         ctl/sun.c
    149         endif
    150 endif
    151 
    152 GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
    153 ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
    154 GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES)))
    155 
    156 OBJECTS := $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(GENARCH_OBJECTS)
    157 
    158 .PHONY: all clean depend disasm links
    159 
    160 all: $(OUTPUT) $(OUTPUT).disasm
    161 
    162 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    16337
    16438clean:
    165         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    166 
    167 depend:
    168         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    169 
    170 $(OUTPUT): $(OBJECTS) $(LIBS)
    171         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    172 
    173 disasm: $(OUTPUT).disasm
    174 
    175 $(OUTPUT).disasm: $(OUTPUT)
    176         $(OBJDUMP) -d $< > $@
    177 
    178 %.o: %.S
    179         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    180 
    181 %.o: %.s
    182         $(AS) $(AFLAGS) $< -o $@
    183 
    184 %.o: %.c
    185         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/loader/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
    3 # Copyright (c) 2008 Jiri Svoboda
     3# Copyright (c) 2007 Jakub Jermar
    44# All rights reserved.
    55#
     
    2828#
    2929
    30 ## Setup toolchain
    31 #
     30include Makefile.common
    3231
    33 LIBC_PREFIX = ../../lib/libc
    34 SOFTINT_PREFIX = ../../lib/softint
     32.PHONY: all clean
    3533
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 include arch/$(UARCH)/Makefile.inc
    38 
    39 CFLAGS += -Iinclude
    40 
    41 LIBS = $(LIBC_PREFIX)/libc.a $(SOFTINT_PREFIX)/libsoftint.a
    42 
    43 ## Sources
    44 #
    45 
    46 OUTPUT = loader
    47 GENERIC_SOURCES = \
    48         main.c \
    49         elf_load.c \
    50         interp.s
    51 
    52 SOURCES := $(GENERIC_SOURCES) $(ARCH_SOURCES)
    53 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    54 
    55 .PHONY: all clean depend disasm
    56 
    57 all: $(OUTPUT) disasm
    58 
    59 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    6037
    6138clean:
    62         -rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm arch/$(UARCH)/_link.ld Makefile.depend
    63 
    64 depend:
    65         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    66 
    67 $(OUTPUT): $(OBJECTS) $(LIBS) arch/$(UARCH)/_link.ld
    68         $(LD) -T arch/$(UARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map
    69 
    70 disasm:
    71         $(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
    72 
    73 arch/$(UARCH)/_link.ld: arch/$(UARCH)/_link.ld.in
    74         $(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@
    75 
    76 %.o: %.S
    77         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    78 
    79 %.o: %.s
    80         $(AS) $(AFLAGS) $< -o $@
    81 
    82 %.o: %.c
    83         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm arch/*/_link.ld
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/loader/arch/ia32/_link.ld.in

    rfcbd1be r1787e527  
    88PHDRS {
    99        interp PT_INTERP;
    10         text PT_LOAD FILEHDR PHDRS FLAGS(5);
     10        text PT_LOAD FILEHDR PHDRS FLAGS(5);
    1111        data PT_LOAD FLAGS(6);
    1212}
     
    1616                *(.interp);
    1717        } :interp
    18 
     18       
    1919        . = 0x70001000;
    20 
     20       
    2121        .init ALIGN(0x1000) : SUBALIGN(0x1000) {
    2222                *(.init);
    2323        } :text
     24       
    2425        .text : {
    2526                *(.text);
    26                 *(.rodata*);
     27                *(.rodata*);
    2728        } :text
    2829       
     
    3031                *(.data);
    3132        } :data
     33       
    3234        .tdata : {
    3335                _tdata_start = .;
    3436                *(.tdata);
     37                *(.gnu.linkonce.tb.*);
    3538                _tdata_end = .;
    3639        } :data
     40       
    3741        .tbss : {
    3842                _tbss_start = .;
     
    4044                _tbss_end = .;
    4145        } :data
     46       
    4247        _tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
     48       
    4349        .bss : {
    44                 *(COMMON);
    45                 *(.bss);
     50                *(COMMON);
     51                *(.bss);
    4652        } :data
    4753       
    4854        . = ALIGN(0x1000);
     55       
    4956        _heap = .;
    5057       
     
    5259                *(*);
    5360        }
    54 
    5561}
  • uspace/srv/loader/arch/ia32/ia32.s

    rfcbd1be r1787e527  
    4040        movl 0x8(%ebp), %eax
    4141
    42         # %ebx := pcb
    43         # pcb is passed to the entry point int %ebx
    44         mov 0xc(%ebp), %ebx
     42        # %edi := pcb
     43        # pcb is passed to the entry point in %edi
     44        mov 0xc(%ebp), %edi
    4545
    4646        # Save a tiny bit of stack space
  • uspace/srv/loader/main.c

    rfcbd1be r1787e527  
    7272static pcb_t pcb;
    7373
     74/** Current working directory */
     75static char *cwd = NULL;
     76
    7477/** Number of arguments */
    7578static int argc = 0;
     
    102105        task_id = task_get_id();
    103106       
    104         if (!ipc_data_read_receive(&callid, &len)) {
     107        if (!async_data_read_receive(&callid, &len)) {
    105108                ipc_answer_0(callid, EINVAL);
    106109                ipc_answer_0(rid, EINVAL);
     
    111114                len = sizeof(task_id);
    112115       
    113         ipc_data_read_finalize(callid, &task_id, len);
     116        async_data_read_finalize(callid, &task_id, len);
    114117        ipc_answer_0(rid, EOK);
    115118}
    116119
     120/** Receive a call setting the current working directory.
     121 *
     122 * @param rid
     123 * @param request
     124 */
     125static void ldr_set_cwd(ipc_callid_t rid, ipc_call_t *request)
     126{
     127        ipc_callid_t callid;
     128        size_t len;
     129       
     130        if (!async_data_write_receive(&callid, &len)) {
     131                ipc_answer_0(callid, EINVAL);
     132                ipc_answer_0(rid, EINVAL);
     133                return;
     134        }
     135       
     136        cwd = malloc(len + 1);
     137        if (!cwd) {
     138                ipc_answer_0(callid, ENOMEM);
     139                ipc_answer_0(rid, ENOMEM);
     140                return;
     141        }
     142       
     143        async_data_write_finalize(callid, cwd, len);
     144        cwd[len] = '\0';
     145       
     146        ipc_answer_0(rid, EOK);
     147}
    117148
    118149/** Receive a call setting pathname of the program to execute.
     
    127158        char *name_buf;
    128159       
    129         if (!ipc_data_write_receive(&callid, &len)) {
     160        if (!async_data_write_receive(&callid, &len)) {
    130161                ipc_answer_0(callid, EINVAL);
    131162                ipc_answer_0(rid, EINVAL);
     
    140171        }
    141172       
    142         ipc_data_write_finalize(callid, name_buf, len);
     173        async_data_write_finalize(callid, name_buf, len);
    143174        ipc_answer_0(rid, EOK);
    144175       
     
    164195        int n;
    165196       
    166         if (!ipc_data_write_receive(&callid, &buf_size)) {
     197        if (!async_data_write_receive(&callid, &buf_size)) {
    167198                ipc_answer_0(callid, EINVAL);
    168199                ipc_answer_0(rid, EINVAL);
     
    187218        }
    188219       
    189         ipc_data_write_finalize(callid, arg_buf, buf_size);
     220        async_data_write_finalize(callid, arg_buf, buf_size);
    190221       
    191222        arg_buf[buf_size] = '\0';
     
    239270        ipc_callid_t callid;
    240271        size_t buf_size;
    241         if (!ipc_data_write_receive(&callid, &buf_size)) {
     272        if (!async_data_write_receive(&callid, &buf_size)) {
    242273                ipc_answer_0(callid, EINVAL);
    243274                ipc_answer_0(rid, EINVAL);
     
    268299        }
    269300       
    270         ipc_data_write_finalize(callid, fil_buf, buf_size);
     301        async_data_write_finalize(callid, fil_buf, buf_size);
    271302       
    272303        int count = buf_size / sizeof(fdi_node_t);
     
    312343       
    313344        elf_create_pcb(&prog_info, &pcb);
     345       
     346        pcb.cwd = cwd;
    314347       
    315348        pcb.argc = argc;
     
    406439                case LOADER_GET_TASKID:
    407440                        ldr_get_taskid(callid, &call);
     441                        continue;
     442                case LOADER_SET_CWD:
     443                        ldr_set_cwd(callid, &call);
    408444                        continue;
    409445                case LOADER_SET_PATHNAME:
  • uspace/srv/ns/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Setup toolchain
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../../lib/libc
    33 SOFTINT_PREFIX = ../../lib/softint
     32.PHONY: all clean
    3433
    35 include $(LIBC_PREFIX)/Makefile.toolchain
    36 
    37 LIBS = $(LIBC_PREFIX)/libc.a
    38 
    39 ## Sources
    40 #
    41 
    42 OUTPUT = ns
    43 SOURCES = \
    44         ns.c \
    45         service.c \
    46         clonable.c \
    47         task.c
    48 
    49 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    50 
    51 .PHONY: all clean depend disasm
    52 
    53 all: $(OUTPUT) $(OUTPUT).disasm
    54 
    55 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5637
    5738clean:
    58         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    59 
    60 depend:
    61         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    62 
    63 $(OUTPUT): $(OBJECTS) $(LIBS)
    64         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    65 
    66 disasm: $(OUTPUT).disasm
    67 
    68 $(OUTPUT).disasm: $(OUTPUT)
    69         $(OBJDUMP) -d $< > $@
    70 
    71 %.o: %.S
    72         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    73 
    74 %.o: %.s
    75         $(AS) $(AFLAGS) $< -o $@
    76 
    77 %.o: %.c
    78         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/ns/service.c

    rfcbd1be r1787e527  
    156156               
    157157                hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
    158                 ipcarg_t retval = ipc_forward_fast(pr->callid, hs->phone,
    159                     pr->arg2, pr->arg3, 0, IPC_FF_NONE);
    160                
    161                 if (!(pr->callid & IPC_CALLID_NOTIFICATION))
    162                         ipc_answer_0(pr->callid, retval);
     158                (void) ipc_forward_fast(pr->callid, hs->phone, pr->arg2,
     159                    pr->arg3, 0, IPC_FF_NONE);
    163160               
    164161                list_remove(cur);
     
    242239       
    243240        hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
    244         retval = ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
     241        (void) ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
    245242            IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
     243        return;
    246244       
    247245out:
  • uspace/srv/vfs/Makefile

    rfcbd1be r1787e527  
    11#
    2 # Copyright (c) 2006 Martin Decky
    3 # Copyright (c) 2008 Jakub Jermar
     2# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    44# All rights reserved.
    55#
     
    2828#
    2929
    30 ## Setup toolchain
    31 #
     30include Makefile.common
    3231
    33 LIBC_PREFIX = ../../lib/libc
    34 SOFTINT_PREFIX = ../../lib/softint
     32.PHONY: all clean
    3533
    36 include $(LIBC_PREFIX)/Makefile.toolchain
    37 
    38 LIBS = $(LIBC_PREFIX)/libc.a
    39 
    40 ## Sources
    41 #
    42 
    43 OUTPUT = vfs
    44 SOURCES = \
    45         vfs.c \
    46         vfs_node.c \
    47         vfs_file.c \
    48         vfs_ops.c \
    49         vfs_lookup.c \
    50         vfs_register.c
    51 
    52 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    53 
    54 .PHONY: all clean depend disasm
    55 
    56 all: $(OUTPUT) $(OUTPUT).disasm
    57 
    58 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBS)
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5937
    6038clean:
    61         -rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend $(OBJECTS)
    62 
    63 depend:
    64         $(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
    65 
    66 $(OUTPUT): $(OBJECTS) $(LIBS)
    67         $(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
    68 
    69 disasm: $(OUTPUT).disasm
    70 
    71 $(OUTPUT).disasm: $(OUTPUT)
    72         $(OBJDUMP) -d $< > $@
    73 
    74 %.o: %.S
    75         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    76 
    77 %.o: %.s
    78         $(AS) $(AFLAGS) $< -o $@
    79 
    80 %.o: %.c
    81         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/srv/vfs/vfs.c

    rfcbd1be r1787e527  
    126126                        vfs_sync(callid, &call);
    127127                        break;
     128                case VFS_IN_DUP:
     129                        vfs_dup(callid, &call);
    128130                default:
    129131                        ipc_answer_0(callid, ENOTSUP);
  • uspace/srv/vfs/vfs.h

    rfcbd1be r1787e527  
    186186extern bool vfs_files_init(void);
    187187extern vfs_file_t *vfs_file_get(int);
    188 extern int vfs_fd_alloc(void);
     188extern int vfs_fd_assign(vfs_file_t *file, int fd);
     189extern int vfs_fd_alloc(bool desc);
    189190extern int vfs_fd_free(int);
    190191
     
    200201extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
    201202extern void vfs_sync(ipc_callid_t, ipc_call_t *);
     203extern void vfs_dup(ipc_callid_t, ipc_call_t *);
    202204extern void vfs_close(ipc_callid_t, ipc_call_t *);
    203205extern void vfs_read(ipc_callid_t, ipc_call_t *);
  • uspace/srv/vfs/vfs_file.c

    rfcbd1be r1787e527  
    7676/** Allocate a file descriptor.
    7777 *
    78  * @return              First available file descriptor or a negative error
    79  *                      code.
    80  */
    81 int vfs_fd_alloc(void)
     78 * @param desc If true, look for an available file descriptor
     79 *             in a descending order.
     80 *
     81 * @return First available file descriptor or a negative error
     82 *         code.
     83 */
     84int vfs_fd_alloc(bool desc)
    8285{
    8386        if (!vfs_files_init())
     
    8588       
    8689        unsigned int i;
    87         for (i = 0; i < MAX_OPEN_FILES; i++) {
     90        if (desc)
     91                i = MAX_OPEN_FILES - 1;
     92        else
     93                i = 0;
     94       
     95        while (true) {
    8896                if (!files[i]) {
    8997                        files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
     
    96104                        return (int) i;
    97105                }
     106               
     107                if (desc) {
     108                        if (i == 0)
     109                                break;
     110                       
     111                        i--;
     112                } else {
     113                        if (i == MAX_OPEN_FILES - 1)
     114                                break;
     115                       
     116                        i++;
     117                }
    98118        }
    99119       
     
    118138        vfs_file_delref(files[fd]);
    119139        files[fd] = NULL;
     140       
     141        return EOK;
     142}
     143
     144/** Assign a file to a file descriptor.
     145 *
     146 * @param file File to assign.
     147 * @param fd   File descriptor to assign to.
     148 *
     149 * @return EOK on success or EINVAL if fd is an invalid or already
     150 *         used file descriptor.
     151 *
     152 */
     153int vfs_fd_assign(vfs_file_t *file, int fd)
     154{
     155        if (!vfs_files_init())
     156                return ENOMEM;
     157       
     158        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] != NULL))
     159                return EINVAL;
     160       
     161        files[fd] = file;
     162        vfs_file_addref(files[fd]);
    120163       
    121164        return EOK;
  • uspace/srv/vfs/vfs_lookup.c

    rfcbd1be r1787e527  
    209209            (ipcarg_t) result->triplet.index, &answer);
    210210       
    211        
    212211        ipcarg_t rc;
    213212        async_wait_for(req, &rc);
  • uspace/srv/vfs/vfs_ops.c

    rfcbd1be r1787e527  
    125125                            (ipcarg_t) dev_handle, &answer);
    126126                        /* send the mount options */
    127                         rc = ipc_data_write_start(phone, (void *)opts,
     127                        rc = async_data_write_start(phone, (void *)opts,
    128128                            str_size(opts));
    129129                        if (rc != EOK) {
     
    207207       
    208208        /* send the mount options */
    209         rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));
     209        rc = async_data_write_start(phone, (void *)opts, str_size(opts));
    210210        if (rc != EOK) {
    211211                async_wait_for(msg, NULL);
     
    268268        ipc_callid_t callid;
    269269        size_t size;
    270         if (!ipc_data_write_receive(&callid, &size)) {
     270        if (!async_data_write_receive(&callid, &size)) {
    271271                ipc_answer_0(callid, EINVAL);
    272272                ipc_answer_0(rid, EINVAL);
     
    290290       
    291291        /* Deliver the mount point. */
    292         ipcarg_t retval = ipc_data_write_finalize(callid, mp, size);
     292        ipcarg_t retval = async_data_write_finalize(callid, mp, size);
    293293        if (retval != EOK) {
    294294                ipc_answer_0(rid, retval);
     
    299299       
    300300        /* Now we expect to receive the mount options. */
    301         if (!ipc_data_write_receive(&callid, &size)) {
     301        if (!async_data_write_receive(&callid, &size)) {
    302302                ipc_answer_0(callid, EINVAL);
    303303                ipc_answer_0(rid, EINVAL);
     
    324324
    325325        /* Deliver the mount options. */
    326         retval = ipc_data_write_finalize(callid, opts, size);
     326        retval = async_data_write_finalize(callid, opts, size);
    327327        if (retval != EOK) {
    328328                ipc_answer_0(rid, retval);
     
    337337         * system.
    338338         */
    339         if (!ipc_data_write_receive(&callid, &size)) {
     339        if (!async_data_write_receive(&callid, &size)) {
    340340                ipc_answer_0(callid, EINVAL);
    341341                ipc_answer_0(rid, EINVAL);
     
    370370       
    371371        /* Deliver the file system name. */
    372         retval = ipc_data_write_finalize(callid, fs_name, size);
     372        retval = async_data_write_finalize(callid, fs_name, size);
    373373        if (retval != EOK) {
    374374                ipc_answer_0(rid, retval);
     
    469469       
    470470        ipc_callid_t callid;
    471         if (!ipc_data_write_receive(&callid, &len)) {
     471        if (!async_data_write_receive(&callid, &len)) {
    472472                ipc_answer_0(callid, EINVAL);
    473473                ipc_answer_0(rid, EINVAL);
     
    483483       
    484484        int rc;
    485         if ((rc = ipc_data_write_finalize(callid, path, len))) {
     485        if ((rc = async_data_write_finalize(callid, path, len))) {
    486486                ipc_answer_0(rid, rc);
    487487                free(path);
     
    543543         * structure.
    544544         */
    545         int fd = vfs_fd_alloc();
     545        int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
    546546        if (fd < 0) {
    547547                vfs_node_put(node);
     
    620620         * structure.
    621621         */
    622         int fd = vfs_fd_alloc();
     622        int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
    623623        if (fd < 0) {
    624624                vfs_node_put(node);
     
    679679}
    680680
     681static int vfs_close_internal(vfs_file_t *file)
     682{
     683        /*
     684         * Lock the open file structure so that no other thread can manipulate
     685         * the same open file at a time.
     686         */
     687        fibril_mutex_lock(&file->lock);
     688       
     689        if (file->refcnt <= 1) {
     690                /* Only close the file on the destination FS server
     691                   if there are no more file descriptors (except the
     692                   present one) pointing to this file. */
     693               
     694                int fs_phone = vfs_grab_phone(file->node->fs_handle);
     695               
     696                /* Make a VFS_OUT_CLOSE request at the destination FS server. */
     697                aid_t msg;
     698                ipc_call_t answer;
     699                msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle,
     700                    file->node->index, &answer);
     701               
     702                /* Wait for reply from the FS server. */
     703                ipcarg_t rc;
     704                async_wait_for(msg, &rc);
     705               
     706                vfs_release_phone(fs_phone);
     707                fibril_mutex_unlock(&file->lock);
     708               
     709                return IPC_GET_ARG1(answer);
     710        }
     711       
     712        fibril_mutex_unlock(&file->lock);
     713        return EOK;
     714}
     715
    681716void vfs_close(ipc_callid_t rid, ipc_call_t *request)
    682717{
     
    690725        }
    691726       
    692         /*
    693          * Lock the open file structure so that no other thread can manipulate
    694          * the same open file at a time.
    695          */
    696         fibril_mutex_lock(&file->lock);
    697         int fs_phone = vfs_grab_phone(file->node->fs_handle);
    698        
    699         /* Make a VFS_OUT_CLOSE request at the destination FS server. */
    700         aid_t msg;
    701         ipc_call_t answer;
    702         msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle,
    703             file->node->index, &answer);
    704 
    705         /* Wait for reply from the FS server. */
    706         ipcarg_t rc;
    707         async_wait_for(msg, &rc);
    708 
    709         vfs_release_phone(fs_phone);
    710         fibril_mutex_unlock(&file->lock);
    711        
    712         int retval = IPC_GET_ARG1(answer);
    713         if (retval != EOK)
    714                 ipc_answer_0(rid, retval);
    715        
    716         retval = vfs_fd_free(fd);
    717         ipc_answer_0(rid, retval);
     727        int ret = vfs_close_internal(file);
     728        if (ret != EOK)
     729                ipc_answer_0(rid, ret);
     730       
     731        ret = vfs_fd_free(fd);
     732        ipc_answer_0(rid, ret);
    718733}
    719734
     
    747762        int res;
    748763        if (read)
    749                 res = ipc_data_read_receive(&callid, NULL);
     764                res = async_data_read_receive(&callid, NULL);
    750765        else
    751                 res = ipc_data_write_receive(&callid, NULL);
     766                res = async_data_write_receive(&callid, NULL);
    752767        if (!res) {
    753768                ipc_answer_0(callid, EINVAL);
     
    934949{
    935950        int fd = IPC_GET_ARG1(*request);
    936         size_t size = IPC_GET_ARG2(*request);
    937951        ipcarg_t rc;
    938952
     
    944958
    945959        ipc_callid_t callid;
    946         if (!ipc_data_read_receive(&callid, NULL)) {
     960        if (!async_data_read_receive(&callid, NULL)) {
    947961                ipc_answer_0(callid, EINVAL);
    948962                ipc_answer_0(rid, EINVAL);
     
    970984        ipc_callid_t callid;
    971985
    972         if (!ipc_data_write_receive(&callid, &len)) {
     986        if (!async_data_write_receive(&callid, &len)) {
    973987                ipc_answer_0(callid, EINVAL);
    974988                ipc_answer_0(rid, EINVAL);
     
    982996        }
    983997        int rc;
    984         if ((rc = ipc_data_write_finalize(callid, path, len))) {
     998        if ((rc = async_data_write_finalize(callid, path, len))) {
    985999                ipc_answer_0(rid, rc);
    9861000                free(path);
     
    9891003        path[len] = '\0';
    9901004
    991         if (!ipc_data_read_receive(&callid, NULL)) {
     1005        if (!async_data_read_receive(&callid, NULL)) {
    9921006                free(path);
    9931007                ipc_answer_0(callid, EINVAL);
     
    10381052        ipc_callid_t callid;
    10391053
    1040         if (!ipc_data_write_receive(&callid, &len)) {
     1054        if (!async_data_write_receive(&callid, &len)) {
    10411055                ipc_answer_0(callid, EINVAL);
    10421056                ipc_answer_0(rid, EINVAL);
     
    10501064        }
    10511065        int rc;
    1052         if ((rc = ipc_data_write_finalize(callid, path, len))) {
     1066        if ((rc = async_data_write_finalize(callid, path, len))) {
    10531067                ipc_answer_0(rid, rc);
    10541068                free(path);
     
    10751089        ipc_callid_t callid;
    10761090
    1077         if (!ipc_data_write_receive(&callid, &len)) {
     1091        if (!async_data_write_receive(&callid, &len)) {
    10781092                ipc_answer_0(callid, EINVAL);
    10791093                ipc_answer_0(rid, EINVAL);
     
    10871101        }
    10881102        int rc;
    1089         if ((rc = ipc_data_write_finalize(callid, path, len))) {
     1103        if ((rc = async_data_write_finalize(callid, path, len))) {
    10901104                ipc_answer_0(rid, rc);
    10911105                free(path);
     
    11261140
    11271141        /* Retrieve the old path. */
    1128         if (!ipc_data_write_receive(&callid, &olen)) {
     1142        if (!async_data_write_receive(&callid, &olen)) {
    11291143                ipc_answer_0(callid, EINVAL);
    11301144                ipc_answer_0(rid, EINVAL);
     
    11371151                return;
    11381152        }
    1139         if ((rc = ipc_data_write_finalize(callid, old, olen))) {
     1153        if ((rc = async_data_write_finalize(callid, old, olen))) {
    11401154                ipc_answer_0(rid, rc);
    11411155                free(old);
     
    11451159       
    11461160        /* Retrieve the new path. */
    1147         if (!ipc_data_write_receive(&callid, &nlen)) {
     1161        if (!async_data_write_receive(&callid, &nlen)) {
    11481162                ipc_answer_0(callid, EINVAL);
    11491163                ipc_answer_0(rid, EINVAL);
     
    11581172                return;
    11591173        }
    1160         if ((rc = ipc_data_write_finalize(callid, new, nlen))) {
     1174        if ((rc = async_data_write_finalize(callid, new, nlen))) {
    11611175                ipc_answer_0(rid, rc);
    11621176                free(old);
     
    13111325}
    13121326
     1327void vfs_dup(ipc_callid_t rid, ipc_call_t *request)
     1328{
     1329        int oldfd = IPC_GET_ARG1(*request);
     1330        int newfd = IPC_GET_ARG2(*request);
     1331       
     1332        /* Lookup the file structure corresponding to oldfd. */
     1333        vfs_file_t *oldfile = vfs_file_get(oldfd);
     1334        if (!oldfile) {
     1335                ipc_answer_0(rid, EBADF);
     1336                return;
     1337        }
     1338       
     1339        /* If the file descriptors are the same, do nothing. */
     1340        if (oldfd == newfd) {
     1341                ipc_answer_1(rid, EOK, newfd);
     1342                return;
     1343        }
     1344       
     1345        /*
     1346         * Lock the open file structure so that no other thread can manipulate
     1347         * the same open file at a time.
     1348         */
     1349        fibril_mutex_lock(&oldfile->lock);
     1350       
     1351        /* Lookup an open file structure possibly corresponding to newfd. */
     1352        vfs_file_t *newfile = vfs_file_get(newfd);
     1353        if (newfile) {
     1354                /* Close the originally opened file. */
     1355                int ret = vfs_close_internal(newfile);
     1356                if (ret != EOK) {
     1357                        ipc_answer_0(rid, ret);
     1358                        return;
     1359                }
     1360               
     1361                ret = vfs_fd_free(newfd);
     1362                if (ret != EOK) {
     1363                        ipc_answer_0(rid, ret);
     1364                        return;
     1365                }
     1366        }
     1367       
     1368        /* Assign the old file to newfd. */
     1369        int ret = vfs_fd_assign(oldfile, newfd);
     1370        fibril_mutex_unlock(&oldfile->lock);
     1371       
     1372        if (ret != EOK)
     1373                ipc_answer_0(rid, ret);
     1374        else
     1375                ipc_answer_1(rid, EOK, newfd);
     1376}
     1377
    13131378/**
    13141379 * @}
  • uspace/srv/vfs/vfs_register.c

    rfcbd1be r1787e527  
    122122         * VFS info structure from the client FS.
    123123         */
    124         if (!ipc_data_write_receive(&callid, &size)) {
     124        if (!async_data_write_receive(&callid, &size)) {
    125125                /*
    126126                 * The client doesn't obey the same protocol as we do.
     
    163163        fibril_mutex_initialize(&fs_info->phone_lock);
    164164               
    165         rc = ipc_data_write_finalize(callid, &fs_info->vfs_info, size);
     165        rc = async_data_write_finalize(callid, &fs_info->vfs_info, size);
    166166        if (rc != EOK) {
    167167                dprintf("Failed to deliver the VFS info into our AS, rc=%d.\n",
     
    229229         */
    230230
    231         if (!ipc_share_in_receive(&callid, &size)) {
     231        if (!async_share_in_receive(&callid, &size)) {
    232232                dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
    233233                list_remove(&fs_info->fs_link);
     
    257257         * Commit to read-only sharing the PLB with the client.
    258258         */
    259         (void) ipc_share_in_finalize(callid, plb,
     259        (void) async_share_in_finalize(callid, plb,
    260260            AS_AREA_READ | AS_AREA_CACHEABLE);
    261261
Note: See TracChangeset for help on using the changeset viewer.