/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h" /* * * mcc.c * * This is the driver for the Multi-Channel Communications Controller * of the MPC8260. This version is constructed for the EST SBC8260 to * handle data from an interface to an offboard T1 framer. The driver * supports MCC2 + TDM A:2 (channel 128) which is connected to the * external interface. * * Neville Chandler * Lucent Technologies - Bell Labs * March 2001 * */ #define PKT_LEN 40#define MPC82XX_INIT_DELAY 0x10000 #define HPIC 0xFC000000#define HPIA 0xFC000010#define HPID_A 0xFC000020#define HPID 0xFC000030 #include "mcc2.h" static ssize_t mcc2_read( struct file *, char *, size_t, loff_t * );static ssize_t mcc2_write( struct file *, const char *, size_t, loff_t *);static loff_t mcc2_lseek( struct file *, loff_t, int );static int mcc2_release( struct inode *, struct file * );static ssize_t mcc2_ioctl( struct inode *, struct file *, unsigned int, unsigned long );//static ssize_t mcc2_ioctl( struct inode *, struct file *, unsigned int, char * ); void MPC82xxCpmInit( void );void PortInit( void );void PortSelectPin( unsigned short ); void InitMemAlloc( void );void HeapCreate( U32, U32, U32, U32, char *);void HeapCreate( U32, U32, U32, U32, char *);void *HeapSearchMem( U32, U32);void *HeapAllocMem( U32, U32);void HeapFreeMem( U32, void *); void InitLinkedList( void );boolean DwCreateList( ListDB * );void *DwMalloc( U32 );void DwFree( U32, void * ); void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) extern int ppc_spurious_interrupts;extern int ppc_second_irq;extern struct irqaction *ppc_irq_action[NR_IRQS];extern unsigned int ppc_local_bh_count[NR_CPUS];extern unsigned int ppc_local_irq_count[NR_CPUS];extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS];extern atomic_t ppc_n_lost_interrupts; //static void disp_led( unsigned char ); void Mcc2Init( void );void MccDisable( unsigned char );void MccEnable( unsigned char, unsigned char, unsigned char );void MccRiscCmd( unsigned char, dwv_RISC_OPCODE, unsigned char );boolean MccTest( void );int MccTxBuffer( unsigned char, unsigned char, char *, unsigned short, unsigned short );extern U32 PpcDisable( void );extern void PpcMsrRestore( U32 ); static int mcc2_major = MCC_MAJOR; static BOOLEAN insertBD_T( BD_PFIFO *, BD_P );static BOOLEAN removBD_T( BD_PFIFO *, BD_P * );BOOLEAN empty(volatile register FIFO *);int insert( FIFO *, char * );int remove( FIFO *, char ** );void AppInit( void ); #define physaddr(ADDR) (0x60020000 | ((ADDR) << 23) | (2 << 18)) mcc_iorw_t mcc_iorw; #if 0typedef struct mcc_io { unsigned int cmd; unsigned int address; unsigned int *buf; int ind; int nbytes; siramctl_t SiRam; cpmux_t CpMux; mcc_t Mcc_T; iop8260_t Io_Ports;} mcc_iorw_t;#endif static voidioctl_parm( unsigned int loop_mode ){ /* Setup the SIMODE Register */ Si2Regs->SiAmr = SIxMR_SAD_BANK0_FIRST_HALF | /* SADx */ loop_mode | /* SDMx */ SIxMR_NO_BIT_RX_SYNC_DELAY | /* RFSDx */ SIxMR_DSC_CH_DATA_CLK_EQU | /* DSCx */ SIxMR_CRT_SPEPARATE_PINS | /* CRTx */ SIxMR_SLx_NORMAL_OPERATION | /* SLx */ SIxMR_CE_TX_RISING_RX_FALLING | /* CEx */ SIxMR_FE_FALLING_EDGE | /* FEx */ SIxMR_GM_GCI_SCIT_MODE | /* GMx */ SIxMR_NO_BIT_TX_SYNC_DELAY; /* TFSDx */} #if 0static voiddisp_led( unsigned char byte ){ //int i; *leds = byte; //for(i=0; i<1000; i++); }#endif static ssize_tmcc2_ioctl( struct inode *inode, struct file *file, unsigned int ioctl_cmd, // IOCTL number unsigned long param )// char *param ) // IOCTL parameter{ static unsigned char mode; char cp, *cptr; void *vptr; unsigned long *lptr; int i, j; unsigned int ld; unsigned long lng; volatile immap_t *Mmap; cptr = (char *)param; mode = (unsigned char)*cptr; Mmap = ((volatile immap_t *)IMAP_ADDR); switch(ioctl_cmd) { case IOCTL_SET_MODE: //mode = (unsigned char)*param; mode = ((mcc_iorw_t *)param)->cmd; switch( mode ) { case NORMAL_OPERATION: /* Setup the SIMODE Register */ D( printk("mcc2_ioctl: ioctl set NORMAL_OPERATION mode\n"); ) ioctl_parm( (unsigned int)SIxMR_SDM_NORMAL_OPERATION ); /* SDMx */ break; case AUTOMATIC_ECHO: /* Setup the SIMODE Register */ D( printk("mcc2_ioctl: ioctl set AUTOMATIC_ECHO mode\n"); ) ioctl_parm( (unsigned int)SIxMR_SDM_AUTOMATIC_ECHO ); /* SDMx */ break; case INTERNAL_LOOPBACK: /* Setup the SIMODE Register */ D( printk("mcc2_ioctl: ioctl set INTERNAL_LOOPBACK mode\n"); ) ioctl_parm( (unsigned int)SIxMR_SDM_INTERNAL_LOOPBACK ); /* SDMx */ break; case LOOPBACK_CONTROL: /* Setup the SIMODE Register */ D( printk("mcc2_ioctl: ioctl set LOOPBACK_CONTROL mode\n"); ) ioctl_parm( (unsigned int)SIxMR_SDM_LOOPBACK_CONTROL ); /* SDMx */ break; default: printk("mcc2_ioctl: Error, unrecognized ioctl parameter, device operation unchanged.\n"); break; } break; case IOCTL_RWX_MODE: mode = ((mcc_iorw_t *)param)->cmd; switch(mode) { case HPI_RD: lng = (long)(((mcc_iorw_t *)param)->address); lptr = ((unsigned long *)lng); vptr = (void *)lptr; if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)vptr, (((mcc_iorw_t *)param)->nbytes))) { printk("mcc2_ioctl: Failed during read from hpi.\n"); return -EFAULT; } break; case HPI_WR: lng = (long)(((mcc_iorw_t *)param)->address); lptr = ((unsigned long *)lng); vptr = (void *)lptr; if (copy_from_user( (void *)vptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) { printk("mcc2_ioctl: Failed during write to hpi\n"); return -EFAULT; } break; case FPGA_RD: lng = (long)(((mcc_iorw_t *)param)->address); lptr = ((unsigned long *)lng); vptr = (void *)lptr; if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)vptr, (((mcc_iorw_t *)param)->nbytes))) { printk("mcc2_ioctl: Failed during read from FPGA.\n"); return -EFAULT; } break; case FPGA_WR: lng = (long)(((mcc_iorw_t *)param)->address); lptr = ((unsigned long *)lng); vptr = (void *)lptr; if (copy_from_user( (void *)vptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) { printk("mcc2_ioctl: Failed during write to FPGA\n"); return -EFAULT; } break; case MEM_MODR: cptr = (char *)Mmap; cptr += ((mcc_iorw_t *)param)->address; if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)cptr, (((mcc_iorw_t *)param)->nbytes))) { printk("mcc2_ioctl: Failed during read of read-modify memory\n"); return -EFAULT; } break; case MEM_MODW: cptr = (char *)Mmap; cptr += ((mcc_iorw_t *)param)->address; if (copy_from_user( (void *)cptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) { printk("mcc2_ioctl: Failed during modify of read-modify memory\n"); return -EFAULT; } break; case IO_PORTS: break; case SI_RAM_CTL1: break; case SI_RAM_CTL2: if (copy_to_user( (void *)param, (siramctl_t *)&(Mmap->im_siramctl2), sizeof(siramctl_t))) { printk("mcc2_ioctl: Failed to copy SI_RAM_CTL2 struct\n"); return -EFAULT; } break; default: break; } break; default: //if (copy_to_user((void *)param, &mode, sizeof(mode))) printk("We are at the end ...\n"); return -EFAULT; break; } break; default: break; } return 0;} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static ssize_tmcc2_open( struct inode *inode, struct file *file ){ MOD_INC_USE_COUNT; return 0;} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static intmcc2_release( struct inode *inode, struct file *file ){ MOD_DEC_USE_COUNT; return 0;} #ifndef MODULE ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// longmcc2_init( long mem_start, long mem_end ){ if ((mcc2_major = register_chrdev(MCC_MAJOR, MCC_NAME, &mcc2_fops))) printk("mcc2_init: Unable to get major for mcc2 device %d\n", MCC_MAJOR); else { //MPC82xxSiuInit(); MPC82xxCpmInit(); } return mem_start;} #else
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
/*
*
* mcc.c
*
* This is the driver for the Multi-Channel Communications Controller
* of the MPC8260. This version is constructed for the EST SBC8260 to
* handle data from an interface to an offboard T1 framer. The driver
* supports MCC2 + TDM A:2 (channel 128) which is connected to the
* external interface.
*
* Neville Chandler
* Lucent Technologies - Bell Labs
* March 2001
*
*/
#define PKT_LEN 40
#define MPC82XX_INIT_DELAY 0x10000
#define HPIC 0xFC000000
#define HPIA 0xFC000010
#define HPID_A 0xFC000020
#define HPID 0xFC000030
#include "mcc2.h"
static ssize_t mcc2_read( struct file *, char *, size_t, loff_t * );
static ssize_t mcc2_write( struct file *, const char *, size_t, loff_t *);
static loff_t mcc2_lseek( struct file *, loff_t, int );
static int mcc2_release( struct inode *, struct file * );
static ssize_t mcc2_ioctl( struct inode *, struct file *, unsigned int, unsigned long );
//static ssize_t mcc2_ioctl( struct inode *, struct file *, unsigned int, char * );
void MPC82xxCpmInit( void );
void PortInit( void );
void PortSelectPin( unsigned short );
void InitMemAlloc( void );
void HeapCreate( U32, U32, U32, U32, char *);
void HeapCreate( U32, U32, U32, U32, char *);
void *HeapSearchMem( U32, U32);
void *HeapAllocMem( U32, U32);
void HeapFreeMem( U32, void *);
void InitLinkedList( void );
boolean DwCreateList( ListDB * );
void *DwMalloc( U32 );
void DwFree( U32, void * );
void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
extern int ppc_spurious_interrupts;
extern int ppc_second_irq;
extern struct irqaction *ppc_irq_action[NR_IRQS];
extern unsigned int ppc_local_bh_count[NR_CPUS];
extern unsigned int ppc_local_irq_count[NR_CPUS];
extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
extern atomic_t ppc_n_lost_interrupts;
//static void disp_led( unsigned char );
void Mcc2Init( void );
void MccDisable( unsigned char );
void MccEnable( unsigned char, unsigned char, unsigned char );
void MccRiscCmd( unsigned char, dwv_RISC_OPCODE, unsigned char );
boolean MccTest( void );
int MccTxBuffer( unsigned char, unsigned char, char *, unsigned short, unsigned short );
extern U32 PpcDisable( void );
extern void PpcMsrRestore( U32 );
static int mcc2_major = MCC_MAJOR;
static BOOLEAN insertBD_T( BD_PFIFO *, BD_P );
static BOOLEAN removBD_T( BD_PFIFO *, BD_P * );
BOOLEAN empty(volatile register FIFO *);
int insert( FIFO *, char * );
int remove( FIFO *, char ** );
void AppInit( void );
#define physaddr(ADDR) (0x60020000 | ((ADDR) << 23) | (2 << 18))
mcc_iorw_t mcc_iorw;
#if 0
typedef struct mcc_io {
unsigned int cmd;
unsigned int address;
unsigned int *buf;
int ind;
int nbytes;
siramctl_t SiRam;
cpmux_t CpMux;
mcc_t Mcc_T;
iop8260_t Io_Ports;
} mcc_iorw_t;
#endif
static void
ioctl_parm( unsigned int loop_mode )
{
/* Setup the SIMODE Register */
Si2Regs->SiAmr = SIxMR_SAD_BANK0_FIRST_HALF | /* SADx */
loop_mode | /* SDMx */
SIxMR_NO_BIT_RX_SYNC_DELAY | /* RFSDx */
SIxMR_DSC_CH_DATA_CLK_EQU | /* DSCx */
SIxMR_CRT_SPEPARATE_PINS | /* CRTx */
SIxMR_SLx_NORMAL_OPERATION | /* SLx */
SIxMR_CE_TX_RISING_RX_FALLING | /* CEx */
SIxMR_FE_FALLING_EDGE | /* FEx */
SIxMR_GM_GCI_SCIT_MODE | /* GMx */
SIxMR_NO_BIT_TX_SYNC_DELAY; /* TFSDx */
}
#if 0
static void
disp_led( unsigned char byte )
{
//int i;
*leds = byte;
//for(i=0; i<1000; i++);
}
#endif
static ssize_t
mcc2_ioctl( struct inode *inode, struct file *file,
unsigned int ioctl_cmd, // IOCTL number
unsigned long param )
// char *param ) // IOCTL parameter
{
static unsigned char mode;
char cp, *cptr;
void *vptr;
unsigned long *lptr;
int i, j;
unsigned int ld;
unsigned long lng;
volatile immap_t *Mmap;
cptr = (char *)param;
mode = (unsigned char)*cptr;
Mmap = ((volatile immap_t *)IMAP_ADDR);
switch(ioctl_cmd)
{
case IOCTL_SET_MODE:
//mode = (unsigned char)*param;
mode = ((mcc_iorw_t *)param)->cmd;
switch( mode )
{
case NORMAL_OPERATION:
/* Setup the SIMODE Register */
D( printk("mcc2_ioctl: ioctl set NORMAL_OPERATION mode\n"); )
ioctl_parm( (unsigned int)SIxMR_SDM_NORMAL_OPERATION ); /* SDMx */
break;
case AUTOMATIC_ECHO:
/* Setup the SIMODE Register */
D( printk("mcc2_ioctl: ioctl set AUTOMATIC_ECHO mode\n"); )
ioctl_parm( (unsigned int)SIxMR_SDM_AUTOMATIC_ECHO ); /* SDMx */
break;
case INTERNAL_LOOPBACK:
/* Setup the SIMODE Register */
D( printk("mcc2_ioctl: ioctl set INTERNAL_LOOPBACK mode\n"); )
ioctl_parm( (unsigned int)SIxMR_SDM_INTERNAL_LOOPBACK ); /* SDMx */
break;
case LOOPBACK_CONTROL:
/* Setup the SIMODE Register */
D( printk("mcc2_ioctl: ioctl set LOOPBACK_CONTROL mode\n"); )
ioctl_parm( (unsigned int)SIxMR_SDM_LOOPBACK_CONTROL ); /* SDMx */
break;
default:
printk("mcc2_ioctl: Error, unrecognized ioctl parameter, device operation unchanged.\n");
break;
}
break;
case IOCTL_RWX_MODE:
mode = ((mcc_iorw_t *)param)->cmd;
switch(mode)
{
case HPI_RD:
lng = (long)(((mcc_iorw_t *)param)->address);
lptr = ((unsigned long *)lng);
vptr = (void *)lptr;
if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)vptr, (((mcc_iorw_t *)param)->nbytes))) {
printk("mcc2_ioctl: Failed during read from hpi.\n");
return -EFAULT;
}
break;
case HPI_WR:
lng = (long)(((mcc_iorw_t *)param)->address);
lptr = ((unsigned long *)lng);
vptr = (void *)lptr;
if (copy_from_user( (void *)vptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
printk("mcc2_ioctl: Failed during write to hpi\n");
return -EFAULT;
}
break;
case FPGA_RD:
lng = (long)(((mcc_iorw_t *)param)->address);
lptr = ((unsigned long *)lng);
vptr = (void *)lptr;
if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)vptr, (((mcc_iorw_t *)param)->nbytes))) {
printk("mcc2_ioctl: Failed during read from FPGA.\n");
return -EFAULT;
}
break;
case FPGA_WR:
lng = (long)(((mcc_iorw_t *)param)->address);
lptr = ((unsigned long *)lng);
vptr = (void *)lptr;
if (copy_from_user( (void *)vptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
printk("mcc2_ioctl: Failed during write to FPGA\n");
return -EFAULT;
}
break;
case MEM_MODR:
cptr = (char *)Mmap;
cptr += ((mcc_iorw_t *)param)->address;
if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)cptr, (((mcc_iorw_t *)param)->nbytes))) {
printk("mcc2_ioctl: Failed during read of read-modify memory\n");
return -EFAULT;
}
break;
case MEM_MODW:
cptr = (char *)Mmap;
cptr += ((mcc_iorw_t *)param)->address;
if (copy_from_user( (void *)cptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
printk("mcc2_ioctl: Failed during modify of read-modify memory\n");
return -EFAULT;
}
break;
case IO_PORTS:
break;
case SI_RAM_CTL1:
break;
case SI_RAM_CTL2:
if (copy_to_user( (void *)param, (siramctl_t *)&(Mmap->im_siramctl2), sizeof(siramctl_t))) {
printk("mcc2_ioctl: Failed to copy SI_RAM_CTL2 struct\n");
return -EFAULT;
}
break;
default:
break;
}
break;
default:
//if (copy_to_user((void *)param, &mode, sizeof(mode)))
printk("We are at the end ...\n");
return -EFAULT;
break;
}
break;
default:
break;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
static ssize_t
mcc2_open( struct inode *inode, struct file *file )
{
MOD_INC_USE_COUNT;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
static int
mcc2_release( struct inode *inode, struct file *file )
{
MOD_DEC_USE_COUNT;
return 0;
}
#ifndef MODULE
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
long
mcc2_init( long mem_start, long mem_end )
{
if ((mcc2_major = register_chrdev(MCC_MAJOR, MCC_NAME, &mcc2_fops)))
printk("mcc2_init: Unable to get major for mcc2 device %d\n", MCC_MAJOR);
else {
//MPC82xxSiuInit();
MPC82xxCpmInit();
}
return mem_start;
}
#else