/******************************************************************************* | |
* Copyright (C) 2014, ZTE Corporation. | |
* | |
* File Name: drvs_dma.h | |
* File Mark: | |
* Description: | |
* Others: | |
* Version: v0.1 | |
* Author: limeifeng | |
* Date: 2014-03-03 | |
* History 1: | |
* Date: | |
* Version: | |
* Author: | |
* Modification: | |
* History 2: | |
********************************************************************************/ | |
#ifndef _DRVS_DMA_H | |
#define _DRVS_DMA_H | |
/**************************************************************************** | |
* Include files | |
****************************************************************************/ | |
/**************************************************************************** | |
* Macros | |
****************************************************************************/ | |
#if defined (_CHIP_ZX297520V3) | |
#define DMAC0_CH_NUM 23 /*dmac0¿ØÖÆÆ÷µÄͨµÀÊý*/ | |
#elif defined (_CHIP_ZX297520V2) | |
#define DMAC0_CH_NUM 19 /*dmac0¿ØÖÆÆ÷µÄͨµÀÊý*/ | |
#endif | |
//#define DMAC1_CH_NUM 9 /*dmac1¿ØÖÆÆ÷µÄͨµÀÊý*/ | |
#define DMAC_CH_MAX DMAC0_CH_NUM | |
/**************************************************************************** | |
* Type | |
****************************************************************************/ | |
typedef enum _T_ZDrv_DmaId | |
{ | |
DMAC0=0, | |
DMAC_NUM | |
}T_ZDrv_DmaId; | |
/*ÊÇ·ñΪ×èÈû·½Ê½´«Êä*/ | |
typedef enum _T_ZDrvDma_IsBlock | |
{ | |
DMA_NOT_BLOCK=0, | |
DMA_BLOCK=1, | |
}T_ZDrvDma_IsBlock; | |
#if defined (_CHIP_ZX297520V3) | |
typedef enum | |
{ | |
/*DMAC0ͨµÀºÅ¶¨Òå*/ | |
DMAC0_CH_UART0_TX = 0, | |
DMAC0_CH_UART0_RX, | |
DMAC0_CH_UART1_TX, | |
DMAC0_CH_UART1_RX, /* or DMAC0_CH_HASH_RX*/ | |
DMAC0_CH_SSP0_TX, | |
DMAC0_CH_SSP0_RX, | |
DMAC0_CH_GPRS0, | |
DMAC0_CH_GPRS1, | |
DMAC0_CH_USIM, | |
DMAC0_CH_I2S0_TX, /*or DMAC0_CH_TDM_TX*/ | |
DMAC0_CH_I2S0_RX0, /*or DMAC0_CH_TDM_RX*/ | |
DMAC0_CH_I2S1_TX, /*or DMAC0_CH_TDM_TX*/ | |
DMAC0_CH_I2S1_RX0, /*or DMAC0_CH_TDM_RX*/ | |
DMAC0_CH_SPIFC0_TX, | |
DMAC0_CH_SPIFC0_RX, | |
DMAC0_CH_SSP1_TX, | |
DMAC0_CH_SSP1_RX, | |
DMAC0_CH_UART2_TX, /*or DMAC0_CH_I2S0_RX1*/ | |
DMAC0_CH_UART2_RX, /*or DMAC0_CH_I2S1_RX1*/ | |
DMAC0_CH_EMBMS, | |
DMAC0_CH_USIM1, | |
DMAC0_CH_M2M_TX, | |
DMAC0_CH_M2M_RX, | |
DMAC0_CH_MEMORY, /*ÓÃÓÚÉêÇëDMAC0ÉϵĿÕÏÐͨµÀ*/ | |
}T_Dma_Peripheral_Id; | |
#elif defined (_CHIP_ZX297520V2) | |
typedef enum | |
{ | |
/*DMAC0ͨµÀºÅ¶¨Òå*/ | |
DMAC0_CH_UART0_TX = 0, | |
DMAC0_CH_UART0_RX, | |
DMAC0_CH_UART1_TX, | |
DMAC0_CH_UART1_RX, | |
DMAC0_CH_SSP0_TX, | |
DMAC0_CH_SSP0_RX, | |
DMAC0_CH_GPRS0, | |
DMAC0_CH_GPRS1, | |
DMAC0_CH_USIM, | |
DMAC0_CH_I2S0_TX, | |
DMAC0_CH_I2S0_RX, | |
DMAC0_CH_I2S1_TX, | |
DMAC0_CH_I2S1_RX, | |
DMAC0_CH_SPIFC0_TX, | |
DMAC0_CH_SPIFC0_RX, | |
DMAC0_CH_SSP1_TX, | |
DMAC0_CH_SSP1_RX, | |
DMAC0_CH_UART2_TX, | |
DMAC0_CH_UART2_RX, | |
DMAC0_CH_MEMORY, /*ÓÃÓÚÉêÇëDMAC0ÉϵĿÕÏÐͨµÀ*/ | |
}T_Dma_Peripheral_Id; | |
#endif | |
/*----DMA Transfer Control Set------*/ | |
typedef enum | |
{ | |
DMA_DISABLE = 0, /*disable DMA transmission*/ | |
DMA_ENABLE = 1, /*enable DMA transmission*/ | |
DMA_ENABLE_ALL | |
}T_DMA_ENABLE; | |
/*----DMA Request mode set------*/ | |
typedef enum | |
{ | |
DMA_PERIPHERAL_REQ = 0, /*peripheral request*/ | |
DMA_SOFT_REQ = 1, /*soft request for single transfer*/ | |
DMA_REQ_MOD_ALL | |
}T_DMA_REQ_MOD; | |
/*----DMA Source or Dest address mode------*/ | |
typedef enum | |
{ | |
DMA_ADDRMOD_RAM = 0, /*RAM mode, address will increase when transmission*/ | |
DMA_ADDRMOD_FIFO = 1, /*FIFO mode, address will not change during transmission*/ | |
DMA_ADDRMOD_ALL | |
}T_DMA_ADDR_MOD; | |
/*----DMA IRQ Mode------*/ | |
typedef enum | |
{ | |
DMA_ALL_IRQ_DISABLE = 0, /*½ûÄÜËùÓÐÖжÏ*/ | |
DMA_TC_IRQ_ENABLE = 1, /*Íê³ÉÖжÏʹÄÜ*/ | |
DMA_ERR_IRQ_ENABLE =2, /*´«ÊäºÍÅäÖôíÎóÖжÏʹÄÜ*/ | |
DMA_ALL_IRQ_ENABLE = 3, /*ʹÄÜËùÓÐÖжÏ*/ | |
DMA_IRQMOD_ALL | |
}T_DMA_IRQ_MOD; | |
/*----DMA Burst Size------*/ | |
typedef enum | |
{ | |
DMA_BURST_SIZE_8BIT = 0, | |
DMA_BURST_SIZE_16BIT = 1, | |
DMA_BURST_SIZE_32BIT = 2, | |
DMA_BURST_SIZE_64BIT = 3, | |
DMA_BURST_SIZE_128BIT = 4, | |
DMA_BURST_SIZE_ALL | |
} | |
T_DMA_BURST_SIZE; | |
/*----DMA Burst Len------*/ | |
typedef enum | |
{ | |
DMA_BURST_LEN_1 = 0, /* 1 tranfer in each burst*/ | |
DMA_BURST_LEN_2 , /* 2 tranfers in each burst*/ | |
DMA_BURST_LEN_3 , /* 3 tranfers in each burst*/ | |
DMA_BURST_LEN_4 , /* 4 tranfers in each burst*/ | |
DMA_BURST_LEN_5 , /* 5 tranfers in each burst*/ | |
DMA_BURST_LEN_6 , /* 6 tranfers in each burst*/ | |
DMA_BURST_LEN_7 , /* 7 tranfers in each burst*/ | |
DMA_BURST_LEN_8 , /* 8 tranfers in each burst*/ | |
DMA_BURST_LEN_9 , /* 9 tranfers in each burst*/ | |
DMA_BURST_LEN_10, /* 10 tranfers in each burst*/ | |
DMA_BURST_LEN_11 , /* 11 tranfers in each burst*/ | |
DMA_BURST_LEN_12 , /* 12 tranfers in each burst*/ | |
DMA_BURST_LEN_13 , /* 13 tranfers in each burst*/ | |
DMA_BURST_LEN_14 , /* 14 tranfers in each burst*/ | |
DMA_BURST_LEN_15 , /* 15 tranfers in each burst*/ | |
DMA_BURST_LEN_16 , /* 16 tranfers in each burst*/ | |
DMA_BURST_LEN_ALL | |
} | |
T_DMA_BURST_LEN; | |
/*----DMA Int Select------*/ | |
typedef enum | |
{ | |
DMA_INT_TO_PS, | |
DMA_INT_TO_PHY, | |
DMA_INT_TO_M0, | |
DMA_INT_SEL_ALL | |
}T_DMA_INT_SEL; | |
typedef enum | |
{ | |
DMA_INT_ERR, /*transmission error*/ | |
DMA_INT_END, /*transmission done*/ | |
MAX_DMA_INT | |
} T_ZDrvDma_IntStatus; /*T_HalDma_IntStatus;*/ | |
/*----DMA Control reg para------*/ | |
typedef struct _T_DMA_CONTROL | |
{ | |
T_DMA_REQ_MOD BurstReqMod; /*DMA Request mode*/ | |
T_DMA_ADDR_MOD SrcMod; /*DMA Source address mode*/ | |
T_DMA_ADDR_MOD DestMod; /*DMA Destination address mode*/ | |
T_DMA_IRQ_MOD IrqMod; | |
T_DMA_BURST_SIZE SrcBurstSize; /*DMA burst size£¬ÍâÉèÄÚ´æ¼ä´«ÊäʱҪÂú×ãCountÊÇ | |
max(SrcBurstSize,DestBurstSize)µÄÕûÊý±¶*/ | |
T_DMA_BURST_LEN SrcBurstLen; | |
T_DMA_BURST_SIZE DestBurstSize; /*DMA burst size£¬ÍâÉèÄÚ´æ¼ä´«ÊäʱҪÂú×ãCountÊÇ | |
max(SrcBurstSize,DestBurstSize)µÄÕûÊý±¶*/ | |
T_DMA_INT_SEL IntSel; /* select witch core will deal with the dma int*/ | |
} T_DMA_CONTROL; | |
/*----DMA channel para ------*/ | |
typedef struct | |
{ | |
UINT32 SrcAddr; /*DMA source address*/ | |
UINT32 DestAddr; /*DMA Destination address*/ | |
UINT16 Count; /*һά´«Êäʱ´«ÊäµÄÊý¾Ý×Ü×Ö½ÚÊý*/ | |
UINT16 YCount; /*һά´«ÊäʱΪ0*/ | |
UINT16 ZCount; /*һά´«ÊäʱΪ0*/ | |
UINT16 SrcYstep; /*һά´«ÊäʱΪ0*/ | |
UINT16 SrcZstep; /*һά´«ÊäʱΪ0*/ | |
UINT16 DestYstep; /*һά´«ÊäʱΪ0*/ | |
UINT16 DestZstep; /*һά´«ÊäʱΪ0*/ | |
UINT32 LLI; /*Á´±íµØÖ·£¬²»ÊÇÁ´±í´«Êäʱһ¶¨ÒªÉèΪ0*/ | |
T_DMA_CONTROL CONTROL; | |
}T_ZDrvDma_ChannelDef; | |
typedef struct | |
{ | |
UINT32 SrcAddr; /*DMA source address*/ | |
UINT32 DestAddr; /*DMA Destination address*/ | |
UINT16 Count; /*һά´«Êäʱ´«ÊäµÄÊý¾Ý×Ü×Ö½ÚÊý*/ | |
}T_ZDrvDma_EmbmsChannelDef; | |
/*----DMA Group------*/ | |
typedef enum | |
{ | |
DMA_GROUP_1234_5678 = 0, | |
DMA_GROUP_2341_5678 , | |
DMA_GROUP_3412_5678 , | |
DMA_GROUP_4123_5678 , | |
DMA_GROUP_1234_6785 , | |
DMA_GROUP_2341_6785 , | |
DMA_GROUP_3412_6785 , | |
DMA_GROUP_4123_6785 , | |
DMA_GROUP_1234_7856 , | |
DMA_GROUP_2341_7856 , | |
DMA_GROUP_3412_7856 , | |
DMA_GROUP_4123_7856 , | |
DMA_GROUP_1234_8567 , | |
DMA_GROUP_2341_8567 , | |
DMA_GROUP_3412_8567 , | |
DMA_GROUP_4123_8567 , | |
DMA_GROUP_5678_1234 , | |
DMA_GROUP_5678_2341 , | |
DMA_GROUP_5678_3412 , | |
DMA_GROUP_5678_4123 , | |
DMA_GROUP_6785_1234 , | |
DMA_GROUP_6785_2341 , | |
DMA_GROUP_6785_3412 , | |
DMA_GROUP_6785_4123 , | |
DMA_GROUP_7856_1234 , | |
DMA_GROUP_7856_2341 , | |
DMA_GROUP_7856_3412 , | |
DMA_GROUP_7856_4123 , | |
DMA_GROUP_8567_1234 , | |
DMA_GROUP_8567_2341 , | |
DMA_GROUP_8567_3412 , | |
DMA_GROUP_8567_4123 , | |
DMA_GROUP_ALL | |
} | |
T_DMA_GROUP_ORDER; | |
/*----DMA Group Arbi Mode------*/ | |
typedef enum | |
{ | |
DMA_MODE_RR = 0, /*ÂÖѯ·½Ê½,DMA·Ö×éÎÞЧ*/ | |
DMA_MODE_8PRI, /*ÿËĸöͨµÀÒ»×飬°´ÇëÇóÏß´ÓµÍλµ½¸ßλ·Ö³É8×é | |
Àý:1234_5678,1>2>3>4>5>6>7>8*/ | |
DMA_MODE_4PRI, /*Àý:1234_5678,1>2>3>4,5>6>7>8,1234Óë5678×é¼äͬÓÅÏȼ¶*/ | |
DMA_MODE_2PRI, /*Àý:1234_5678,1234>5678*/ | |
DMA_MODE_ALL | |
} | |
T_DMA_GROUP_MODE; | |
/*----T_DMA_STATUS------*/ | |
typedef enum | |
{ | |
DMA_TRANSFER_DONE = 0, | |
DMA_CFG_ERROR, | |
DMA_NOT_DONE, | |
DMA_STATUS_ALL | |
} | |
T_DMA_STATUS; | |
typedef VOID (*zDrvDma_CallbackFunc)(T_ZDrvDma_IntStatus); | |
/**************************************************************************** | |
* Global Function Prototypes | |
****************************************************************************/ | |
/******************************************************************************* | |
* Function: zDrvDma_SetPriority | |
* Description: | |
* Parameters:dmacID :DMAC0¡¢DMAC1 | |
* groupOrder:ÓÅÏȼ¶·Ö×é˳Ðò1 2 3 4 5 6 7 8 ÿËĸöͨµÀÒ»×飬°´ÇëÇóÏߴӵ͵½¸ß | |
·ÖΪ8×é¡£ | |
groupMode:ÓÅÏȼ¶·Ö×éģʽ£¬ DMA_MODE_RR : ÂÖѯ·½Ê½£¬²»·Ö×飬ÎÞÓÅÏȼ¶²î±ð | |
DMA_MODE_8PRI:ÿËĸöͨµÀÒ»×飬°´ÇëÇóÏß´ÓµÍλµ½¸ßλ·Ö³É8×é | |
Àý:1234_5678,1>2>3>4>5>6>7>8 | |
DMA_MODE_4PRI: Àý:1234_5678,1>2>3>4,5>6>7>8,1234Óë5678×é¼äͬÓÅÏȼ¶ | |
DMA_MODE_2PRI: Àý:1234_5678,1234>5678 | |
* Input: | |
* | |
* Output: | |
* | |
* Returns: | |
* | |
* Others: | |
********************************************************************************/ | |
SINT32 zDrvDma_SetPriority(T_ZDrv_DmaId dmacID, T_DMA_GROUP_ORDER groupOrder, T_DMA_GROUP_MODE groupMode); | |
/******************************************************************************* | |
* Function: zDrvDma_Initiate | |
* Description: reset dma controller,the reset line will hold 2ms | |
* Parameters: | |
* Input: | |
* | |
* Output: | |
* | |
* Returns: | |
* | |
* Others: | |
********************************************************************************/ | |
SINT32 zDrvDma_Initiate(VOID); | |
/******************************************************************************* | |
* Function: zDrvDma_AllocChannel | |
* Description: | |
for users, they don't konw with channel chould be used to do the transfer. | |
so they should first call this function to get a free channel id; | |
afer dma transfer is over , zDrvDma_DeAllocChannel should be called to release the | |
channedl resoure | |
* Parameters: | |
* Input: | |
* peripheralID: peripheral request line defined by structure T_Dma_Peripheral_Id | |
* Output: | |
* | |
* Returns: | |
* | |
* Others: | |
********************************************************************************/ | |
SINT32 zDrvDma_AllocChannel(T_Dma_Peripheral_Id peripheralID); | |
/************************************************************************** | |
* Function: zDrvDma_ConfigChannel | |
* Description: | |
* Parameters: | |
* Input: | |
* channelID: the return value from zDrvDma_AllocChannel | |
* tChanPar:parameter of channel | |
* CallBack:when dma transfer is over, isr will call cbk | |
* Output: None | |
* Returns: | |
* T_ZDrvDma_Ret | |
* Others: | |
* 1. ÔÚÔ´»òÄ¿µÄµØÖ·Ö»ÒªÓÐÒ»¶ËÓй̶¨µØÖ·£¬¼´T_DMA_ADDR_MODΪ | |
* DMA_ADDRMOD_FIFOʱ£¬tChanPar µÄCount ±ØÐëÊǽϴóburstsize | |
* µÄÕûÊý±¶!!! | |
* 2.ÔÚ BurstReqMod = DMA_PERIPHERAL_REQʱ£¬ÐèÒªÌØ±ð×¢Òâ:Èç¹û¶ÔÓ¦ÍâÉèÖ»ÄܲúÉú | |
* burstÇëÇó¶øÃ»ÓÐsingleÇëÇóÊä³ö¹¦ÄÜ£¬ÄÇôtChanPar µÄCount ±ØÐëÊÇburstsize*burstlen | |
* µÄÕûÊý±¶!!! | |
* 3.SrcAddrºÍDestAddrÒªÇóΪburstsizeµÄÕûÊý±¶£¬¼´ÒÔburstsizeΪµ¥Î»µØÖ·¶ÔÆë¡£ | |
* 4.tChanPar µÄ²ÎÊýCount µÄȡֵҪСÓÚµÈÓÚ64K-1×Ö½Ú£¬Countµ¥Î»Îª×Ö½Ú!! | |
**************************************************************************/ | |
SINT32 zDrvDma_ConfigChannel(UINT32 channelID,T_ZDrvDma_ChannelDef tChanPar); | |
/************************************************************************** | |
* Function: zDrvDma_StartChannel | |
* Description: | |
* Parameters: | |
* Input: | |
* channelID: the return value from zDrvDma_AllocChannel | |
* CallBack:if not null, when dma transfer is over, 'callback' will be called in the dma isr | |
isBlock: if set true, the process will be suspended until the dma transfer is done | |
* Output: None | |
* Returns: | |
* T_ZDrvDma_Ret | |
* Others: None | |
**************************************************************************/ | |
SINT32 zDrvDma_StartChannel(UINT32 channelID, zDrvDma_CallbackFunc CallBack, T_ZDrvDma_IsBlock isBlock); | |
/******************************************************************************* | |
* Function: zDrvDma_DeAllocChannel | |
* Description:ÊÍ·ÅÒѾÉêÇë³É¹¦µÄDMA ͨµÀ£¬ÈçûÓÐÉêÇë³É¹¦Ôò²»ÄÜÊÍ·Å | |
* Ò»°ãÔÚ¸ÃDMAͨµÀÅäÖ÷µ»Ø´íÎóÐÅÏ¢»òʹÓÃÕß²»ÔÙʹÓøÃDMAͨµÀ | |
* ʱµ÷Óô˺¯Êý¡£ | |
* Parameters: | |
* Input: | |
* | |
* Output: | |
* | |
* Returns: | |
* | |
* Others:ÈôΪ×èÈû´«Êä(zDrvDma_StartChannelµÄisBlock²ÎÊýΪTRUE) | |
* ÏàͬͨµÀµÄzDrvDma_DeAllocChannel±ØÐëÔÚºÍzDrvDma_StartChannelͬһ¸öÏ̱߳»µ÷Óà | |
* ·ñÔò¿ÉÄܻᵼÖµ÷ÓÃzDrvDma_StartChannelµÄÏß³ÌÒòdmaδÀ´Íê³ÉÖж϶øÓÀÔ¶ÏÝËÀ | |
********************************************************************************/ | |
SINT32 zDrvDma_DeAllocChannel(UINT32 channelID); | |
/************************************************************************** | |
* Function: zDrvDma_GetTransferNumber | |
* Description:»ñÈ¡ucChannel ´ú±íµÄͨµÀµÄÊý¾ÝµÄ´«ÊäÊ£Óà´óС | |
* Parameters: | |
* Input: zDrvDma_AllocChannel µÄ·µ»ØÖµ:¸ß16λ:dma¿ØÖÆÆ÷µÍ16λ:ͨµÀºÅ(0~15) | |
* Output: None | |
* Output: None | |
* Returns: | |
* None | |
* Others: None | |
**************************************************************************/ | |
UINT32 zDrvDma_GetTransferNumber(UINT32 ucChannel); | |
/************************************************************************** | |
* Function: zDrvDma_DisableChannel | |
* Description: Ç¿ÖÆÍ£Ö¹ucChannelËùָͨµÀºÅµÄ´«Êä¡£ | |
* Í£Ö¹ºóÈôÏëÖØÐÂÆô¶¯´«Ê䣬ÐèÖØÐÂÅäÖòÎÊý¡£ | |
* Parameters: | |
* Input: | |
* ucChannel: zDrvDma_AllocChannelµÄ·µ»ØÖµ¡£ | |
* Output: None | |
* Returns: | |
* | |
* Others: ´Ëº¯ÊýÍ£Ö¹DMA´«Ê䣬²»ÊÇÔÝÍ£¡£ | |
**************************************************************************/ | |
SINT32 zDrvDma_DisableChannel(UINT32 ucChannel); | |
/************************************************************************** | |
* Function: zDrvDma_GetStatus | |
* Description:Ê¡µçרÓýӿڣ¬ÓÃÓÚ²»²úÉúÖжϵÄDMA´«Êä | |
* Parameters: | |
* Input: zDrvDma_AllocChannel µÄ·µ»ØÖµ:¸ß16λ:dma¿ØÖÆÆ÷µÍ16λ:ͨµÀºÅ(0~15) | |
* Output: None | |
* Returns: | |
* DMA_TRANSFER_DONE: channelID 's dma transfer has done. | |
* DMA_CFG_ERROR:something wrong with channelID's dma configuration | |
* DMA_NOT_DONE: if dma not done and dma config has no problem,return this value. | |
* | |
* Others: None | |
**************************************************************************/ | |
T_DMA_STATUS zDrvDma_GetStatus(UINT32 channelID); | |
/************************************************************************** | |
* Function: zDrvDma_ConfigLLI | |
* Description:Ê¡µçרÓýӿڣ¬ÓÃÓÚ²»²úÉúÖжϵÄDMA´«Êä | |
* Parameters: | |
* Input: channelID:zDrvDma_AllocChannel µÄ·µ»ØÖµ:¸ß16λ:dma¿ØÖÆÆ÷µÍ16λ:ͨµÀºÅ(0~15) | |
channelaPara:DMA²ÎÊýÊý×é | |
LLIParaCnt:Êý×éÔªËØ¸öÊý:×î´óΪ32 | |
isLoop:TRUE--Ñ»·´«ËÍ FALSE--normal | |
* Output: None | |
* Returns: | |
* | |
* Others: None | |
**************************************************************************/ | |
SINT32 zDrvDma_ConfigLLI(UINT32 channelID,T_ZDrvDma_ChannelDef channelaPara[], UINT32 LLIParaCnt, BOOL isLoop); | |
/******************************************************************************* | |
* Function: zDrvDma_Mem2MemForEmbms | |
* Description: | |
this function implement a mem to mem dma transfer function, | |
note: the memery involved must be set to non-cacheable | |
* Parameters: | |
* Input: | |
* embmsChannel: | |
LLIParaCnt:number of embmsChannel[] | |
CallBack: callback func | |
* Output: | |
* | |
* Returns: | |
* | |
* Others: | |
********************************************************************************/ | |
SINT32 zDrvDma_Mem2MemForEmbms(T_ZDrvDma_EmbmsChannelDef embmsChannel[], UINT32 LLIParaCnt, zDrvDma_CallbackFunc CallBack); | |
#endif/*_DRVS_DMA_H*/ | |