Commit 72aebf77 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Add doxygen documentation

parent 5850bdf6
......@@ -159,7 +159,7 @@ static irqreturn_t elphel_irq_handler(int irq, void * dev_instance)
return handled;
}
/** Command queue processing tasklet */
void process_queue(unsigned long data)
{
unsigned long irq_flags;
......@@ -474,6 +474,7 @@ static int map_vectors(struct elphel_ahci_priv *dpriv)
return index;
}
/** Split buffer pointed by vector @e vect into several smaller buffer. Each part will be less than #MAX_PRDT_LEN bytes */
static inline void vectsplit(struct fvec *vect, struct fvec *parts, size_t *n_elem)
{
size_t len;
......@@ -489,6 +490,8 @@ static inline void vectsplit(struct fvec *vect, struct fvec *parts, size_t *n_el
*n_elem = *n_elem + 1;
}
}
/** Copy @e len bytes from buffer pointed by @e src vector to buffer pointed by @e dest vector */
static inline void vectcpy(struct fvec *dest, void *src, size_t len)
{
unsigned char *d = (unsigned char *)dest->iov_base;
......@@ -496,6 +499,8 @@ static inline void vectcpy(struct fvec *dest, void *src, size_t len)
memcpy(d + dest->iov_len, src, len);
dest->iov_len += len;
}
/** Move vector forward by @e len bytes decreasing its length */
static inline void vectmov(struct fvec *vec, size_t len)
{
if (vec->iov_len >= len) {
......@@ -504,12 +509,16 @@ static inline void vectmov(struct fvec *vec, size_t len)
vec->iov_len -= len;
}
}
/** Shrink vector length by @len bytes */
static inline void vectshrink(struct fvec *vec, size_t len)
{
if (vec->iov_len >= len) {
vec->iov_len -= len;
}
}
/** Return the number of bytes needed to align @e data_len to @e align_len boundary */
static inline size_t align_bytes_num(size_t data_len, size_t align_len)
{
size_t rem = data_len % align_len;
......@@ -518,12 +527,15 @@ static inline size_t align_bytes_num(size_t data_len, size_t align_len)
else
return align_len - rem;
}
/** This helper function is used to position a pointer @e offset bytes from the end
* of a buffer. DMA handle is not updated intentionally as it is not needed during copying */
static inline unsigned char *vectrpos(struct fvec *vec, size_t offset)
{
return (unsigned char *)vec->iov_base + (vec->iov_len - offset);
}
/** Align current frame to disk sector boundary and each individual buffer to #ALIGNMENT_SIZE boundary */
static void align_frame(struct elphel_ahci_priv *dpriv)
{
unsigned char *src;
......@@ -784,6 +796,7 @@ static void init_vectors(struct frame_buffers *buffs, struct fvec *chunks)
chunks[CHUNK_COMMON].iov_len = 0;
}
/** Allocate memory for frame buffers */
static int init_buffers(struct device *dev, struct frame_buffers *buffs)
{
int mult;
......@@ -846,6 +859,7 @@ err_header:
return -ENOMEM;
}
/** Free allocated frame buffers */
static void deinit_buffers(struct device *dev, struct frame_buffers *buffs)
{
kfree(buffs->jpheader_buff.iov_base);
......@@ -856,6 +870,7 @@ static void deinit_buffers(struct device *dev, struct frame_buffers *buffs)
kfree(buffs->rem_buff.iov_base);
}
/** Discard buffer pointers which makes the command slot marked as empty */
static inline void reset_chunks(struct fvec *vects, int all)
{
int i;
......@@ -869,6 +884,7 @@ static inline void reset_chunks(struct fvec *vects, int all)
}
}
/** Get driver private structure from pointer to device structure */
static inline struct elphel_ahci_priv *dev_get_dpriv(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
......@@ -916,6 +932,7 @@ static int process_cmd(struct elphel_ahci_priv *dpriv)
return dpriv->sg_elems;
}
/** Finish currently running command */
static void finish_cmd(struct elphel_ahci_priv *dpriv)
{
int all;
......@@ -935,7 +952,7 @@ static void finish_cmd(struct elphel_ahci_priv *dpriv)
dpriv->flags &= ~PROC_CMD;
}
/** Fill free space in REM buffer with 0 and save the reaming data chunk */
/** Fill free space in REM buffer with 0 and save the remaining data chunk */
static void finish_rec(struct elphel_ahci_priv *dpriv)
{
size_t stuff_len;
......@@ -959,6 +976,7 @@ static void finish_rec(struct elphel_ahci_priv *dpriv)
process_cmd(dpriv);
}
/** Move a pointer to free command slot one step forward */
int move_tail(struct elphel_ahci_priv *dpriv)
{
size_t slot = (dpriv->tail_ptr + 1) % MAX_CMD_SLOTS;
......@@ -974,6 +992,7 @@ int move_tail(struct elphel_ahci_priv *dpriv)
}
}
/** Move a pointer to next ready command */
int move_head(struct elphel_ahci_priv *dpriv)
{
size_t use_tail;
......@@ -997,6 +1016,7 @@ int move_head(struct elphel_ahci_priv *dpriv)
}
/** Check if command queue is empty */
int is_cmdq_empty(const struct elphel_ahci_priv *dpriv)
{
size_t use_tail;
......@@ -1013,6 +1033,7 @@ int is_cmdq_empty(const struct elphel_ahci_priv *dpriv)
return 1;
}
/** Get command slot before the last one filled in */
size_t get_prev_slot(const struct elphel_ahci_priv *dpriv)
{
size_t slot;
......@@ -1028,10 +1049,11 @@ size_t get_prev_slot(const struct elphel_ahci_priv *dpriv)
return slot;
}
static ssize_t rawdev_write(struct device *dev, ///<
struct device_attribute *attr, ///<
const char *buff, ///<
size_t buff_sz) ///<
/** Get and enqueue new command */
static ssize_t rawdev_write(struct device *dev, ///< device structure associated with the driver
struct device_attribute *attr, ///< interface for device attributes
const char *buff, ///< buffer containing new command
size_t buff_sz) ///< the size of the command buffer
{
ssize_t rcvd = 0;
bool proceed = false;
......@@ -1249,6 +1271,7 @@ static void elphel_cmd_issue(struct ata_port *ap,///< device port for which the
writel(1 << slot_num, port_mmio + PORT_CMD_ISSUE);
}
/** Defer system command if internal command queue is not empty */
static int elphel_qc_defer(struct ata_queued_cmd *qc)
{
int ret;
......@@ -1272,6 +1295,7 @@ static int elphel_qc_defer(struct ata_queued_cmd *qc)
return ret;
}
/** Return the stating position of disk buffer (in LBA) */
static ssize_t lba_start_read(struct device *dev, struct device_attribute *attr, char *buff)
{
struct ata_host *host = dev_get_drvdata(dev);
......@@ -1281,6 +1305,7 @@ static ssize_t lba_start_read(struct device *dev, struct device_attribute *attr,
return snprintf(buff, 20, "%llu\n", dpriv->lba_ptr.lba_start);
}
/** Set the starting position of disk buffer (in LBA) */
static ssize_t lba_start_write(struct device *dev, struct device_attribute *attr, const char *buff, size_t buff_sz)
{
struct ata_host *host = dev_get_drvdata(dev);
......@@ -1296,6 +1321,7 @@ static ssize_t lba_start_write(struct device *dev, struct device_attribute *attr
return buff_sz;
}
/** Return the ending position of disk buffer (in LBA) */
static ssize_t lba_end_read(struct device *dev, struct device_attribute *attr, char *buff)
{
struct ata_host *host = dev_get_drvdata(dev);
......@@ -1305,6 +1331,7 @@ static ssize_t lba_end_read(struct device *dev, struct device_attribute *attr, c
return snprintf(buff, 20, "%llu\n", dpriv->lba_ptr.lba_end);
}
/** Set the ending position of disk buffer (in LBA) */
static ssize_t lba_end_write(struct device *dev, struct device_attribute *attr, const char *buff, size_t buff_sz)
{
struct ata_host *host = dev_get_drvdata(dev);
......@@ -1320,6 +1347,7 @@ static ssize_t lba_end_write(struct device *dev, struct device_attribute *attr,
return buff_sz;
}
/** Return the current position of write pointer (in LBA) */
static ssize_t lba_current_read(struct device *dev, struct device_attribute *attr, char *buff)
{
struct ata_host *host = dev_get_drvdata(dev);
......@@ -1329,6 +1357,7 @@ static ssize_t lba_current_read(struct device *dev, struct device_attribute *att
return snprintf(buff, 20, "%llu\n", dpriv->lba_ptr.lba_write);
}
/** Set the current position of write pointer (in LBA) */
static ssize_t lba_current_write(struct device *dev, struct device_attribute *attr, const char *buff, size_t buff_sz)
{
struct ata_host *host = dev_get_drvdata(dev);
......@@ -1400,6 +1429,7 @@ static struct platform_driver ahci_elphel_driver = {
};
module_platform_driver(ahci_elphel_driver);
/** Debug function, checks frame alignment */
static int check_chunks(struct fvec *vects)
{
int i;
......@@ -1423,6 +1453,7 @@ static int check_chunks(struct fvec *vects)
return ret;
}
/** Debug function, prints the S/G list of current command */
static void dump_sg_list(const struct device *dev, const struct fvec *sgl, size_t elems)
{
int i;
......
......@@ -25,56 +25,36 @@
#ifndef _AHCI_ELPHEL_EXT
#define _AHCI_ELPHEL_EXT
/** Flag indicating that IRQ corresponds to internal command and should not be
* processed in ahci_handle_port_interrupt */
#define IRQ_SIMPLE (1 << 0)
/** Flag indicating that disk is currently busy. Access to this flag should be protected by
* spin locks to prevent race conditions */
#define DISK_BUSY (1 << 1)
/** Processing driver's internal command is in progress */
#define PROC_CMD (1 << 2)
/** Flag indicating that the remaining chunk of data will be recorded */
#define LAST_BLOCK (1 << 3)
/** Flag indicating that recording should be stopped right after the last chunk of data
* is written */
#define DELAYED_FINISH (1 << 4)
#define LOCK_TAIL (1 << 5)
/** The length of a command FIS in double words */
#define CMD_FIS_LEN 5
/** This is used to get 28-bit address from 64-bit value */
#define ADDR_MASK_28_BIT ((u64)0xfffffff)
/** A maximum of length of 4MB may exist for PRDT entry */
#define MAX_PRDT_LEN 0x3fffff
/** An array or JPEG frame chunks contains pointers to JPEG leading marker,
* JPEG header, Exif data if present, stuffing bytes chunk which aligns
* the frame size to disk sector boundary, JPEG data which
* can be split into two chunks, their corresponding align buffers, JPEG
* trailing marker, and pointer to a buffer containing the remainder of a
* frame. Ten chunks of data in total.
* @todo Fix description */
#define MAX_DATA_CHUNKS 9
/** Default port number */
#define DEFAULT_PORT_NUM 0
/** Align buffers length to this amount of bytes */
#define ALIGNMENT_SIZE 32
/** Maximum number of entries in PRDT table. HW max is 64k.
* Set this value the same as AHCI_MAX_SG in ahci.h */
#define MAX_SGL_LEN 168
/** Maximum number of frames which will be processed at the same time */
#define MAX_CMD_SLOTS 4
/** Maximum number of sectors for READ DMA or WRITE DMA commands */
#define MAX_LBA_COUNT 0xff
/** Maximum number of sectors for READ DMA EXT or WRITE_DMA EXT commands */
#define MAX_LBA_COUNT_EXT 0xffff
/** Physical disk block size */
#define PHY_BLOCK_SIZE 512
#define JPEG_MARKER_LEN 2
/** The size in bytes of JPEG marker length field */
#define JPEG_SIZE_LEN 2
/** Include REM buffer to total size calculation */
#define INCLUDE_REM 1
/** Exclude REM buffer from total size calculation */
#define EXCLUDE_REM 0
#define IRQ_SIMPLE (1 << 0) ///< Flag indicating that IRQ corresponds to internal command and should not be
///< processed in ahci_handle_port_interrupt
#define DISK_BUSY (1 << 1) ///< Flag indicating that disk is currently busy. Access to this flag should be protected by
///< spin locks to prevent race conditions
#define PROC_CMD (1 << 2) ///< Processing driver's internal command is in progress
#define LAST_BLOCK (1 << 3) ///< Flag indicating that the remaining chunk of data will be recorded
#define DELAYED_FINISH (1 << 4) ///< Flag indicating that recording should be stopped right after the last chunk of data is written
#define LOCK_TAIL (1 << 5) ///< Lock current command slot until all data buffers are assigned and the frame is aligned
#define CMD_FIS_LEN 5 ///< The length of a command FIS in double words
#define ADDR_MASK_28_BIT ((u64)0xfffffff)///< This is used to get 28-bit address from 64-bit value
#define MAX_PRDT_LEN 0x3fffff ///< A maximum of length of 4MB may exist for PRDT entry
#define MAX_DATA_CHUNKS 9 ///< An array or JPEG frame chunks contains pointers to JPEG leading marker,
///< JPEG header, Exif data if present, stuffing bytes chunk which aligns
///< the frame size to disk sector boundary, JPEG data which
///< can be split into two chunks, align buffers, JPEG
///< trailing marker, and pointer to a buffer containing the remainder of a
///< frame. Nine chunks of data in total.
#define DEFAULT_PORT_NUM 0 ///< Default port number
#define ALIGNMENT_SIZE 32 ///< Align buffers length to this amount of bytes
#define MAX_SGL_LEN 168 ///< Maximum number of entries in PRDT table. HW max is 64k.
///< Set this value the same as AHCI_MAX_SG in ahci.h
#define MAX_CMD_SLOTS 4 ///< Maximum number of frames which will be processed at the same time
#define MAX_LBA_COUNT 0xff ///< Maximum number of sectors for READ DMA or WRITE DMA commands
#define MAX_LBA_COUNT_EXT 0xffff ///< Maximum number of sectors for READ DMA EXT or WRITE_DMA EXT commands
#define PHY_BLOCK_SIZE 512 ///< Physical disk block size
#define JPEG_MARKER_LEN 2 ///< The size in bytes of JPEG marker
#define JPEG_SIZE_LEN 2 ///< The size in bytes of JPEG marker length field
#define INCLUDE_REM 1 ///< Include REM buffer to total size calculation
#define EXCLUDE_REM 0 ///< Exclude REM buffer from total size calculation
/** This structure holds raw device buffer pointers */
struct drv_pointers {
......@@ -84,38 +64,43 @@ struct drv_pointers {
uint16_t wr_count; ///< the number of LBA to write next time
};
/** Container structure for frame buffers */
struct frame_buffers {
struct fvec exif_buff;
struct fvec jpheader_buff;
struct fvec trailer_buff;
struct fvec common_buff;
struct fvec exif_buff; ///< Exif buffer
struct fvec jpheader_buff; ///< JPEG header buffer
struct fvec trailer_buff; ///< buffer for trailing marker
struct fvec common_buff; ///< common buffer where other parts are combined
struct fvec rem_buff; ///< remainder from previous frame
};
/** Symbolic names for slots in buffer pointers. Buffer alignment function relies on the order of these names, so
* new names can be added but the overall order should not be changed */
enum {
CHUNK_LEADER,
CHUNK_EXIF,
CHUNK_HEADER,
CHUNK_COMMON,
CHUNK_DATA_0,
CHUNK_DATA_1,
CHUNK_TRAILER,
CHUNK_ALIGN,
CHUNK_REM
CHUNK_LEADER, ///< pointer to JPEG leading marker
CHUNK_EXIF, ///< pointer to Exif buffer
CHUNK_HEADER, ///< pointer to JPEG header data excluding leading marker
CHUNK_COMMON, ///< pointer to common buffer
CHUNK_DATA_0, ///< pointer to JPEG data
CHUNK_DATA_1, ///< pointer to the second half of JPEG data if a frame crosses circbuf boundary
CHUNK_TRAILER, ///< pointer to JPEG trailing marker
CHUNK_ALIGN, ///< pointer to buffer where the second part of JPEG data should be aligned
CHUNK_REM ///< pointer to buffer containing the remainder of current frame. It will be recorded during next transaction
};
/** AHCI driver private structure */
struct elphel_ahci_priv {
u32 clb_offs;
u32 fb_offs;
u32 base_addr;
u32 flags;
int curr_cmd;
size_t max_data_sz;
struct drv_pointers lba_ptr;
struct frame_buffers fbuffs[MAX_CMD_SLOTS];
struct fvec data_chunks[MAX_CMD_SLOTS][MAX_DATA_CHUNKS];
struct fvec sgl[MAX_SGL_LEN];
int sg_elems;
u32 clb_offs; ///< CLB offset, received from device tree
u32 fb_offs; ///< FB offset, received from device tree
u32 base_addr; ///< controller base address
u32 flags; ///< flags indicating current state of the driver. Access to #DISK_BUSY flags is protected with
///< a spin lock
int curr_cmd; ///< current ATA command
size_t max_data_sz; ///< maximum data size (in bytes) which can be processed with current ATA command
struct drv_pointers lba_ptr; ///< disk buffer pointers
struct frame_buffers fbuffs[MAX_CMD_SLOTS]; ///< a set of buffers for each command
struct fvec data_chunks[MAX_CMD_SLOTS][MAX_DATA_CHUNKS];///< a set of vectors pointing to data buffers for each command
struct fvec sgl[MAX_SGL_LEN]; ///< an array of data buffers mapped for next transaction
int sg_elems; ///< the number of S/G vectors mapped for next transaction in @e sgl array
int curr_data_chunk; ///< index of a data chunk used during last transaction
size_t curr_data_offset; ///< offset of the last byte in a data chunk pointed to by @e curr_data_chunk
size_t head_ptr; ///< pointer to command slot which will be written next
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment