linux/drivers/mcst/mbk3/bk3.h

454 lines
14 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _BK3_H_
#define _BK3_H_
/*
* Copyright (c) 1997 by MCST.
*/
#include <linux/mcst/bk3_def.h>
#include <linux/workqueue.h> /* maks */
/*
* Уровни отладки
*/
#undef BK3_LIST_DEBUG
#undef BK3_REG_DEBUG
#undef BK3_STATUS_DEBUG
#undef BK3_POSTD_DEBUG
#undef BK3_WAIT_DEBUG
/*
* Version and release of protocol
*/
#define BK3_PROT_VER 1
#define BK3_PROT_REL 2
#define BK3_PROT_VER_SHIFT 8
#define BK3_PROT_REL_VER_MASK 0xFFFF
#define PRN_FAIL_ADDR_COUNT 5
#define my_rel_ver (BK3_PROT_REL | (BK3_PROT_VER << BK3_PROT_VER_SHIFT))
/*
* Interrupts
*/
/* Maximum valuable bit in interrupt reg */
#define BK3_MAX_INTERRUPT (1 << 11)
#define BK3_POSSIBLE_INTERRUPTS 0xFFF
#define BK3_I_CMDFREE (1 << 11) /* Command buffer free */
#define BK3_I_RPTCMD (1 << 10) /* we are asked to repeat command */
#define BK3_I_SBUSPRTY (1 << 9) /* S-bus parity control */
#define BK3_I_RCVFLT (1 << 8) /* rcvr fault */
#define BK3_I_ISCMD (1 << 7) /* There is command to read */
#define BK3_I_OPTPRTY (1 << 6) /* Optic parity failure */
#define BK3_I_TRMZERO (1 << 5) /* IO count of transmitter == 0 */
#define BK3_I_RCVZERO (1 << 4) /* IO count of reciever == 0 */
#define BK3_I_LSRFAILR (1 << 3) /* Laser failure */
#define BK3_I_CMDFLT (1 << 2) /* cmd has been read with error */
#define BK_I_PKTERR (1 << 1) /* bad type of packet */
#define BK3_I_RESET (1 << 0) /* Request to reset */
/* Interrupt mask */
#define BK3_IM_M1 (1 << 1)
#define BK3_IM_M2 (1 << 2)
#define BK3_IM_ALL (BK3_IM_M1 | BK3_IM_M2)
#define BK3_IM1_INTRS (BK3_I_RESET | BK3_I_RCVZERO | BK3_I_TRMZERO | \
BK3_I_CMDFLT | BK3_I_RPTCMD | BK3_I_CMDFREE | BK3_I_ISCMD)
#define BK3_IM2_INTRS (BK_I_PKTERR | BK3_I_LSRFAILR | BK3_I_OPTPRTY | \
BK3_I_RCVFLT | BK3_I_SBUSPRTY)
/*
* TCNT/RCNT structure
*/
#define BK3_SIZE_MASK 0x0000ffff /* Number of blocks field mask */
#define BK3_BLK_MASK 0x00070000 /* Block size field mask */
#define BK3_BLK_SHIFT 16
#define BK3_HW_BLK_SZ 64 /* Hardware minimum block size to transfer */
#define BK3_HW_BLK_SHIFT 6
#define BK3_ALIGN_MASK 0x3F /* To check alignment and padding of I/O array */
/*
* Registers definitions ( u_int = 32b == caddr_t)
*/
typedef struct { /* All regs 32b wide */
u_int dummy00;
u_int dummy04;
u_int tcwd; /* Transmitter address register 0x-x008 */
u_int dummy0c;
u_int rcwd; /* Reciever address register 0x-x010 */
u_int dummy14;
u_int mask; /* Interrupt mask register 0x-x018 */
u_int dummy1c;
u_int wctl; /* Transmit Command register 0x-x020 */
u_int dummy24;
u_int wcmd; /* Not used 0x-x028 */
u_int dummy2c;
u_int intr; /* Interrupt register 0x-x030 */
u_int dummy34;
u_int rctl; /* Recieve command register 0x-x038 */
u_int dummy3c;
u_int arst; /* Reset I/O channel register 0x-x040 */
u_int dummy44;
u_int prst; /* Raise D[0] intr for mate 0x-x048 */
u_int dummy4c;
u_int rcnt; /* Reciever counter/blksz reg 0x-x050 */
u_int dummy54;
u_int trst; /* Reset Transmitter I/O buf 0x-x058 */
u_int dummy5c;
u_int tcnt; /* Tramsmitter cntr/blksz reg 0x-x060 */
u_int dummy64;
u_int rswcnl; /* Switch channel (base == 0 | reserve == 1) 0x-x068 */
u_int dummy6c;
u_int rptcmd; /* Sends request to repeat cmd 0x-x070 */
u_int r_fifo; /* Recieve register fifo (выполнить 256 раз) 0x-x078 */
} bk3_regs_t;
#define BK3_REG_SIZE sizeof (bk3_regs_t)
/*
* Буфер
*/
typedef struct bk3_buf {
struct list_head list;
dma_addr_t address;
void *kvaddr;
int num;
} bk3_buf_t;
#define search_in_list( list1, num1) ({ \
struct list_head* tmp; \
struct list_head* ret=0; \
list_for_each(tmp, list1) { \
if( list_entry(tmp, bk3_buf_t, list)->num == num1) { \
ret = tmp;\
break;\
} \
} \
ret;})
#ifdef BK3_LIST_DEBUG
#define CHECK_LIST(list) ({\
int check = ((list)->next && (list)->prev);\
if(check == 0)\
printk("list " #list " corrupted; pid:%d %s:%d\n",\
in_interrupt()?0:current->pid, __FUNCTION__, __LINE__);\
check;})
#define list_del1(entry) do{\
DPRINTK("%-64s #%d", "list_del(" #entry ")",\
list_entry((entry), bk3_buf_t, list)->num );\
list_del(entry); } while(0)
#define list_add_tail1(new3, head3) do{\
DPRINTK("%-64s #%d", "list_add_tail("#new3 "," #head3 ")",\
list_entry((new3), bk3_buf_t, list)->num );\
list_add_tail( new3, head3); } while(0)
#define list_move_tail1(list3, head3) do { \
if( CHECK_LIST(head3) && \
CHECK_LIST(list3) && \
CHECK_LIST((list3)->prev) && \
CHECK_LIST((list3)->next)){ \
DPRINTK("%-64s #%d", "list_move_tail("#list3 "," #head3 ")", \
list_entry((list3), bk3_buf_t, list)->num); \
list_move_tail( list3, head3); \
}\
} while(0)
#else /*BK3_LIST_DEBUG*/
#define list_del1(entry) list_del(entry)
#define list_add_tail1(new3, head3) list_add_tail(new3, head3)
#define list_move_tail1(list3, head3) list_move_tail( list3, head3)
#endif /*BK3_LIST_DEBUG*/
typedef struct bk3_pool_buf {
bk3_buf_t buffer[NUM_BUF_BK3];
struct list_head free_list; /* список свободных */
struct list_head ready_list; /* список готовых на выдачу */
struct list_head busy_list; /* список занятых пользователем */
bk3_buf_t *work_buf; /* в обмене */
} bk3_pool_buf_t;
/* Private data of each instance of driver */
typedef struct {
struct of_device *op;
int instance;
struct mutex mutex;
kcondvar_t cv_wait_peer_reset;
kcondvar_t cv_reset;
kcondvar_t cv_D0_reset;
kcondvar_t cv_cmd;
kcondvar_t cv_no_read_buffers;
kcondvar_t cv_no_write_buffers;
kcondvar_t cv_msg_in;
kcondvar_t cv_msg_out;
size_t buf_size;
u_int work_mask;
volatile bk3_regs_t *bk3_regs_p; /* регистры устройства */
volatile u_int status; /* см. флаги ниже */
u_int io_modes; /* см. флаги ниже */
long reset_time; /* time to wait for real IO */
/* to complete (usexs)*/
long rd_wait_usecs; /* read must wait usecs for */
/* peer activity */
long wr_wait_usecs; /* write must wait usecs for */
/* peer activity */
u_int last_cmd;
u_int last_cmd_rpt_cnt;
u_int last_snd_cmd_tag;
int version_mbk3;
u_int type; /* MBK3_OPTIC | MBK3_ELECTRIC */
u_int channel; /* channel base == 0, reserve == 1 */
#define bk3_io_buf (bks->io_buf)
u_int burstes;
u_char prots_matched;
u_char burst; /* power of 2 of using burst */
u_char siz;
u_char rd_ready;
bk3_stat_t stat;
bk3_msg_rcv_t msg_rcv;
bk3_pool_buf_t read_pool;
bk3_pool_buf_t write_pool;
struct work_struct D0_intr_tqueue;
struct work_struct interrupt_tqueue;
dma_addr_t dma_addr; /* адрес буфера преобразованый в dma-адрес */
unsigned int *buffer; /* Буферы приёма/передачи */
raw_spinlock_t interrupt_lock;
int interrupts;
} bk3_devstate_t;
/* io_modes field flags */
#define NO_DUPLEX 0x04
#define RD_RESET_BEFORE_IO 0x08
#define WR_RESET_BEFORE_IO 0x10
/** default values of some fields **/
#define BK3_IO_MODES_DEFAULT (NO_DUPLEX | RD_RESET_BEFORE_IO | \
WR_RESET_BEFORE_IO)
#define BK3_RESET_TIME_DEFAULT (3 * 1000000)
#define BK3_RD_WAIT_DEFAULT (5 * 1000000)
#define BK3_WR_WAIT_DEFAULT (5 * 1000000)
#define BK3_NUM_RESTART_DEFAULT 0
#define BK3_NUM_RESET_TRY 5
/* status field flags */
#define PEER_IS_DEAD 0x0000001 /* мы решили что абонент в отказе */
#define READ_IS_ACTIVE 0x0000002 /* драйвер исполняет чтение */
#define WRITE_IS_ACTIVE 0x0000004 /* драйвер исполняет запись */
#define READ_IS_OVER 0x0000040 /* устройство выполнило чтение */
#define WRITE_IS_OVER 0x0000400 /* устройство выполнило запись */
#define PEER_READ_IS_OVER 0x0000800 /* aбонент выполнил чтение */
#define WE_RAISED_RESET 0x0010000 /* мы решили что устройство зависло и */
/* инициировали У0 устройства и абонента */
#define RESET_IN_PROGRESS 0x0020000 /* драйвер занимается нулением аналов */
#define PEER_RESET_DONE 0x0080000 /* выполнен У0 абонента */
#define CMD_IS_ACTIVE 0x0100000 /* команда послана абоненту и мы */
/* ждем подтверждения получения */
#define CMD_WAIT_FREE 0x0200000 /* somebody is going to send cmd */
/* and waiting for cmd free */
#define CONFIRM_PEER_RESET 0x0400000 /* peer done reset and asked us */
/* to confirm our reset */
#define RESET_NEEDED 0x0800000
#define WE_SND_MSG 0x1000000 /* мы послали СБЩ */
#define NO_RECEIVING_BUFFERS 0x0001000 /* Отсутствуют буфера на приём */
#define WE_GOT_MESSAGE 0x0002000 /* Мы получили сообщение */
#ifdef BK3_STATUS_DEBUG
#define ON_STATUS(bks,M) do{bks->status |= (M);DPRINTK("%-40s:ON bk3 %d",#M,inst);}while(0)
#define OFF_STATUS(bks,M) do{bks->status &= ~(M);DPRINTK("%-40s:OFF bk3 %d",#M,inst);}while(0)
#else /* BK3_STATUS_DEBUG */
#define ON_STATUS(bks,M) (bks->status |= (M))
#define OFF_STATUS(bks,M) (bks->status &= ~(M))
#endif /*BK3_STATUS_DEBUG*/
#define IS_ON_STATUS(bks,M) (bks->status & (M))
#define IS_OFF_STATUS(bks,M) (!(bks->status & (M)))
#define RESET_STATUS(bks) (bks->status = 0);
#define NEW_VERS(bks) (bks->version_mbk3 == 1)
#define OLD_VERS(bks) (bks->version_mbk3 == 0)
/* Registers handling */
#ifdef BK3_REG_DEBUG
#define SET_BK3_REG(bks,reg,what) do { \
bks->bk3_regs_p->reg = what; \
DPRINTK("bk3 %d SET_BK3_REG(%-40s): *%p = %08lX ", inst, #reg ", " #what, &bks->bk3_regs_p->reg, (unsigned int)what); \
} while(0)
#define GET_BK3_REG(bks, reg) ({ \
unsigned int res = bks->bk3_regs_p->reg; \
DPRINTK("bk3 %d GET_BK3_REG(%-40s): = %08lX ", inst, #reg, res); \
res;})
#else /* BK3_REG_DEBUG */
#define SET_BK3_REG(bks, reg, what) bks->bk3_regs_p->reg = what
#define GET_BK3_REG(bks, reg) bks->bk3_regs_p->reg
#endif /* BK3_REG_DEBUG */
#define SET_RRST_REG(bks,what) bks->bk3_regs_p->rcnt = what;\
drv_usecwait(50)
#define SET_TRST_REG(bks,what) bks->bk3_regs_p->tcnt = what;\
drv_usecwait(50)
#define SET_BK3_MASK(bks, VAL_MASK) { \
bks->work_mask = VAL_MASK; \
SET_BK3_REG(bks, mask, bks->work_mask); \
}
#define GET_BK3_MASK(bks) { \
bks->work_mask = GET_BK3_REG(bks, mask); \
}
#define BK3_MASK(bks) bks->work_mask
/*
* Commands
*/
/* Command structure */
#define BK3_C_ARG_MASK 0x00ffffff
#define BK3_C_CMD_MASK 0x7f000000
#define BK3_C_TAG_MASK 0x80000000
/*
* Read ask. Reciever initiates I/O.
* Argument : number of 16-byte blocks to be able to recieve
*/
#define BK3_C_RASK 0x05000000 /* у абонента готов приёмный буфер */
#define BK3_C_PEER_RESET 0x40000000 /* абонент перезагрузился */
#define BK3_C_SND_MSG 0x50000000 /* мы послали сообщение */
#define BK3_C_RCV_MSG 0x51000000 /* м*/
#define BK3_C_SND_RD 0x77000000
#define PEER_ON_SYNC_MODE 0x76000000 /* aбонент включил синхронизацию */
#define PEER_OFF_SYNC_MODE 0x78000000 /* aбонент выключил синхронизацию */
#define WE_SND_CMD 0x79300000 /* we send cmd */
/*
* TYPE MBK3
*/
#define MBK3_OPTIC 0
#define MBK3_ELECTRIC 1
/*
* WORK CHANNEL MBK3_ELECTRIC
*/
#define MBK3_CHANNEL_BASE 0
#define MBK3_CHANNEL_RESERVE 1
extern int bk3_debug;
/*
* Debug flags
*/
#define BK3_DEBUG_WAITING 0x01
#define BK3_DBG_START_TRANSFER 0x02
#define BK3_DBG_ERR_RETURNS 0x04
#define BK3_DBG_INTR 0x08
#define BK3_DBG_IOCTL 0x10
#define BK3_DBG_RESET 0x20
#define BK3_DBG_SEND_CMD 0x40
#define BK3_REG_WR 0x80
#define BK3_ATTACH 0x100
#define CE_CONT KERN_EMERG /* continuation */
#define CE_NOTE KERN_NOTICE /* notice */
#define CE_WARN KERN_WARNING /* warning */
#define CE_PANIC KERN_EMERG /* panic */
#define cmn_err(level, fmt, args...) printk(level fmt "\n", ## args)
#define gethrtime ddi_gethrtime
#define bzero(d, n) memset((d), 0, (n))
#define DPRINTK(fmt, args...) \
printk(KERN_EMERG fmt ":%-21s #%d pid: %d\n",## args, __FUNCTION__, __LINE__, current->pid)
#define dprt(fmt, args...) printk( KERN_EMERG fmt "\n", ## args)
#define TRACE(arg) ({\
int res;\
printk(KERN_EMERG __FUNCTION__ ":%d:\n" #arg,__LINE__);\
res = arg; res;})
#ifdef BK3_WAIT_DEBUG
#undef cv_timedwait
#define cv_timedwait(args...) ({\
int res;\
res = ddi_cv_timedwait(args);\
DPRINTK("cv_timedwait(%50s) == %2d bk3 %d", #args, res, inst);\
res;})
#undef cv_broadcast
#define cv_broadcast(cv) do{\
ddi_cv_broadcast(cv);\
DPRINTK("cv_broadcast(" #cv ") bk3 %d", inst);\
}while(0)
#else /*BK3_WAIT_DEBUG*/
#endif /*BK3_WAIT_DEBUG*/
#define TRANSF_CNT ((bks->siz << BK3_BLK_SHIFT) | (bks->buf_size >> (bks->burst - 1)))
void bk3_D0_intr_handle(void * arg);
int bk3_reset_device(bk3_devstate_t *bks);
irqreturn_t bk3_intr(int irq, void *arg);
irqreturn_t bk3_interrupt(int irq, void *arg);
int bk3_postd1( bk3_devstate_t *bks, u_int messg);
int bk3_init_pool_buf(bk3_devstate_t *bks);
#ifdef BK3_POSTD_DEBUG
#define bk3_postd( bks, messg) ({\
int res;DPRINTK("bk3_postd("#messg") bk3 %d", inst);\
res = bk3_postd1( bks, messg);\
res;})
#else /* BK3_POSTD_DEBUG */
#define bk3_postd bk3_postd1
#endif /* BK3_POSTD_DEBUG */
#endif /*_BK3_H_*/