Module Name: src Committed By: macallan Date: Tue Jan 8 19:03:16 UTC 2013
Modified Files: src/sys/arch/arm/omap: omap2_obio.c omap2_reg.h Added Files: src/sys/arch/arm/omap: omapdma.c omapdmareg.h omapdmavar.h Log Message: add a simple driver for OMAP3's built-in DMA controller To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 src/sys/arch/arm/omap/omap2_obio.c cvs rdiff -u -r1.15 -r1.16 src/sys/arch/arm/omap/omap2_reg.h cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/omap/omapdma.c \ src/sys/arch/arm/omap/omapdmareg.h src/sys/arch/arm/omap/omapdmavar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/omap/omap2_obio.c diff -u src/sys/arch/arm/omap/omap2_obio.c:1.18 src/sys/arch/arm/omap/omap2_obio.c:1.19 --- src/sys/arch/arm/omap/omap2_obio.c:1.18 Mon Dec 24 06:28:55 2012 +++ src/sys/arch/arm/omap/omap2_obio.c Tue Jan 8 19:03:16 2013 @@ -1,7 +1,7 @@ -/* $Id: omap2_obio.c,v 1.18 2012/12/24 06:28:55 kiyohara Exp $ */ +/* $Id: omap2_obio.c,v 1.19 2013/01/08 19:03:16 macallan Exp $ */ /* adapted from: */ -/* $NetBSD: omap2_obio.c,v 1.18 2012/12/24 06:28:55 kiyohara Exp $ */ +/* $NetBSD: omap2_obio.c,v 1.19 2013/01/08 19:03:16 macallan Exp $ */ /* @@ -103,7 +103,7 @@ #include "opt_omap.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: omap2_obio.c,v 1.18 2012/12/24 06:28:55 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: omap2_obio.c,v 1.19 2013/01/08 19:03:16 macallan Exp $"); #include "locators.h" #include "obio.h" @@ -364,7 +364,7 @@ static const struct { { .name = "avic", .addr = INTC_BASE_3430, .required = true }, #endif #if defined(OMAP_3530) - { .name = "avic", .addr = INTC_BASE_3530, .required = true }, + { .name = "avic", .addr = INTC_BASE_3530, .required = true }, #endif { .name = "gpio1", .addr = GPIO1_BASE, .required = false }, { .name = "gpio2", .addr = GPIO2_BASE, .required = false }, @@ -385,6 +385,9 @@ static const struct { { .name = "omapicu", .addr = 0x48200000, .required = true }, { .name = "prcm", .addr = 0x44e00000, .required = true }, #endif +#if defined(OMAP_3530) + { .name = "omapdma", .addr = OMAP3530_SDMA_BASE, .required = true }, +#endif }; static void Index: src/sys/arch/arm/omap/omap2_reg.h diff -u src/sys/arch/arm/omap/omap2_reg.h:1.15 src/sys/arch/arm/omap/omap2_reg.h:1.16 --- src/sys/arch/arm/omap/omap2_reg.h:1.15 Thu Dec 13 01:15:50 2012 +++ src/sys/arch/arm/omap/omap2_reg.h Tue Jan 8 19:03:16 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: omap2_reg.h,v 1.15 2012/12/13 01:15:50 matt Exp $ */ +/* $NetBSD: omap2_reg.h,v 1.16 2013/01/08 19:03:16 macallan Exp $ */ /* * Copyright (c) 2007 Microsoft @@ -143,7 +143,8 @@ #define OMAP2_CM_ICLKEN1_CORE 0x210 #define OMAP2_CM_ICLKEN2_CORE 0x214 #define OMAP2_CM_CLKSEL2_CORE 0x244 -#define OMAP2_CM_SIZE (OMAP2_CM_CLKSEL2_CORE + 4) +#define OMAP3_CM_IDLEST1_CORE 0xa20 +#define OMAP2_CM_SIZE (0x1000) /* * bit defines for OMAP2_CM_CLKSEL_MPU @@ -729,4 +730,10 @@ #define OMAP3530_SDRC_BASE 0x6d000000 #define OMAP3530_SDRC_SIZE 0x00010000 /* 16KB */ +/* + * DMA + */ +#define OMAP3530_SDMA_BASE 0x48056000 +#define OMAP3530_SDMA_SIZE 0x00001000 /* 4KB */ + #endif /* _ARM_OMAP_OMAP2_REG_H_ */ Added files: Index: src/sys/arch/arm/omap/omapdma.c diff -u /dev/null src/sys/arch/arm/omap/omapdma.c:1.1 --- /dev/null Tue Jan 8 19:03:16 2013 +++ src/sys/arch/arm/omap/omapdma.c Tue Jan 8 19:03:16 2013 @@ -0,0 +1,157 @@ +/* $NetBSD: omapdma.c,v 1.1 2013/01/08 19:03:16 macallan Exp $ */ + +/* + * Copyright (c) 2012 Michael Lorenz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * OMAP 3530 DMA controller + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: omapdma.c,v 1.1 2013/01/08 19:03:16 macallan Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/lwp.h> +#include <sys/kauth.h> + +#include <sys/bus.h> +#include <arm/omap/omapdmareg.h> +#include <arm/omap/omapdmavar.h> +#include <arm/omap/omap2_obiovar.h> +#include <arm/omap/omap2_obioreg.h> +#include <arm/omap/omap2_prcm.h> + +struct omapdma_softc { + device_t sc_dev; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_regh; +}; + +static int omapdma_match(device_t, cfdata_t, void *); +static void omapdma_attach(device_t, device_t, void *); + +CFATTACH_DECL_NEW(omapdma, sizeof(struct omapdma_softc), + omapdma_match, omapdma_attach, NULL, NULL); + +struct omapdma_softc *omapdma_sc = NULL; + +static int +omapdma_match(device_t parent, cfdata_t match, void *aux) +{ + struct obio_attach_args *obio = aux; + + if ((obio->obio_addr == -1) || (obio->obio_size == 0)) + return 0; + return 1; +} + +static void +omapdma_attach(device_t parent, device_t self, void *aux) +{ + struct omapdma_softc *sc = device_private(self); + struct obio_attach_args *obio = aux; + uint32_t reg; + + sc->sc_iot = obio->obio_iot; + sc->sc_dev = self; + + printf(": OMAP DMA controller rev "); + if (bus_space_map(obio->obio_iot, obio->obio_addr, obio->obio_size, 0, + &sc->sc_regh)) { + aprint_error_dev(sc->sc_dev, ": couldn't map register space\n"); + return; + } + reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPDMA_REVISION); + printf("%d.%d\n", (reg >> 4) & 0xf, reg & 0xf); + + /* disable & clear all interrupts etc. */ + bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPDMA_IRQENABLE_L0, 0); + bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPDMA_IRQENABLE_L1, 0); + bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPDMA_IRQENABLE_L2, 0); + bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPDMA_IRQENABLE_L3, 0); + bus_space_write_4(sc->sc_iot, sc->sc_regh, + OMAPDMA_IRQSTATUS_L0, 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_regh, + OMAPDMA_IRQSTATUS_L1, 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_regh, + OMAPDMA_IRQSTATUS_L2, 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_regh, + OMAPDMA_IRQSTATUS_L3, 0xffffffff); + + bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPDMA_SYSCONFIG, + OMAPDMA_IDLEMODE_NO_STANDBY | OMAPDMA_SMART_IDLE | + OMAPDMA_AUTOIDLE); + + omapdma_sc = sc; + + /* + * TODO: + * - channel allocation + */ +} + +void +omapdma_write_reg(int reg, uint32_t val) +{ + if (omapdma_sc != NULL) { + bus_space_write_4(omapdma_sc->sc_iot, omapdma_sc->sc_regh, + reg, val); + } +} + +uint32_t +omapdma_read_reg(int reg) +{ + if (omapdma_sc != NULL) { + return bus_space_read_4(omapdma_sc->sc_iot, + omapdma_sc->sc_regh, reg); + } + return 0; +} + +void +omapdma_write_ch_reg(int ch, int reg, uint32_t val) +{ + if (omapdma_sc != NULL) { + bus_space_write_4(omapdma_sc->sc_iot, omapdma_sc->sc_regh, + OMAPDMA_CHANNEL_BASE + 0x60 * ch + reg, val); + } +} + +uint32_t +omapdma_read_ch_reg(int ch, int reg) +{ + if (omapdma_sc != NULL) { + return bus_space_read_4(omapdma_sc->sc_iot, + omapdma_sc->sc_regh, + OMAPDMA_CHANNEL_BASE + 0x60 * ch + reg); + } + return 0; +} Index: src/sys/arch/arm/omap/omapdmareg.h diff -u /dev/null src/sys/arch/arm/omap/omapdmareg.h:1.1 --- /dev/null Tue Jan 8 19:03:16 2013 +++ src/sys/arch/arm/omap/omapdmareg.h Tue Jan 8 19:03:16 2013 @@ -0,0 +1,176 @@ +/* $NetBSD: omapdmareg.h,v 1.1 2013/01/08 19:03:16 macallan Exp $ */ + +/* + * Copyright (c) 2012 Michael Lorenz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: omapdmareg.h,v 1.1 2013/01/08 19:03:16 macallan Exp $"); + +#ifndef OMAPDMA_REG_H +#define OMAPDMA_REG_H + +/* + * all register offsets are relative to OMAP3530_SDMA_BASE + */ + +#define OMAPDMA_REVISION 0x00000000 + +/* each bit corresponds to a DMA channel, write 1 to clear */ +#define OMAPDMA_IRQSTATUS_L0 0x00000008 +#define OMAPDMA_IRQSTATUS_L1 0x0000000c +#define OMAPDMA_IRQSTATUS_L2 0x00000010 +#define OMAPDMA_IRQSTATUS_L3 0x00000014 + +#define OMAPDMA_IRQENABLE_L0 0x00000018 +#define OMAPDMA_IRQENABLE_L1 0x0000001c +#define OMAPDMA_IRQENABLE_L2 0x00000020 +#define OMAPDMA_IRQENABLE_L3 0x00000024 + +#define OMAPDMA_SYSSTATUS 0x00000028 + #define OMAPDMA_RESET_DONE 0x00000001 + +#define OMAPDMA_SYSCONFIG 0x0000002c + #define OMAPDMA_IDLEMODE_MASK 0x00003000 + #define OMAPDMA_IDLEMODE_FORCE_STANDBY 0x00000000 + #define OMAPDMA_IDLEMODE_NO_STANDBY 0x00001000 + #define OMAPDMA_IDLEMODE_SMART_STANDBY 0x00002000 + #define OMAPDMA_CLKACT_MASK 0x00000300 + #define OMAPDMA_EMUFREE 0x00000020 + #define OMAPDMA_SIDLEMODE_MASK 0x00000018 + #define OMAPDMA_FORCE_IDLE 0x00000000 + #define OMAPDMA_NO_IDLE 0x00000008 + #define OMAPDMA_SMART_IDLE 0x00000010 + #define OMAPDMA_SOFTRESET 0x00000002 + #define OMAPDMA_AUTOIDLE 0x00000001 + +/* capability registers */ +#define OMAPDMA_CAPS_0 0x00000064 + #define OMAPDMA_CAP_FILL 0x00080000 /* fill support */ + #define OMAPDMA_CAP_TRANS_BLT 0x00040000 /* transparent blit */ +#define OMAPDMA_CAPS_2 0x0000006c +#define OMAPDMA_CAPS_3 0x00000070 +#define OMAPDMA_CAPS_4 0x00000074 +#define OMAPDMA_GCR 0x00000078 + +/* + * there are 32 channels, each occupies a 0x60 register space starting at + * 0x00000080 + 0x60 * c for c = 0 .. 31 + */ +#define OMAPDMA_CHANNEL_BASE 0x00000080 + +#define OMAPDMAC_CCR 0x00000000 + #define CCR_WRITE_PRIORITY 0x04000000 + #define CCR_BUFFERING_DISABLE 0x02000000 + #define CCR_SEL_SRC_DST_SYNC 0x01000000 + #define CCR_PREFETCH 0x00800000 + #define CCR_SUPERVISOR 0x00400000 + #define CCR_SUNC_CONTROL_UPPER_MASK 0x00180000 + #define CCR_BLOCK_SYNC 0x00040000 + #define CCR_TRANSPARENT_COPY_ENABLE 0x00020000 + #define CCR_CONST_FILL_ENABLE 0x00010000 + #define CCR_DST_AMODE_MASK 0x0000c000 + #define CCR_DST_AMODE_CONST_ADDR 0x00000000 + #define CCR_DST_AMODE_POST_INCR 0x00004000 + #define CCR_DST_AMODE_SINGLE_INDEX 0x00008000 + #define CCR_DST_AMODE_DOUBLE_INDEX 0x0000c000 + #define CCR_SRC_AMODE_MASK 0x00003000 + #define CCR_SRC_AMODE_CONST_ADDR 0x00000000 + #define CCR_SRC_AMODE_POST_INCR 0x00001000 + #define CCR_SRC_AMODE_SINGLE_INDEX 0x00002000 + #define CCR_SRC_AMODE_DOUBLE_INDEX 0x00003000 + #define CCR_WR_ACTIVE 0x00000400 + #define CCR_RD_ACTIVE 0x00000200 + #define CCR_SUSPEND_SENSITIVE 0x00000100 + #define CCR_ENABLE 0x00000080 + #define CCR_READ_PRIORITY 0x00000040 + #define CCR_FRAME_SYNC 0x00000020 + #define CCR_SYNCHRO_CONTROL_MASK 0x0000001f +#define OMAPDMAC_CLNK_CTRL 0x00000004 + #define CLNK_ENABLE_LNK 0x00008000 + #define CLNK_NEXT_CHANNEL_MASK 0x0000001f +#define OMAPDMAC_CICRI 0x00000008 + #define CICRI_DRAIN_IE 0x00001000 + #define CICRI_MISALIGNED_ERR_IE 0x00000800 + #define CICRI_SUPERVISOR_ERR_IE 0x00000400 + #define CICRI_TRANSFER_ERR_IE 0x00000100 + #define CICRI_PKT_IE 0x00000080 + #define CICRI_BLOCK_IE 0x00000020 + #define CICRI_LAST_IE 0x00000010 + #define CICRI_FRAME_IE 0x00000008 + #define CICRI_HALF_IE 0x00000004 + #define CICRI_DROP_IE 0x00000002 +#define OMAPDMAC_CSR 0x0000000c + #define CSR_DRAIN_END 0x00001000 + #define CSR_MISALIGNED_ADRS_ERR 0x00000800 + #define CSR_SUPERVISOR_ERR 0x00000400 + #define CSR_TRANS_ERR 0x00000100 + #define CSR_PKT 0x00000080 + #define CSR_SYNC 0x00000040 + #define CSR_BLOCK 0x00000020 + #define CSR_LAST 0x00000010 + #define CSR_FRAME 0x00000008 + #define CSR_HALF 0x00000004 + #define CSR_DROP 0x00000002 +#define OMAPDMAC_CSDPI 0x00000010 + #define CSDPI_SRC_ENDIAN 0x00100000 + #define CSDPI_SRC_ENDIAN_LOCK 0x00080000 + #define CSDPI_DST_ENDIAN 0x00040000 + #define CSDPI_DST_ENDIAN_LOCK 0x00020000 + #define CSDPI_WRITE_MODE_MASK 0x00018000 + #define CSDPI_WRITE_NONPOSTED 0x00000000 + #define CSDPI_WRITE_POSTED 0x00008000 + #define CSDPI_WRITE_EXCEPT_LAST 0x00010000 + #define CSDPI_DST_BURST_MASK 0x0000c000 + #define CSDPI_DST_BURST_SINGLE 0x00000000 + #define CSDPI_DST_BURST_16 0x00004000 + #define CSDPI_DST_BURST_32 0x00008000 + #define CSDPI_DST_BURST_64 0x0000c000 + #define CSDPI_DST_PACKED 0x00002000 + #define CSDPI_SCR_BURST_MASK 0x00000180 + #define CSDPI_SCR_BURST_SINGLE 0x00000000 + #define CSDPI_SCR_BURST_16 0x00000080 + #define CSDPI_SCR_BURST_32 0x00000100 + #define CSDPI_SCR_BURST_64 0x00000180 + #define CSDPI_SCR_PACKED 0x00000040 + #define CSDPI_DATA_TYPE_MASK 0x00000003 + #define CSDPI_DATA_TYPE_8 0x00000000 + #define CSDPI_DATA_TYPE_16 0x00000001 + #define CSDPI_DATA_TYPE_32 0x00000002 +#define OMAPDMAC_CEN 0x00000014 +#define OMAPDMAC_CFN 0x00000018 +#define OMAPDMAC_CSSA 0x0000001c +#define OMAPDMAC_CDSA 0x00000020 +#define OMAPDMAC_CSEI 0x00000024 +#define OMAPDMAC_CSFI 0x00000028 +#define OMAPDMAC_CDEI 0x0000002c +#define OMAPDMAC_CDFI 0x00000030 +#define OMAPDMAC_CSAC 0x00000034 +#define OMAPDMAC_CDAC 0x00000038 +#define OMAPDMAC_CCEN 0x0000003c +#define OMAPDMAC_CCFN 0x00000040 +#define OMAPDMAC_COLOR 0x00000044 + +#endif /* OMAPDMA_REG_H */ Index: src/sys/arch/arm/omap/omapdmavar.h diff -u /dev/null src/sys/arch/arm/omap/omapdmavar.h:1.1 --- /dev/null Tue Jan 8 19:03:16 2013 +++ src/sys/arch/arm/omap/omapdmavar.h Tue Jan 8 19:03:16 2013 @@ -0,0 +1,41 @@ +/* $NetBSD: omapdmavar.h,v 1.1 2013/01/08 19:03:16 macallan Exp $ */ + +/* + * Copyright (c) 2012 Michael Lorenz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: omapdmavar.h,v 1.1 2013/01/08 19:03:16 macallan Exp $"); + +#ifndef OMAPDMA_VAR_H +#define OMAPDMA_VAR_H + +void omapdma_write_reg(int, uint32_t); +uint32_t omapdma_read_reg(int); +void omapdma_write_ch_reg(int, int, uint32_t); +uint32_t omapdma_read_ch_reg(int, int); + + +#endif /* OMAPDMA_VAR_H */ \ No newline at end of file