patch-2.3.42 linux/arch/sparc/ap1000/tnet.c

Next file: linux/arch/sparc/ap1000/util.c
Previous file: linux/arch/sparc/ap1000/timer.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.41/linux/arch/sparc/ap1000/tnet.c linux/arch/sparc/ap1000/tnet.c
@@ -1,708 +0,0 @@
-  /*
-   * Copyright 1996 The Australian National University.
-   * Copyright 1996 Fujitsu Laboratories Limited
-   * 
-   * This software may be distributed under the terms of the Gnu
-   * Public License version 2 or later
-  */
-/* routines to control the AP1000 Tnet interface */
-
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/aplib.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <asm/pgtable.h>
-#include <asm/pgtsrmmu.h>
-#include <stdarg.h>
-#include <linux/skbuff.h>
-
-
-/* message types for system messages */
-#define TNET_IP         0
-#define TNET_IP_SMALL   1
-#define TNET_RPC        2
-
-static struct {
-	int errors;
-	int alloc_errors;
-	int bytes_received;
-	int bytes_sent;
-	int packets_received;
-	int packets_sent;
-	int small_packets_received;
-	int small_packets_sent;
-} tnet_stats;
-
-extern int cap_cid0;
-extern int cap_ncel0;
-static u_long xy_global_head;
-
-extern unsigned _ncel, _ncelx, _ncely, _cid, _cidx, _cidy;
-
-extern struct ringbuf_struct system_ringbuf;
-extern u_long system_read_ptr;
-
-u_long system_recv_flag = 0;
-static u_long system_recv_count = 0;
-
-int *tnet_rel_cid_table;
-
-static int dummy=1;
-
-#define TNET_IP_THRESHOLD 100
-
-void tnet_check_completion(void);
-static void reschedule(void);
-static u_long tnet_add_completion(void (*fn)(int a1,...), 
-				  int a1,int a2);
-static void tnet_info(void);
-
-static struct {
-  int shift;
-  void (*fn)(void);
-} iports[4] = {
-  {MC_INTP_0_SH,tnet_check_completion},
-  {MC_INTP_1_SH,reschedule},
-  {MC_INTP_2_SH,NULL},
-  {MC_INTP_3_SH,NULL}};
-
-static inline int rel_cid(unsigned dst)
-{  
-	unsigned dstx, dsty;
-	unsigned dx,dy;
-
-	if (dst == _cid) return 0;
-
-	dstx = dst % _ncelx;
-	dsty = dst / _ncelx;
-	if (dstx >= _cidx)
-		dx = dstx - _cidx;
-	else
-		dx = (_ncelx - _cidx) + dstx;
-	
-	if (dsty >= _cidy)
-		dy = dsty - _cidy;
-	else
-		dy = (_ncely - _cidy) + dsty;
-	
-	return (dx<<8) | dy;
-}
-
-#define SAVE_PID() \
-  unsigned long flags; \
-  int saved_pid; \
-  save_flags(flags); cli(); \
-  saved_pid = MSC_IN(MSC_PID); \
-  MSC_OUT(MSC_PID,SYSTEM_CONTEXT);
-
-#define RESTORE_PID() \
-  MSC_OUT(MSC_PID,saved_pid); \
-  restore_flags(flags);
-
-
-void ap_put(int dest_cell,u_long local_addr,int size,
-	    u_long remote_addr,u_long dest_flag,u_long local_flag)
-{
-  volatile u_long *entry;
-  SAVE_PID();
-    
-  entry = (volatile u_long *)MSC_PUT_QUEUE_S;
-
-  *entry = tnet_rel_cid_table[dest_cell];
-  *entry = ((size+3) >> 2); 
-  *entry = (u_long)remote_addr;
-  *entry = 0;
-  *entry = (u_long)dest_flag;
-  *entry = (u_long)local_flag;
-  *entry = (u_long)local_addr;
-  *entry = 0;
-  RESTORE_PID();
-}
-
-/* remote_addr is physical 
-   local address is virtual 
-   both flags are virtual */
-void ap_phys_put(int dest_cell,u_long local_addr,int size,
-		 u_long remote_addr,u_long dest_flag,u_long local_flag)
-{
-  volatile u_long *entry;
-  SAVE_PID();
-
-  entry = (volatile u_long *)MSC_CPUT_QUEUE_S;
-
-  *entry = tnet_rel_cid_table[dest_cell];
-  *entry = ((size+3) >> 2); 
-  *entry = (u_long)remote_addr;
-  *entry = 0;
-  *entry = (u_long)dest_flag;
-  *entry = (u_long)local_flag;
-  *entry = (u_long)local_addr;
-  *entry = 0;
-  RESTORE_PID();
-}
-
-
-/* broadcast put - yeah! */
-void ap_bput(u_long local_addr,int size,
-	     u_long remote_addr,u_long dest_flag,u_long local_flag)
-{
-  volatile u_long *entry = (volatile u_long *)MSC_XYG_QUEUE_S;
-  SAVE_PID();
-
-  *entry = xy_global_head;
-  *entry = ((size+3) >> 2);
-  *entry = (u_long)remote_addr;
-  *entry = 0;
-  *entry = (u_long)dest_flag;
-  *entry = (u_long)local_flag;
-  *entry = (u_long)local_addr;
-  *entry = 0;
-  RESTORE_PID();
-}
-
-
-/* remote_addr is physical */
-void ap_phys_bput(u_long local_addr,int size,
-		  u_long remote_addr,u_long dest_flag,u_long local_flag)
-{
-  volatile u_long *entry = (volatile u_long *)MSC_CXYG_QUEUE_S;
-  SAVE_PID();
-
-  *entry = xy_global_head;
-  *entry = ((size+3) >> 2);
-  *entry = (u_long)remote_addr;
-  *entry = 0;
-  *entry = (u_long)dest_flag;
-  *entry = (u_long)local_flag;
-  *entry = (u_long)local_addr;
-  *entry = 0;
-  RESTORE_PID();
-}
-
-
-
-void ap_get(int dest_cell,u_long local_addr,int size,
-	    u_long remote_addr,u_long local_flag,u_long dest_flag)
-{
-  volatile u_long *entry;
-  SAVE_PID();
-    
-  entry = (u_long *)MSC_GET_QUEUE_S;
-
-  *entry = tnet_rel_cid_table[dest_cell];
-  *entry = (size+3) >> 2;           /* byte --> word */
-  *entry = (u_long)local_addr;
-  *entry = 0;
-  *entry = (u_long)local_flag;
-  *entry = (u_long)dest_flag;
-  *entry = (u_long)remote_addr;
-  *entry = 0;    
-  RESTORE_PID();
-}
-
-
-/* local_addr is physical 
-   remote_addr is virtual
-   both flags are virtual
-*/
-void ap_phys_get(int dest_cell,u_long local_addr,int size,
-		 u_long remote_addr,u_long local_flag,u_long dest_flag)
-{
-  volatile u_long *entry;
-  SAVE_PID();
-    
-  entry = (u_long *)MSC_CGET_QUEUE_S;
-
-  *entry = tnet_rel_cid_table[dest_cell];
-  *entry = (size+3) >> 2;           /* byte --> word */
-  *entry = (u_long)local_addr;
-  *entry = 0;
-  *entry = (u_long)local_flag;
-  *entry = (u_long)dest_flag;
-  *entry = (u_long)remote_addr;
-  *entry = 0;    
-  RESTORE_PID();
-}
-
-
-/*
- * copy a message from the ringbuffer - being careful of wraparound
-*/
-static inline void tnet_copyin(unsigned *dest,unsigned *src,int size)
-{
-	unsigned *limit = (unsigned *)system_ringbuf.ringbuf + 
-		(SYSTEM_RINGBUF_SIZE>>2);
-	int size1 = limit - src;
-
-	if (size < size1)
-		size1 = size;
-
-	size -= size1;
-	while (size1--) {
-		*dest++ = *src++;
-	}
-	src = system_ringbuf.ringbuf;
-	while (size--) {
-		*dest++ = *src++;
-	}
-}
-
-
-/*
-  put some data into a tasks ringbuffer. size is in words.
-  */
-static inline void memcpy_to_rbuf(unsigned tid,unsigned *msgp,unsigned size)
-{
-	struct aplib_struct *aplib;
-	unsigned octx, ctx;
-	struct task_struct *tsk;
-	unsigned room;
-
-	tsk = task[tid];
-	if (!tsk || !tsk->aplib)
-		return;
-
-	octx = srmmu_get_context();
-	ctx = MPP_TASK_TO_CTX(tid);
-	if (octx != ctx)
-		srmmu_set_context(ctx);
-	aplib = tsk->aplib;
-
-	if (aplib->write_pointer < aplib->read_pointer) 
-		room = aplib->read_pointer - (aplib->write_pointer+1);
-	else
-		room = aplib->ringbuf_size - 
-			((aplib->write_pointer+1)-aplib->read_pointer);
-
-	if (room < size) {
-		send_sig(SIGLOST,tsk,1);		
-		goto finished;
-	}
-
-	tnet_copyin(&aplib->ringbuf[aplib->write_pointer], msgp, size);
-
-	aplib->write_pointer += size;
-	if (aplib->write_pointer >= aplib->ringbuf_size)
-		aplib->write_pointer -= aplib->ringbuf_size;
-
-	aplib->rbuf_flag1++;
-
-finished:
-	if (octx != ctx)
-		srmmu_set_context(octx);
-}
-
-
-
-/* a aplib message has arrived on the system message queue - process
-   it immediately and return the number of bytes taken by the message in
-   the system ringbuffer 
-
-   Note that this function may be called from interrupt level
-   */
-static inline void aplib_system_recv(unsigned *msgp)
-{
-	unsigned tag = msgp[1]>>28;
-	unsigned size, tid;
-
-	if (tag == RBUF_BIGSEND) {
-		aplib_bigrecv(msgp);
-		return;
-	}
-
-	size = (msgp[0]&0xFFFFF);
-	tid = (msgp[1]&0x3FF);
-
-	memcpy_to_rbuf(tid,msgp,size+2);
-}
-
-
-void tnet_ip_complete(struct sk_buff *skb,int from)
-{  
-#if IP_DEBUG
-	char *data = skb->data;
-	int i;
-	printk("CID(%d) tnet ip complete from %d\n",_cid,from);
-
-	for (i=0;i<skb->len;i+=4)
-		printk("(%08x)%c",*(int *)(data+i),i==32?'\n':' ');
-	printk("\n");
-#endif
-	/* ap_phys_put(from,(u_long)&dummy,4,MC_INTP_0,0,0); */
-	bif_rx(skb);
-	tnet_stats.bytes_received += skb->len;
-	tnet_stats.packets_received++;
-}
-
-
-static void tnet_ip_recv(int cid,u_long *info)
-{
-	u_long flag;
-	u_long ipsize = info[1];
-	u_long remote_addr = info[0];
-	u_long remote_flag = info[2];
-	struct sk_buff *skb = dev_alloc_skb(ipsize+8);
-	char *p;
-
-	if (!skb) {
-		ap_put(cid,0,0,0,remote_flag,0);
-		ap_phys_put(cid,(u_long)&dummy,4,MC_INTP_0,0,0);
-		tnet_stats.alloc_errors++;
-		return;
-	}
-
-	skb_reserve(skb,8); /* align on 16 byte boundary */
-
-	flag = tnet_add_completion(tnet_ip_complete,(int)skb,(int)cid);
-
-	p = (char *)skb_put(skb,ipsize);
-#if 0
-{
-	static unsigned count=0;
-	if (count%500 == 0)
-		printk("CID(%d) fetching %d bytes from %x to %x\n",
-		       _cid,ipsize,remote_addr,p);
-	count++;
-}
-#endif
-	ap_get(cid,p,ipsize,remote_addr,flag,remote_flag);
-	ap_phys_get(cid,MC_INTP_0,4,(u_long)&dummy,0,0);
-#if IP_DEBUG
-	printk("CID(%d) ip packet of length %ld from %ld\n",_cid,ipsize,cid);
-#endif
-}
-
-
-static void tnet_ip_recv_small(u_long *data,int size)
-{
-	struct sk_buff *skb = dev_alloc_skb(size+8);
-	if (skb) {
-		skb_reserve(skb,8);
-		tnet_copyin((unsigned *)skb_put(skb,size),(unsigned *)data,(size+3)>>2);
-		bif_rx(skb);
-		tnet_stats.bytes_received += size;
-		tnet_stats.packets_received++;
-		tnet_stats.small_packets_received++;
-	} else {
-		tnet_stats.alloc_errors++;
-	}
-}
-
-
-/* we've got an RPC from a remote cell */
-static void tnet_rpc_recv(u_long *data,int size)
-{
-	struct fnp {
-		void (*fn)();
-	} fnp;
-	fnp = *(struct fnp *)data;
-	fnp.fn(data,size);
-}
-
-/*
- * receive messages from the system ringbuffer. We don't bother with
- * all the niceities that are done in user space, we just always
- * process the messages in order 
- */
-static inline void tnet_recv(void)
-{
-	unsigned flags;
-	u_long from,*data,fix,align,size1,size,type;
-
-	if (system_recv_flag == system_recv_count) 
-		return;
-
-	save_flags(flags); cli();
-	while (system_recv_flag != system_recv_count) {
-		u_long read_ptr = 
-			(system_read_ptr + 1) % (SYSTEM_RINGBUF_SIZE>>5);  
-		u_long *msgp = 
-			((u_long *)system_ringbuf.ringbuf) + (read_ptr<<3);
-		u_long tag = (msgp[1]>>28) & 0xF;
-		size1 = (msgp[0]&0xFFFFF)<<2;
-
-		/* move our read pointer past this message */
-		system_read_ptr = (system_read_ptr + 
-				   ((size1+8+31)>>5))%(SYSTEM_RINGBUF_SIZE>>5);
-		system_recv_count++;		
-
-
-		if (tag != RBUF_SYSTEM) {
-			aplib_system_recv(msgp);
-			continue;
-		} 
-
-		from = msgp[0] >> 22;
-		data = msgp+2;
-		fix = (msgp[0]>>20)&3;
-		align = (msgp[1]>>26)&3;
-		size = ((size1 - align) & ~3) | fix;
-		type = (msgp[1]&0xFF);
-
-		switch (type) {
-		case TNET_IP:
-			tnet_ip_recv(from,data);
-			break;
-			
-		case TNET_IP_SMALL:
-			tnet_ip_recv_small(data,size);
-			break;
-			
-		case TNET_RPC:
-			tnet_rpc_recv(data,size);
-			break;
-			
-		default:
-			tnet_stats.errors++;
-			printk("unknown Tnet type %ld\n",type);
-		}
-
-#if DEBUG
-		printk("CID(%d) recvd %d bytes of type %d read_ptr=%x\n",
-		       _cid,size,type,system_read_ptr);
-#endif
-	}
-	restore_flags(flags);
-}
-
-
-#define COMPLETION_LIST_LENGTH 256
-
-static unsigned completion_list_rp = 0;
-static unsigned completion_list_wp = 0;
-
-static volatile struct completion_struct {
-  u_long flag;
-  void (*fn)(int a1,...);
-  u_long args[2];
-} completion_list[COMPLETION_LIST_LENGTH];
-
-
-void tnet_check_completion(void)
-{
-	struct completion_struct *cs;
-	unsigned flags;
-
-	tnet_recv();  
-
-	if (completion_list[completion_list_rp].flag != 2)
-		return;
-
-	save_flags(flags); cli();
-  
-	while (completion_list[completion_list_rp].flag == 2) {
-		cs = &completion_list[completion_list_rp];
-		cs->flag = 0;
-		if (++completion_list_rp == COMPLETION_LIST_LENGTH)
-			completion_list_rp = 0;
-
-		restore_flags(flags);
-
-		cs->fn(cs->args[0],cs->args[1]);
-
-		if (completion_list[completion_list_rp].flag != 2)
-			return;
-
-		save_flags(flags); cli();
-	}
-	
-	restore_flags(flags);
-}
-
-
-static u_long tnet_add_completion(void (*fn)(int a1,...),int a1,int a2)
-{
-        unsigned flags;
-        struct completion_struct *cs;
-	
-	save_flags(flags); cli();
-
-	while (completion_list[completion_list_wp].flag != 0)
-		tnet_check_completion();
-
-	cs = &completion_list[completion_list_wp];
-
-	if (++completion_list_wp == COMPLETION_LIST_LENGTH)
-		completion_list_wp = 0;
-
-	restore_flags(flags);
-
-        cs->flag = 1;
-        cs->fn = fn;
-	cs->args[0] = a1;
-	cs->args[1] = a2;
-
-        return (u_long)&cs->flag;
-}
-
-
-/* 
- * send a message to the tnet ringuffer on another cell. When the send has
- * completed call fn with the args supplied 
- */
-static void tnet_send(long cid,long type,char *src_addr,long byteSize,
-		      int immediate,u_long flag)
-{
-	int wordSize;
-	int byteAlign, byteFix;
-	u_long src;
-	u_long info1, info2;
-	volatile u_long *entry = (volatile u_long *)MSC_SEND_QUEUE_S;
-	SAVE_PID();
-
-	byteAlign = ((u_long)src_addr) & 0x3;
-	byteFix = byteSize & 0x3;
-	
-	src = (u_long)src_addr & ~3;
-	
-	wordSize = (byteSize + byteAlign + 3) >> 2;
-	
-	info1 = (_cid << 22) | (byteFix << 20) | wordSize;
-	info2 = (RBUF_SYSTEM<<28) | (byteAlign << 26) | type;
-	
-	*entry = tnet_rel_cid_table[cid];
-	*entry = wordSize;
-	*entry = (u_long)&system_recv_flag;
-	*entry = flag;
-	*entry = (u_long)src;
-	*entry = 0;
-	*entry = info1;
-	*entry = info2;
-	RESTORE_PID();
-	
-	ap_phys_put(cid,(u_long)&dummy,4,MC_INTP_0,0,0);
-	if (immediate && flag) 
-		ap_phys_put(_cid,(u_long)&dummy,4,MC_INTP_0,0,0);
-}
-
-
-static void free_skb(struct sk_buff *skb, int op)
-{
-	dev_kfree_skb(skb);
-}
-
-void tnet_send_ip(int cid,struct sk_buff *skb)
-{
-	char *data = skb->data + sizeof(struct cap_request);
-	int size = skb->len - sizeof(struct cap_request);
-	u_long flag;
-#if IP_DEBUG
-	int i;
-	for (i=0;i<size;i+=4)
-		printk("[%08x]%c",*(int *)(data+i),i==32?'\n':' ');
-	printk("\n");
-#endif
-	if (size > TNET_IP_THRESHOLD) {
-		int *info = (int *)skb->data; /* re-use the header */
-		info[0] = (int)data;
-		info[1] = size;
-		info[2] = tnet_add_completion(free_skb, (int)skb, 0);
-		tnet_send(cid,TNET_IP,info,sizeof(int)*3,0,0);
-	} else {
-		flag = tnet_add_completion(free_skb, (int)skb, 0);
-		tnet_send(cid,TNET_IP_SMALL,data,size,0,flag);
-		tnet_stats.small_packets_sent++;
-	}
-	tnet_stats.packets_sent++;
-	tnet_stats.bytes_sent += size;
-#if IP_DEBUG
-	printk("CID(%d) sent IP of size %d to %d\n",_cid,size,cid);
-#endif
-}
-
-static void reschedule(void)
-{
-	current->need_resched = 1;
-	mark_bh(TQUEUE_BH);
-}
-
-
-/* make a remote procedure call 
-   If free is set then free the data after sending it 
-   The first element of data is presumed to be a function pointer
-*/
-int tnet_rpc(int cell,char *data,int size,int free)
-{
-	unsigned flag=0;
-
-	if (free) {
-		flag = tnet_add_completion(kfree,data,0);
-	}
-
-	tnet_send(cell,TNET_RPC,data,size,0,flag);
-	return 0;
-}
-
-
-static void iport_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-	int i;
-	u_long intr = MC_IN(MC_INTR_PORT);
-
-	for (i=0;i<4;i++) {
-		if (intr & (AP_INTR_REQ << iports[i].shift)) {
-			MC_OUT(MC_INTR_PORT,AP_CLR_INTR_REQ << iports[i].shift);
-			if (iports[i].fn) iports[i].fn();
-		}
-	}
-}
-
-
-void ap_tnet_init(void)
-{
-	int i;
-
-	bif_add_debug_key('T',tnet_info,"Tnet status");
-
-	memset(completion_list,0,sizeof(completion_list));
-	
-	request_irq(APIPORT_IRQ, iport_irq, SA_INTERRUPT, "iport", 0);
-
-	for (i=0;i<4;i++) {
-		MC_OUT(MC_INTR_PORT,AP_CLR_INTR_REQ << iports[i].shift);
-		MC_OUT(MC_INTR_PORT,AP_CLR_INTR_MASK << iports[i].shift);
-	}    
-
-
-	tnet_rel_cid_table = (int *)kmalloc(sizeof(int)*_ncel,GFP_ATOMIC);
-	for (i=0;i<_ncel;i++)
-		tnet_rel_cid_table[i] = rel_cid(i);
-
-	if(_cid == 0) {
-		xy_global_head  = (((_ncelx -1) << 8) & 0xff00) | 
-			((_ncely - 1) & 0xff);
-	}
-	else {
-		for(i = 1; i < _ncel; i *= 2){
-			if(i & _cid) {	
-				int	rcidx = (_cid-i)%_ncelx - _cid%_ncelx;
-				int	rcidy = (_cid-i)/_ncelx - _cid/_ncelx;
-				xy_global_head  = ((rcidx << 8) & 0xff00) | 
-					(rcidy & 0xff);
-				break;	
-			}
-		}
-	}
-}
-
-static void tnet_info(void)
-{
-	struct completion_struct *cs;
-	
-	printk(
-	       "errors=%d  alloc_errors=%d
-bytes_received=%d  bytes_sent=%d
-packets_received=%d  packets_sent=%d
-small_received=%d  small_sent=%d
-",
-	       tnet_stats.errors, tnet_stats.alloc_errors,
-	       tnet_stats.bytes_received,
-	       tnet_stats.bytes_sent, tnet_stats.packets_received,
-	       tnet_stats.packets_sent, tnet_stats.small_packets_received,
-	       tnet_stats.small_packets_sent);
-
-	printk("recv_flag=%d recv_count=%d read_ptr=%d\n",
-	       system_recv_flag,system_recv_count,system_read_ptr);
-	printk("completion_list_rp=%d  completion_list_wp=%d\n",
-	       completion_list_rp,completion_list_wp);
-}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)