📄 ccmcp.c
字号:
/*!****************************************************************************! 05.03.2002 splitted huge cmoscam.c*! FILE NAME : ccmcp.c*!*! DESCRIPTION: TBD*//****************** INCLUDE FILES SECTION ***********************************/#include <linux/module.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/string.h>#include <linux/init.h>#include <linux/config.h>#include <asm/system.h>#include <asm/svinto.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/delay.h>#include <asm/uaccess.h>#include <asm/cmoscama.h>#include "cc303.h"#include "cci2c.h"#include "ccmcp.h"#define D(x)// MCP static datastatic int MCP_shadow[MCP_W_size];static int MCP_addr;static int MCP_exists; // 0- no MCP board, 1 - MCP board present, 2 - positioner presentvoid MCP_reset(int resetOn);int MCP_init(void);void MCPSendDibit(int dibit);int MCPSendGetDibit(int dibit);int MCPSendA (int wnr, int a);void MCPWriteD (int d);int MCPReadD (void);int MCPWriteSyncTab(void);int MCPDemoSequencer(void);int MCPpresent(void) {return MCP_exists;}int positionerPresent(void) {return (MCP_exists==2);}/************************************** MCP functions *******************************************//*Will assume 16-bit words, first MCP_W_size (1024) mapped to MCP write space (with shadow), next MCP_R_size (256) - to MCP read address space*//*#define MCP_W_size 1024#define MCP_R_size 256#define MCPOtherBits 0xffa7a7ff#define MCPReset 0x00000800#define MCPNoReset 0x00105800#define MCPToggleA 0x00080000#define MCPToggleB 0x00001000#define MCPctlseq 0x00#define MCPsofttg 0x02#define MCPeackn 0x03#define MCPctlgate 0x04#define MCPwstdly 0x06#define MCPwrsmsk 0x07#define MCPwrsup 0x08#define MCPwrmons 0x09#define MCPwnom 0x0a#define MCPwdenom 0x0b#define MCPwoutw 0x0c#define MCPwinvctl 0x0d#define MCPctlsync 0x0e#define MCPwrdlys 0x10#define MCPwinv 0x40#define MCPwshared 0x80#define MCPwrsynctb 0x100#define MCPwrseq 0x200static int MCP_shadow[MCP_W_size];static int MCP_addr;*//* ----------------- low level MCP control routines ------------------ */int MCP_initmodule(void) { //- once, with loading linux int i;// Init unused shadow data as negative for (i=0;i<MCP_W_size;i++) MCP_shadow[i]= -1; MCP_reset(1); // to be sure MCP_reset(0); // reset off// check that "in control" but no "request" MCP_exists=0;// i=MCPSendA(0,0);//D(printk("MCPSendA returned %x\r\n",i));// if ((i & 3)!=1) {// D(printk("Should return -1!! %x\r\n",i));// return -1; // (not in control) or "request" - no MCP board present// } if ((MCPSendA(0,0) & 3)!=1) return -1; // (not in control) or "request" - no MCP board present// modified to include positioner board (MCP_exists==2)// MCP_exists=1; MCPSendA(0,0x80); // MCP_exists=((MCPReadD()>>9)&&7)+1;// MCP - 1, positioner - 2 if (MCPpresent()) { MCPWriteSyncTab(); // write 256x4 sync table MCPDemoSequencer(); // program some demo/reasonable sequencer parameters } return 0;}void MCP_reset(int resetOn) { if (resetOn) ccamCRAndOr (MCPOtherBits,MCPReset); else ccamCRAndOr (MCPOtherBits,MCPNoReset);}int MCP_init(void) {// make sure external reset is off if ((ccamGetCR() & CCAM_MASK(XRST)) == 0) {MCP_reset(1); MCP_reset(0); return 1;} // reset was on return 0;}void MCPSendDibit(int dibit) { // 0- "start", 1 - "0", 2 - "1", 3 - "act" if (dibit & 2) ccamCRXor (MCPToggleB); else ccamCRXor (MCPToggleA);// ccamCRXor (0); // delay needed? - it did work before if (dibit & 1) ccamCRXor (MCPToggleB); else ccamCRXor (MCPToggleA);}int MCPSendGetDibit(int dibit) { // 0- "start", 1 - "0", 2 - "1", 3 - "act" - returns dibit read int d;// int i;// int ii; d = (port_csp0_addr[1] >>2) & 1; if (dibit & 2) ccamCRXor (MCPToggleB); else ccamCRXor (MCPToggleA); ccamCRXor (0); // delay needed 1 was enough, - maybe with extra restore_flags() - now not needed anymore d |= (port_csp0_addr[1] >>1) & 2; if (dibit & 1) ccamCRXor (MCPToggleB); else ccamCRXor (MCPToggleA);// printk("%d",d); return d;}int MCPSendA (int wnr, int a) { // wnr 0 - read, 1 - write int wr,d; wr=MCP_init(); // 1 - "reset was active" MCP_addr=a; MCPSendDibit(0); // start d=MCPSendGetDibit((wnr & 1)+1); // "0" - read, "1" - write if (wr) d |=4; // mark that was reset;// later - check "in control" here... do { // at least one 0/1 should be sent MCPSendDibit((a & 1)+1); a = (a >> 1);// printf ("a= %x\r\n",a); } while (a); if (wnr) MCPSendDibit(3); // act return d;}void MCPWriteD (int d) { if ((MCP_addr >= 0) && (MCP_addr < MCP_W_size) ) { MCP_shadow[MCP_addr++]=d; while (d) { MCPSendDibit((d & 1)+1); d = (d >> 1); } MCPSendDibit(3); // act }}int MCPReadD (void) { // will always read 12 bit data int d; MCPSendDibit(3); // act d = MCPSendGetDibit(1); // while sending 0 d |= MCPSendGetDibit(1) << 2; d |= MCPSendGetDibit(1) << 4; d |= MCPSendGetDibit(1) << 6; d |= MCPSendGetDibit(1) << 8; d |= MCPSendGetDibit(1) << 10; return d;}int MCPWriteSyncTab(void) { // write 256x4 sync table int i,d; if ((MCPSendA(1,MCPwrsynctb)&& 1)==0) return -1; // (not in control) synctab for (i=0;i<256;i++) { d=-1; if ((i & 0xff) == 0xff) d = 0x0; else if ((i & 0xff) == 0x00) d = 0x8; else if ((i & 0x03) == 0x02) d = 0x1; else if ((i & 0x03) == 0x01) d = 0x9; else if ((i & 0x07) == 0x04) d = 0x2; else if ((i & 0x07) == 0x03) d = 0xa; else if ((i & 0x0f) == 0x08) d = 0x3; else if ((i & 0x0f) == 0x07) d = 0xb; else if ((i & 0x1f) == 0x10) d = 0x4; else if ((i & 0x1f) == 0x0f) d = 0xc; else if ((i & 0x3f) == 0x20) d = 0x5; else if ((i & 0x3f) == 0x1f) d = 0xd; else if ((i & 0x7f) == 0x40) d = 0x6; else if ((i & 0x7f) == 0x3f) d = 0xe; else if ((i & 0xff) == 0x80) d = 0x7; else if ((i & 0xff) == 0x7f) d = 0xf; MCPWriteD (d); } return 0;}int MCPDemoSequencer(void) { // program some demo/reasonable sequencer parameters/* 2-pulse sequence: 1-st pulse - delay 0, duration 10 2-nd pulse - delay 1000, duration 10000 if ((MCPSendA(1,MCPwrseq)&& 1)==0) return -1; // (not in control) sequencer table MCPWriteD ( 0x09); // first word - ON-OFF-NOP-NOP MCPWriteD (0x0018); // delay after first word (in 40-ns steps) up to 15 bits+ "extend" bit =16bits MCPWriteD ( 0x04); // second word - NOP-ON-NOP-NOP MCPWriteD (0x00f9); // delay after second word MCPWriteD ( 0x38); // third word - NOP-OFF-END-NOP*//* 1-pulse sequence: 1-st pulse - delay 0, duration 100,000ns*/ if ((MCPSendA(1,MCPwrseq)&& 1)==0) return -1; // (not in control) sequencer table MCPWriteD ( 0x01); // first word - ON-NOP-NOP-NOP MCPWriteD (0x09c3); // delay after first word (in 40-ns steps) up to 15 bits+ "extend" bit =16bits MCPWriteD ( 0x0e); // second word - OFF-END-NOP-NOP MCPWriteD (0x0000); // delay after second word// program sync delay mask (to prevent "glitches" - needs adjustment? MCPSendA(1,MCPwrsmsk); // MCPWriteD ( 0x2); // 4-step 0..3// write "on" support period MCPSendA(1,MCPwrsup); // MCPWriteD ( 0x1); // 4-step 0..3// set all minimal delays - updated MCPSendA(1,MCPwrdlys); // MCPWriteD ( 0x0); MCPWriteD ( 0x3); MCPWriteD ( 0x0); MCPWriteD ( 0x0); MCPWriteD ( 0x0); MCPWriteD ( 0x3); MCPWriteD ( 0x0); MCPWriteD ( 0x0);// Enable outputs to transistors MCPSendA(1,MCPctlgate+1); MCPWriteD ( 0x0);// program inverter MCPSendA(1,MCPwinv); // MCPWriteD ( 0x1800); // wait 200usec - make it 300 to reduce voltage MCPWriteD ( 0x4043); // 1-st transistor on for 3.4usec MCPWriteD ( 0x8043); // 2-nd transistor on for 3.4usec// MCPWriteD ( 0x4043); // 1-st transistor on for 3.4usec// MCPWriteD ( 0x8043); // 2-nd transistor on for 3.4usec MCPWriteD ( 0xc000); // restart sequence// turn it on// MCPSendA(1,MCPwinvctl); //// MCPWriteD ( 4); // always on (to resetting after trigger)// program PWM MCPSendA (1,MCPwnom); // MCPWriteD ( 0x2000); // MCPwnom (0.4..0.7)under thershold MCPWriteD ( 0xe000); // MCPwdenom 8000/c000/e000/f000/f8000 MCPWriteD ( 0x00f0); // MCPwoutw// that's all for now...// put something in shared... MCPSendA(1,MCPwshared); MCPWriteD ( 0x01); MCPWriteD ( 0x02); MCPWriteD ( 0x04); MCPWriteD ( 0x08); MCPWriteD ( 0x10); MCPWriteD ( 0x20); MCPWriteD ( 0x40); MCPWriteD ( 0x80); MCPWriteD ( 0x100); D(printk("Default data to MCP written\r\n")); return 0; }/* --------- MCP I/O functions ---------------------*/int MCP_open(struct inode *inode, struct file *filp) { // set filesize// int p = MINOR(inode->i_rdev); if (!MCPpresent()) return -ENXIO; // no MCP board detected during Linux startup// enable if not in use or is reset inode->i_size= (MCP_W_size + MCP_R_size) << 1; return 0;}ssize_t MCP_read(struct file * file, char * buf, size_t count, loff_t *off) { unsigned long p,left; unsigned long bp=0;// unsigned short buf16[MCP_W_size + MCP_R_size]; unsigned short buf16[MCP_W_size + MCP_R_size +1]; //not fixed yet?// printk("MCP_read: buf address=%x count=%x\r\n",(long) buf, (long) count); p = (file->f_pos) >> 1; count=count >> 1;// printk ("p= %x\r\n",p);// printk ("Just return and do nothing more\r\n");// return count<<1; if(p >= (MCP_W_size + MCP_R_size)) return -EFAULT; if( (p + count) > (MCP_W_size + MCP_R_size)) { /* truncate count */ count = (MCP_W_size + MCP_R_size) - p; } left=count;/* is it reading some shadow data? */// printk ("p=%x, left=%x, bp=%x, sizeof(buf16)=%lx\r\n",p, left, bp, sizeof(buf16));// return count<<1; while ((p<MCP_W_size) && left--) buf16[bp++]=(unsigned short) (MCP_shadow[p++]);// printk ("buf16[0]= %x buf16[1]= %x\r\n",buf16[0],buf16[1]);// return count<<1;/* is it reading some real data? */ if (++left) { if ((MCPSendA(0, p - MCP_W_size) && 1)==0) return -EIO; // Set start address (read), check "in control" while (left--) buf16[bp++] = MCPReadD (); }// printk ("buf16[0]= %x buf16[1]= %x\r\n",buf16[0],buf16[1]); count=count<<1; if ((p=copy_to_user(buf,buf16,count))) return -EFAULT; file->f_pos += count;// printk("MCP_read returned %x\r\n", count); return count;}ssize_t MCP_write(struct file * file, const char * buf, size_t count, loff_t *off) { unsigned long p,left; unsigned long bp=0; unsigned short buf16[MCP_W_size];// printk("MCP_write: buf address=%x count=%x\r\n",(long) buf, (long) count); p = (file->f_pos) >> 1; count=count>>1;// printk ("p= %x\r\n",p);// printk ("buf[0]= %x buf[1]= %x buf[2]= %x buf[3]= %x\r\n",buf[0],buf[1],buf[2],buf[3]); if(p >= MCP_W_size) return -EFAULT; if( (p + count) > MCP_W_size ) { /* truncate count */ count = MCP_W_size - p; } left=count; if (copy_from_user(buf16,buf,count<<1)) return -EFAULT;// printk ("buf16[0]= %x buf16[1]= %x\r\n",buf16[0],buf16[1]); if ((MCPSendA(1, p) && 1)==0) return -EFAULT; // Set start address (write), check "in control" while (left--) MCPWriteD (buf16[bp++]); count=count<<1; file->f_pos += count;// printk ("MCP_write returned %x\r\n", count);// printk ("New file->f_pos = %lx\r\n",file->f_pos); return count;}loff_t MCP_lseek(struct file * file, loff_t offset, int orig){/* * orig 0: position from begning of data * orig 1: relative from current position * orig 2: position from last data */ unsigned long fs; fs=(MCP_W_size + MCP_R_size) << 1;// printk("MCP_lseek - fs= %x\r\n", fs); switch (orig) { case 0: file->f_pos = offset; break; case 1: file->f_pos += offset; break; case 2: file->f_pos = fs - offset; break; default: return -EINVAL; } /* truncate position */ if (file->f_pos < 0) { file->f_pos = 0; return(-EOVERFLOW); } if (file->f_pos >= fs) { file->f_pos = fs - 1; return(-EOVERFLOW); }// printk("MCP_lseek returned %x\r\n", (int) file->f_pos); return ( file->f_pos );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -