<commit_before>// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 <NAME>
//
// SPDX-License-Identifier: MIT

#include "py/mpconfig.h"
#if MICROPY_VFS && MICROPY_VFS_FAT

#include <stdint.h>
#include <stdio.h>

#include "py/mphal.h"

#include "py/runtime.h"
#include "py/binary.h"
#include "py/objarray.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "extmod/vfs_fat.h"

#if _MAX_SS == _MIN_SS
#define SECSIZE(fs) (_MIN_SS)
#else
#define SECSIZE(fs) ((fs)->ssize)
#endif

typedef void *bdev_t;
STATIC fs_user_mount_t *disk_get_device(void *bdev) {
    return (fs_user_mount_t*)bdev;
}

/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
    bdev_t pdrv,      /* Physical drive nmuber (0..) */
    BYTE *buff,        /* Data buffer to store read data */
    DWORD sector,    /* Sector address (LBA) */
    UINT count        /* Number of sectors to read (1..128) */
)
{
    fs_user_mount_t *vfs = disk_get_device(pdrv);
    if (vfs == NULL) {
        return RES_PARERR;
    }

    if (vfs->flags & FSUSER_NATIVE) {
        mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->readblocks[2];
        if (f(buff, sector, count) != 0) {
            return RES_ERROR;
        }
    } else {
        mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), buff};
        vfs->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
        vfs->readblocks[3] = MP_OBJ_FROM_PTR(&ar);
        nlr_buf_t nlr;
        if (nlr_push(&nlr) == 0) {
            mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->readblocks);
            nlr_pop();
            if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
                return RES_ERROR;
            }
        } else {
            // Exception thrown by readblocks or something it calls.
            return RES_ERROR;
        }
    }

    return RES_OK;
}

/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

DRESULT disk_write (
    bdev_t pdrv,          /* Physical drive nmuber (0..) */
    const BYTE *buff,    /* Data to be written */
    DWORD sector,        /* Sector address (LBA) */
    UINT count            /* Number of sectors to write (1..128) */
)
{
    fs_user_mount_t *vfs = disk_get_device(pdrv);
    if (vfs == NULL) {
        return RES_PARERR;
    }

    if (vfs->writeblocks[0] == MP_OBJ_NULL) {
        // read-only block device
        return RES_WRPRT;
    }

    if (vfs->flags & FSUSER_NATIVE) {
        mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->writeblocks[2];
        if (f(buff, sector, count) != 0) {
            return RES_ERROR;
        }
    } else {
        mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), (void*)buff};
        vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
        vfs->writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
        nlr_buf_t nlr;
        if (nlr_push(&nlr) == 0) {
            mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->writeblocks);
            nlr_pop();
            if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
                return RES_ERROR;
            }
        } else {
            // Exception thrown by writeblocks or something it calls.
            return RES_ERROR;
        }
    }

    return RES_OK;
}


/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
    bdev_t pdrv,      /* Physical drive nmuber (0..) */
    BYTE cmd,         /* Control code */
    void *buff        /* Buffer to send/receive control data */
)
{
    fs_user_mount_t *vfs = disk_get_device(pdrv);
    if (vfs == NULL) {
        return RES_PARERR;
    }

    // First part: call the relevant method of the underlying block device
    mp_int_t out_value = 0;
    if (vfs->flags & FSUSER_HAVE_IOCTL) {
        // new protocol with ioctl
        static const uint8_t op_map[8] = {
            [CTRL_SYNC] = BP_IOCTL_SYNC,
            [GET_SECTOR_COUNT] = BP_IOCTL_SEC_COUNT,
            [GET_SECTOR_SIZE] = BP_IOCTL_SEC_SIZE,
            [IOCTL_INIT] = BP_IOCTL_INIT,
        };
        uint8_t bp_op = op_map[cmd & 7];
        if (bp_op != 0) {
            if (vfs->flags & FSUSER_NATIVE) {
                bool (*f)(size_t, mp_int_t*) = (void*)(uintptr_t)vfs->u.ioctl[2];
                if (!f(bp_op, (mp_int_t*) &out_value)) {
                    return RES_ERROR;
                }<commit_msg>[vfs_fat_diskio] pdrv is not a drive number since f5f4cdae89<commit_after>// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 <NAME>
//
// SPDX-License-Identifier: MIT

#include "py/mpconfig.h"
#if MICROPY_VFS && MICROPY_VFS_FAT

#include <stdint.h>
#include <stdio.h>

#include "py/mphal.h"

#include "py/runtime.h"
#include "py/binary.h"
#include "py/objarray.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "extmod/vfs_fat.h"

#if _MAX_SS == _MIN_SS
#define SECSIZE(fs) (_MIN_SS)
#else
#define SECSIZE(fs) ((fs)->ssize)
#endif

typedef void *bdev_t;
STATIC fs_user_mount_t *disk_get_device(void *bdev) {
    return (fs_user_mount_t*)bdev;
}

/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
    bdev_t pdrv,      /* Physical drive */
    BYTE *buff,        /* Data buffer to store read data */
    DWORD sector,    /* Sector address (LBA) */
    UINT count        /* Number of sectors to read (1..128) */
)
{
    fs_user_mount_t *vfs = disk_get_device(pdrv);
    if (vfs == NULL) {
        return RES_PARERR;
    }

    if (vfs->flags & FSUSER_NATIVE) {
        mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->readblocks[2];
        if (f(buff, sector, count) != 0) {
            return RES_ERROR;
        }
    } else {
        mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), buff};
        vfs->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
        vfs->readblocks[3] = MP_OBJ_FROM_PTR(&ar);
        nlr_buf_t nlr;
        if (nlr_push(&nlr) == 0) {
            mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->readblocks);
            nlr_pop();
            if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
                return RES_ERROR;
            }
        } else {
            // Exception thrown by readblocks or something it calls.
            return RES_ERROR;
        }
    }

    return RES_OK;
}

/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

DRESULT disk_write (
    bdev_t pdrv,          /* Physical drive */
    const BYTE *buff,    /* Data to be written */
    DWORD sector,        /* Sector address (LBA) */
    UINT count            /* Number of sectors to write (1..128) */
)
{
    fs_user_mount_t *vfs = disk_get_device(pdrv);
    if (vfs == NULL) {
        return RES_PARERR;
    }

    if (vfs->writeblocks[0] == MP_OBJ_NULL) {
        // read-only block device
        return RES_WRPRT;
    }

    if (vfs->flags & FSUSER_NATIVE) {
        mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->writeblocks[2];
        if (f(buff, sector, count) != 0) {
            return RES_ERROR;
        }
    } else {
        mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), (void*)buff};
        vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
        vfs->writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
        nlr_buf_t nlr;
        if (nlr_push(&nlr) == 0) {
            mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->writeblocks);
            nlr_pop();
            if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
                return RES_ERROR;
            }
        } else {
            // Exception thrown by writeblocks or something it calls.
            return RES_ERROR;
        }
    }

    return RES_OK;
}


/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
    bdev_t pdrv,      /* Physical drive */
    BYTE cmd,         /* Control code */
    void *buff        /* Buffer to send/receive control data */
)
{
    fs_user_mount_t *vfs = disk_get_device(pdrv);
    if (vfs == NULL) {
        return RES_PARERR;
    }

    // First part: call the relevant method of the underlying block device
    mp_int_t out_value = 0;
    if (vfs->flags & FSUSER_HAVE_IOCTL) {
        // new protocol with ioctl
        static const uint8_t op_map[8] = {
            [CTRL_SYNC] = BP_IOCTL_SYNC,
            [GET_SECTOR_COUNT] = BP_IOCTL_SEC_COUNT,
            [GET_SECTOR_SIZE] = BP_IOCTL_SEC_SIZE,
            [IOCTL_INIT] = BP_IOCTL_INIT,
        };
        uint8_t bp_op = op_map[cmd & 7];
        if (bp_op != 0) {
            if (vfs->flags & FSUSER_NATIVE) {
                bool (*f)(size_t, mp_int_t*) = (void*)(uintptr_t)vfs->u.ioctl[2];
                if (!f(bp_op, (mp_int_t*) &out_value)) {
                    return RES_ERROR;
                }
{'fraction_non_alphanumeric': 0.20350324739224562, 'fraction_numerical': 0.011710293249360362, 'mean_word_length': 1.5683598685873137, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 43, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6682877', 'n_tokens_mistral': 3474, 'n_tokens_neox': 3290, 'n_words': 690}