patch-2.3.42 linux/arch/sparc/ap1000/bnet.c
Next file: linux/arch/sparc/ap1000/dma.c
Previous file: linux/arch/sparc/ap1000/approm.c
Back to the patch index
Back to the overall index
- Lines: 1206
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.3.41/linux/arch/sparc/ap1000/bnet.c
- Orig date:
Fri Feb 20 18:28:22 1998
diff -u --recursive --new-file v2.3.41/linux/arch/sparc/ap1000/bnet.c linux/arch/sparc/ap1000/bnet.c
@@ -1,1205 +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 bif interface. This is the interface
- used to talk to the front end processor */
-
-#include <linux/sched.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <asm/irq.h>
-#include <linux/skbuff.h>
-
-#define NET_DEBUG 0
-
-#define DUMMY_MSG_LEN 100
-#define DUMMY_MSG_WAIT 30
-
-#define MAX_CELLS 128
-
-#define HAVE_BIF() (BIF_IN(BIF_SDCSR) & BIF_SDCSR_BG)
-#define BIF_BUSY() (BIF_IN(BIF_SDCSR) & BIF_SDCSR_BB)
-
-#define SNET_ARBITRATION 0
-#define TOKEN_ARBITRATION 1
-
-#define DEBUG(x)
-
-#if TOKEN_ARBITRATION
-static int have_token = 0;
-#endif
-
-extern struct cap_init cap_init;
-
-static int interrupt_driven = 0;
-static int use_dma = 0;
-struct pt_regs *bif_pt_regs = NULL;
-enum dma_state {DMA_IDLE,DMA_INCOMING,DMA_OUTGOING};
-static enum dma_state dma_state = DMA_IDLE;
-
-static int net_started = 0;
-static int waiting_for_bif = 0;
-static int queue_length = 0;
-
-static int drop_ip_packets = 0;
-
-#define DMA_THRESHOLD 64
-
-static struct cap_request bread_req;
-
-int tnet_ip_enabled = 1;
-
-#define BIF_DATA_WAITING() (BIF_IN(BIF_SDCSR) & BIF_SDCSR_RB)
-
-#define ROUND4(x) (((x) + 3) & -4)
-
-static void bif_intr_receive(struct cap_request *req1);
-
-
-/* read some data from the bif */
-void read_bif(char *buf,int size)
-{
- unsigned *ibuf = (unsigned *)buf;
- unsigned avail;
-
- DEBUG(("|read_bif %d\n",size));
-
- if (dma_state != DMA_IDLE) ap_dma_wait(DMA_CH2);
-
- size = (size+3) >> 2;
-
- while (size > 4) {
- while (!(avail=(BIF_IN(BIF_SDCSR) >> BIF_SDCSR_RB_SHIFT) & 7))
- ;
- if (avail & 4) {
- ibuf[0] = BIF_IN(BIF_DATA);
- ibuf[1] = BIF_IN(BIF_DATA);
- ibuf[2] = BIF_IN(BIF_DATA);
- ibuf[3] = BIF_IN(BIF_DATA);
- size -= 4; ibuf += 4;
- continue;
- }
-
- if (avail & 2) {
- ibuf[0] = BIF_IN(BIF_DATA);
- ibuf[1] = BIF_IN(BIF_DATA);
- size -= 2; ibuf += 2;
- continue;
- }
- *ibuf++ = BIF_IN(BIF_DATA);
- size--;
- }
-
- while (size--) {
- while (!(BIF_IN(BIF_SDCSR) & BIF_SDCSR_RB)) ;
- *ibuf++ = BIF_IN(BIF_DATA);
- }
-
- DEBUG(("|read bif done\n"));
-}
-
-/* throw out some data from the bif. This is usually called when we
- don't have the resources to handle it immediately */
-void bif_toss(int size)
-{
- unsigned flags;
- save_flags(flags); cli();
-
- DEBUG(("|bif toss %d\n",size));
-
- while (size>0) {
- while (!BIF_DATA_WAITING());
- BIF_IN(BIF_DATA);
- size -= 4;
- }
-
- DEBUG(("|bif toss done\n"));
-
- restore_flags(flags);
-}
-
-
-static void bif_reset_interrupts(void)
-{
- BIF_OUT(BIF_INTR,AP_INTR_WENABLE << BIF_INTR_GET_SH);
- BIF_OUT(BIF_INTR,AP_INTR_WENABLE << BIF_INTR_HEADER_SH);
-}
-
-static void bif_mask_interrupts(void)
-{
- BIF_OUT(BIF_INTR,(AP_INTR_MASK|AP_INTR_WENABLE) << BIF_INTR_GET_SH);
- BIF_OUT(BIF_INTR,(AP_INTR_MASK|AP_INTR_WENABLE) << BIF_INTR_HEADER_SH);
-}
-
-static void attn_enable(void)
-{
- BIF_OUT(BIF_INTR,AP_INTR_WENABLE << BIF_INTR_ATTN_SH);
-}
-
-static void attn_mask(void)
-{
- BIF_OUT(BIF_INTR,(AP_INTR_MASK|AP_INTR_WENABLE) << BIF_INTR_ATTN_SH);
-}
-
-
-void ap_bif_status(void)
-{
- static int bif_sdcsr;
- static int bif_intr;
- static int bif_mhocr;
- static int bif_x0sk;
- static int bif_xsk;
- static int bif_xsz;
- static int bif_y0sk;
- static int bif_ysk;
- static int bif_ysz;
- static int bif_cx0sk;
- static int bif_cxsk;
- static int bif_cxsz;
- static int bif_cy0sk;
- static int bif_cysk;
- static int bif_cysz;
- static int bif_ttl;
- static int bif_cttl;
- static int bif_header;
-
- bif_sdcsr = BIF_IN(BIF_SDCSR);
- bif_intr = BIF_IN(BIF_INTR);
- bif_mhocr = BIF_IN(BIF_MHOCR);
-
- bif_x0sk = BIF_IN(BIF_X0SK);
- bif_xsk = BIF_IN(BIF_XSK);
- bif_xsz = BIF_IN(BIF_XSZ);
- bif_y0sk = BIF_IN(BIF_Y0SK);
- bif_ysk = BIF_IN(BIF_YSK);
- bif_ysz = BIF_IN(BIF_YSZ);
-
- bif_cx0sk = BIF_IN(BIF_CX0SK);
- bif_cxsk = BIF_IN(BIF_CXSK);
- bif_cxsz = BIF_IN(BIF_CXSZ);
- bif_cy0sk = BIF_IN(BIF_CY0SK);
- bif_cysk = BIF_IN(BIF_CYSK);
- bif_cysz = BIF_IN(BIF_CYSZ);
-
- bif_ttl = BIF_IN(BIF_TTL);
- bif_cttl = BIF_IN(BIF_CTTL);
- bif_header = BIF_IN(BIF_HEADER);
-
- printk("|\t***** BIF REG. *****\n");
- printk("|\tBIF_SDCSR = %08x ", bif_sdcsr);
- if(bif_sdcsr & BIF_SDCSR_CN) printk("|<BUS DISCONNECT>");
- if(bif_sdcsr & BIF_SDCSR_FN) printk("|<SC/GA ENABLE>");
- if(bif_sdcsr & BIF_SDCSR_DE) printk("|<DMA ENABLE>");
- if(bif_sdcsr & BIF_SDCSR_DR) printk("|<GATHER>");
- if(bif_sdcsr & BIF_SDCSR_BB) printk("|<BUS BSY>");
- if(bif_sdcsr & BIF_SDCSR_BR) printk("|<BUS REQ>");
- if(bif_sdcsr & BIF_SDCSR_BG) printk("|<BUS GET>");
- if(bif_sdcsr & BIF_SDCSR_ER) printk("|<ERROR:");
- if(bif_sdcsr & BIF_SDCSR_SP) printk("|SYNC PARITY:");
- if(bif_sdcsr & BIF_SDCSR_LP) printk("|LBUS PARITY:");
- if(bif_sdcsr & BIF_SDCSR_LR) printk("|READ EMPTY FIFO:");
- if(bif_sdcsr & BIF_SDCSR_LW) printk("|WRITE FULL FIFO:");
- if(bif_sdcsr & BIF_SDCSR_AL) printk("|READ ENDBIT:");
- if(bif_sdcsr & BIF_SDCSR_SS) printk("|SET MASK SSTAT:");
- if(bif_sdcsr & BIF_SDCSR_SC) printk("|CLR SSYNC ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_SY) printk("|REQ SSYNC ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_FS) printk("|SET MASK FSTAT:");
- if(bif_sdcsr & BIF_SDCSR_FC) printk("|CLR FSYNC ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_FY) printk("|REQ FSYNC ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_CP) printk("|BNET PARITY:");
- if(bif_sdcsr & BIF_SDCSR_FP) printk("|FE NOT SET WHEN SC/GA:");
- if(bif_sdcsr & BIF_SDCSR_PS) printk("|RECV PACKET ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_RA) printk("|CHANGE FE ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_PA) printk("|SEND/RECV ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_DL) printk("|DATA LOST:");
- if(bif_sdcsr & BIF_SDCSR_ER) printk("|>");
- if(bif_sdcsr & BIF_SDCSR_PE) printk("|<SYNC PARITY ENABLE>");
- printk("|\n");
- printk("|\tBIF_INTR = %08x\n", bif_intr);
- printk("|\tBIF_MHOCR = %08x\n", bif_mhocr);
-
- printk("|\tBIF_X0SK = %08x\n", bif_x0sk);
- printk("|\tBIF_XSK = %08x\n", bif_xsk);
- printk("|\tBIF_XSZ = %08x\n", bif_xsz);
- printk("|\tBIF_Y0SK = %08x\n", bif_y0sk);
- printk("|\tBIF_YSK = %08x\n", bif_ysk);
- printk("|\tBIF_YSZ = %08x\n", bif_ysz);
- printk("|\tBIF_CX0SK = %08x\n", bif_cx0sk);
- printk("|\tBIF_CXSK = %08x\n", bif_cxsk);
- printk("|\tBIF_CXSZ = %08x\n", bif_cxsz);
- printk("|\tBIF_CY0SK = %08x\n", bif_cy0sk);
- printk("|\tBIF_CYSK = %08x\n", bif_cysk);
- printk("|\tBIF_CYSZ = %08x\n", bif_cysz);
-
- printk("|\tBIF_TTL = %08x\n", bif_ttl);
- printk("|\tBIF_CTTL = %08x\n", bif_cttl);
- printk("|\tBIF_HEADER = %08x\n", bif_header);
-}
-
-
-void bif_led_status(void)
-{
-#if 1
- static int i = 0;
- unsigned char res = 0;
-
- switch (i) {
- case 0:
- case 2:
- res = 0xff;
- break;
- case 1:
- case 3:
- res = 0;
- break;
- default:
- res = 0xFF & (BIF_IN(BIF_SDCSR) >> (((i-4)/4)*8));
- }
- i = (i+1) % 20;
-
- ap_led(res);
-#endif
-}
-
-static void get_bif(void)
-{
- if (HAVE_BIF())
- return;
-
- drop_ip_packets = 1;
-
- DEBUG(("|get_bif started\n"));
-
- if (dma_state != DMA_IDLE)
- ap_dma_wait(DMA_CH2);
-
-#if SNET_ARBITRATION
- /* wait till the host doesn't want the BIF anymore, tossing
- any data that arrives */
- while (BIF_IN(FSTT_CLR) & HOST_STATUS_BIT)
- if (BIF_IN(BIF_SDCSR) & BIF_SDCSR_RB)
- bif_intr_receive(NULL);
- waiting_for_bif = 0;
-#endif
-
-#if TOKEN_ARBITRATION
- BIF_OUT(FSTT_CLR,HOST_STATUS_BIT);
-#endif
-
- /* request the BIF */
- BIF_OUT(BIF_SDCSR,BIF_SDCSR_BR);
-
- /* loop waiting for us to get the BIF, tossing any data */
- while (!HAVE_BIF())
- if (BIF_IN(BIF_SDCSR) & BIF_SDCSR_RB)
- bif_intr_receive(NULL);
-
- bif_reset_interrupts();
- if (!interrupt_driven)
- bif_mask_interrupts();
-
- drop_ip_packets = 0;
-
-#if TOKEN_ARBITRATION
- BIF_OUT(FSTT_SET,HOST_STATUS_BIT);
-#endif
-
- DEBUG(("|get_bif done\n"));
-}
-
-
-/* write a message to the front end over the Bnet. This can be in
- multiple parts, as long as the first part sets "start" and the last
- part sets "end". The bus will be grabbed while this is going on
- */
-static void write_bif(char *buf,int size,int start,int end)
-{
- unsigned *ibuf;
- unsigned avail;
-
- DEBUG(("|write_bif %d %d %d\n",size,start,end));
-
- if (start) {
- /* a dma op may be in progress */
- if (dma_state != DMA_IDLE) ap_dma_wait(DMA_CH2);
- }
-
- size = (size+3) >> 2;
- ibuf = (unsigned *)buf;
- if (end) size--;
-
- while (size > 4) {
- while (!(avail=(BIF_IN(BIF_SDCSR) >> BIF_SDCSR_TB_SHIFT) & 7))
- ;
- if (avail & 4) {
- BIF_OUT(BIF_DATA,ibuf[0]);
- BIF_OUT(BIF_DATA,ibuf[1]);
- BIF_OUT(BIF_DATA,ibuf[2]);
- BIF_OUT(BIF_DATA,ibuf[3]);
- size -= 4; ibuf += 4;
- continue;
- }
-
- if (avail & 2) {
- BIF_OUT(BIF_DATA,ibuf[0]);
- BIF_OUT(BIF_DATA,ibuf[1]);
- size -= 2; ibuf += 2;
- continue;
- }
- BIF_OUT(BIF_DATA,ibuf[0]);
- ibuf++; size--;
- }
-
- while (size--) {
- while (!(BIF_IN(BIF_SDCSR) & BIF_SDCSR_TB)) ;
- BIF_OUT(BIF_DATA,ibuf[0]);
- ibuf++;
- }
-
- if (end) {
- while (!(BIF_IN(BIF_SDCSR) & BIF_SDCSR_TB)) ;
- BIF_OUT(BIF_EDATA,*ibuf);
- }
-
- DEBUG(("|write bif done\n"));
-}
-
-#if TOKEN_ARBITRATION
-static void forward_token(void)
-{
- struct cap_request req;
- req.cid = mpp_cid();
- req.type = REQ_BIF_TOKEN;
- req.size = sizeof(req);
- if (req.cid == cap_init.numcells - 1)
- req.header = MAKE_HEADER(HOST_CID);
- else
- req.header = MAKE_HEADER(req.cid + 1);
-
- write_bif((char *)&req,sizeof(req),1,1);
- have_token = 0;
-}
-#endif
-
-static void release_bif(void)
-{
- static int dummy[DUMMY_MSG_LEN];
-
- waiting_for_bif = 0;
-
-#if SNET_ARBITRATION
- /* mask the attention interrupt */
- attn_mask();
-#endif
-
- /* maybe we don't have it?? */
- if (!HAVE_BIF())
- return;
-
- DEBUG(("|release bif started\n"));
-
- if (dma_state != DMA_IDLE) ap_dma_wait(DMA_CH2);
-
-#if TOKEN_ARBITRATION
- if (have_token)
- forward_token();
-#endif
-
-#if 1
- /* send a dummy message to ensure FIFO flushing
- (suggestion from woods to overcome bif release
- hardware bug) */
- dummy[0] = 0xEEEE4000;
- write_bif((char *)dummy,DUMMY_MSG_LEN,1,1);
-#endif
- /* wait till the send FIFO is completely empty */
- while (!((BIF_IN(BIF_SDCSR) & BIF_SDCSR_TB) == BIF_SDCSR_TB)) ;
-
- /* wait another few us */
- udelay(DUMMY_MSG_WAIT);
-
- /* send release-data */
- BIF_OUT(BIF_DATA,BIF_HEADER_RS);
-
- /* wait until we don't have the bus */
- while (HAVE_BIF()) ;
-
- DEBUG(("|release bif done\n"));
-}
-
-
-/* wait for a particular request type - throwing away anything else! */
-void ap_wait_request(struct cap_request *req,int type)
-{
- drop_ip_packets = 1;
- do {
- while (!BIF_DATA_WAITING())
- if (HAVE_BIF()) release_bif();
- read_bif((char *)req,sizeof(*req));
- if (req->type != type) {
- bif_intr_receive(req);
- }
- } while (req->type != type);
- drop_ip_packets = 0;
-}
-
-
-void write_bif_polled(char *buf1,int len1,char *buf2,int len2)
-{
- unsigned flags;
- save_flags(flags); cli();
-
- get_bif();
- write_bif(buf1,len1,1,(buf2&&len2)?0:1);
- if (buf2 && len2)
- write_bif(buf2,len2,0,1);
- release_bif();
- restore_flags(flags);
-}
-
-static void want_bif(void)
-{
- unsigned flags;
-
- save_flags(flags); cli();
-
- /* maybe we've already got it */
- if (HAVE_BIF()) {
- waiting_for_bif = 0;
- restore_flags(flags);
- return;
- }
-
-#if SNET_ARBITRATION
- if (interrupt_driven)
- attn_enable();
-
- /* check if the host wants it */
- if (BIF_IN(FSTT_CLR) & HOST_STATUS_BIT) {
- /* the host wants it - don't get it yet */
- waiting_for_bif = 1;
- } else {
- /* the host doesn't want it - just set bus request */
- waiting_for_bif = 0;
- BIF_OUT(BIF_SDCSR,BIF_SDCSR_BR);
- while (!HAVE_BIF() && !BIF_BUSY()) ;
- DEBUG(("|set bif request\n"));
- }
- restore_flags(flags);
- return;
-#endif
-
-#if TOKEN_ARBITRATION
- if (net_started && !have_token) {
- BIF_OUT(FSTT_CLR,HOST_STATUS_BIT);
- restore_flags(flags);
- return;
- }
- BIF_OUT(FSTT_SET,HOST_STATUS_BIT);
-#endif
-
- BIF_OUT(BIF_SDCSR,BIF_SDCSR_BR);
- restore_flags(flags);
-}
-
-#define BIF_NOCOPY (1<<0)
-
-/* a queue of requests that need to be sent over the bif. Needs to be
-modified sometime to allow the direct queueing of skb's */
-struct bif_queue {
- volatile struct bif_queue *next;
- struct cap_request req;
- char *data;
- int data_size;
- int flags;
-};
-
-static volatile struct bif_queue *bif_queue_top = NULL;
-static volatile struct bif_queue *bif_queue_end = NULL;
-
-static struct sk_buff *skb_out = NULL;
-static struct sk_buff *skb_in = NULL;
-static char *bif_dma_data = NULL;
-static int bif_dma_out_size = 0;
-
-
-/* send waiting elements. Called mainly when we get a bif "bus get"
- interrupt to say we now have the bus */
-static void bif_intr_runqueue(void)
-{
- unsigned flags;
-
- /* if I don't have the bus then return */
- if (!HAVE_BIF())
- return;
-
- if (dma_state != DMA_IDLE) return;
-
- save_flags(flags); cli();
-
- while (bif_queue_top) {
- volatile struct bif_queue *q = bif_queue_top;
- bif_queue_top = q->next;
-
- /* printk("|queue run (length=%d)\n",queue_length); */
- queue_length--;
-
- if (!q->data) {
- /* use programmed IO for small requests */
- write_bif((char *)&q->req,sizeof(q->req),1,1);
- kfree_s((char *)q,sizeof(*q));
- continue;
- }
-
- if (q->flags & BIF_NOCOPY) {
- write_bif((char *)&q->req,sizeof(q->req),1,0);
- }
-
- if (use_dma && q->data_size > DMA_THRESHOLD) {
- dma_state = DMA_OUTGOING;
- if (q->req.type == REQ_IP) {
- skb_out = (struct sk_buff *)q->data;
- ap_dma_go(DMA_CH2,(unsigned)skb_out->data,
- q->data_size,DMA_DCMD_TD_MD);
- } else {
- if (!(q->flags & BIF_NOCOPY)) {
- bif_dma_data = q->data;
- bif_dma_out_size = q->data_size;
- }
- ap_dma_go(DMA_CH2,(unsigned)q->data,
- q->data_size,DMA_DCMD_TD_MD);
- }
- kfree_s((char *)q,sizeof(*q));
- restore_flags(flags);
- return; /* wait for DMA to complete */
- }
-
- if (q->req.type == REQ_IP) {
- struct sk_buff *skb = (struct sk_buff *)q->data;
- write_bif(skb->data,q->data_size,1,1);
- dev_kfree_skb(skb);
- } else {
- write_bif(q->data,q->data_size,1,1);
- if (!(q->flags & BIF_NOCOPY))
- kfree_s(q->data,q->data_size);
- }
- kfree_s((char *)q,sizeof(*q));
- }
-
- /* I don't want the bus now */
- release_bif();
- restore_flags(flags);
-}
-
-
-static void queue_attach(struct bif_queue *q)
-{
- unsigned flags;
- save_flags(flags); cli();
-
- /* attach it to the end of the queue */
- if (!bif_queue_top) {
- bif_queue_top = q;
- } else {
- bif_queue_end->next = q;
- }
- bif_queue_end = q;
-
- queue_length++;
-
- /* printk("|queue add (length=%d)\n",queue_length); */
-
- /* tell the bus we want access */
- want_bif();
-
- restore_flags(flags);
-}
-
-
-/* queue an element for sending over the bif. */
-int bif_queue(struct cap_request *req,char *buf,int bufsize)
-{
- struct bif_queue *q;
-
- if (req->header == 0)
- req->header = MAKE_HEADER(HOST_CID);
-
- /* if we aren't running interrupt driven then just send it
- immediately */
- if (!interrupt_driven) {
- write_bif_polled((char *)req,sizeof(*req),buf,bufsize);
- return(0);
- }
-
- /* allocate a queue element */
- q = (struct bif_queue *)kmalloc(sizeof(*q), GFP_ATOMIC);
- if (!q) {
- /* yikes! */
- return(-ENOMEM);
- }
-
- q->flags = 0;
- q->data = NULL;
- q->data_size = 0;
-
- if (buf && bufsize>0) {
- q->data_size = bufsize+sizeof(*req);
- q->data = (char *)kmalloc(q->data_size,GFP_ATOMIC);
- if (!q->data) {
- kfree_s(q,sizeof(*q));
- return(-ENOMEM);
- }
- }
-
- q->req = *req;
- if (buf&&bufsize) {
- memcpy(q->data,(char *)req,sizeof(*req));
- memcpy(q->data+sizeof(*req),buf,bufsize);
- }
- q->next = NULL;
-
- queue_attach(q);
-
- return(0);
-}
-
-
-/* queue an element for sending over the bif. */
-int bif_queue_nocopy(struct cap_request *req,char *buf,int bufsize)
-{
- struct bif_queue *q;
-
- if (req->header == 0)
- req->header = MAKE_HEADER(HOST_CID);
-
- /* allocate a queue element */
- q = (struct bif_queue *)kmalloc(sizeof(*q), GFP_ATOMIC);
- if (!q) {
- return(-ENOMEM);
- }
-
- q->data = buf;
- q->data_size = bufsize;
- q->flags = BIF_NOCOPY;
- q->req = *req;
- q->next = NULL;
-
- queue_attach(q);
-
- return(0);
-}
-
-
-/* put an IP packet into the bif queue */
-int bif_send_ip(int cid, struct sk_buff *skb)
-{
- struct cap_request *req = (struct cap_request *)skb->data;
- struct bif_queue *q;
- u_long destip;
-
- destip = *(u_long *)(skb->data+sizeof(*req)+16);
-
- if (cid != -1) {
- req->header = MAKE_HEADER(cid);
- } else if (destip == (cap_init.baseIP | ~cap_init.netmask)) {
- req->header = BIF_HEADER_IN | BIF_HEADER_BR;
- } else {
- req->header = MAKE_HEADER(HOST_CID);
- }
-
- /* allocate a queue element */
- q = (struct bif_queue *)kmalloc(sizeof(*q), GFP_ATOMIC);
- if (!q) {
- /* yikes! */
- dev_kfree_skb(skb);
- return(-ENOMEM);
- }
-
- req->size = ROUND4(skb->len);
- req->cid = mpp_cid();
- req->type = REQ_IP;
-
- q->data = (char *)skb;
- q->data_size = req->size;
- q->next = NULL;
- q->req = *req;
- q->flags = 0;
-
- queue_attach(q);
-
- return(0);
-}
-
-
-/* send an OPENNET request to tell the front end to open the apnet
- network interface */
-void start_apnet(void)
-{
- struct cap_request req;
- req.cid = mpp_cid();
- req.type = REQ_OPENNET;
- req.size = sizeof(req);
- req.header = MAKE_HEADER(HOST_CID);
-
- bif_queue(&req,NULL,0);
- printk("sent start_apnet request\n");
-}
-
-/* we have received an IP packet - pass it to the bif network
- interface code */
-static void reply_ip(struct cap_request *req)
-{
- if (drop_ip_packets ||
- !(skb_in = dev_alloc_skb(req->size - sizeof(*req)))) {
- bif_toss(req->size - sizeof(*req));
- return;
- }
-
- if (use_dma && req->size > DMA_THRESHOLD) {
- dma_state = DMA_INCOMING;
- ap_dma_go(DMA_CH2,
- (unsigned)skb_put(skb_in,req->size - sizeof(*req)),
- req->size - sizeof(*req),DMA_DCMD_TD_DM);
- } else {
- read_bif(skb_put(skb_in,req->size - sizeof(*req)),
- req->size - sizeof(*req));
- bif_rx(skb_in);
- skb_in = NULL;
- }
-}
-
-
-/* we have received a bread block - DMA it in */
-static void reply_bread(struct cap_request *req)
-{
- extern char *ap_buffer(struct cap_request *creq);
- char *buffer;
-
- buffer = ap_buffer(req);
- bread_req = *req;
-
- if (use_dma) {
- dma_state = DMA_INCOMING;
- ap_dma_go(DMA_CH2,
- (unsigned)buffer,req->size - sizeof(*req),
- DMA_DCMD_TD_DM);
- } else {
- read_bif(buffer,req->size - sizeof(*req));
- ap_complete(&bread_req);
- bread_req.type = -1;
- }
-}
-
-
-static struct debug_key {
- struct debug_key *next;
- char key;
- void (*fn)(void);
- char *description;
-} *debug_keys = NULL;
-
-
-void show_debug_keys(void)
-{
- struct debug_key *r;
- for (r=debug_keys;r;r=r->next)
- printk("%c: %s\n",r->key,r->description);
-}
-
-
-void bif_add_debug_key(char key,void (*fn)(void),char *description)
-{
- struct debug_key *r,*r2;
- r = (struct debug_key *)kmalloc(sizeof(*r),GFP_ATOMIC);
- if (r) {
- r->next = NULL;
- r->key = key;
- r->fn = fn;
- r->description = description;
- if (!debug_keys) {
- debug_keys = r;
- } else {
- for (r2=debug_keys;
- r2->next && r2->key != key;r2=r2->next) ;
-
- if (r2->key == key) {
- r2->fn = fn;
- r2->description = description;
- kfree_s(r,sizeof(*r));
- } else {
- r2->next = r;
- }
- }
- }
-}
-
-/* these are very useful for debugging ! */
-static void reply_putchar(struct cap_request *req)
-{
- struct debug_key *r;
-
- char c = req->data[0];
-
- ap_set_user(req->data[1]);
-
- for (r=debug_keys;r;r=r->next)
- if (r->key == c) {
- r->fn();
- break;
- }
- if (!r)
- printk("cell %d got character %d [%c]\n",mpp_cid(),(int)c,c);
-
- ap_set_user(-1);
-}
-
-
-/* send a signal to a task by name or pid */
-static void reply_kill(struct cap_request *req)
-{
- int sig = req->data[0];
- struct task_struct *p;
- int len;
- char name[32];
-
- len = req->size - sizeof(*req);
- if (len == 0) {
- int pid = req->data[1];
- p = find_task_by_pid(pid);
-
- if(p)
- send_sig(sig, p, 1);
- else
- printk("cell %d: no task with pid %d\n",mpp_cid(),pid);
- return;
- }
-
- if (len > sizeof(name)-1) {
- bif_toss(len);
- return;
- }
-
- read_bif(name,len);
- name[len] = 0;
-
- read_lock(&tasklist_lock);
- for_each_task(p)
- if (strcmp(name,p->comm) == 0)
- send_sig(sig,p,1);
- read_unlock(&tasklist_lock);
-}
-
-
-static struct req_list {
- struct req_list *next;
- int type;
- void (*fn)(struct cap_request *);
-} *reg_req_list = NULL;
-
-
-void bif_register_request(int type,void (*fn)(struct cap_request *))
-{
- struct req_list *r,*r2;
- r = (struct req_list *)kmalloc(sizeof(*r),GFP_ATOMIC);
- if (r) {
- r->next = NULL;
- r->type = type;
- r->fn = fn;
- if (!reg_req_list) {
- reg_req_list = r;
- } else {
- for (r2=reg_req_list;
- r2->next && r2->type != type;r2=r2->next) ;
-
- if (r2->type == type) {
- r2->fn = fn;
- kfree_s(r,sizeof(*r));
- } else {
- r2->next = r;
- }
- }
- }
-}
-
-
-
-/* a request has come in on the bif - process it */
-static void bif_intr_receive(struct cap_request *req1)
-{
- struct req_list *r;
- extern void ap_open_reply(struct cap_request *creq);
- struct cap_request req;
-
- if (req1) {
- req = *req1;
- } else {
- /* read the main cap request header */
- read_bif((char *)&req,sizeof(req));
- }
-
- /* service it */
- switch (req.type)
- {
- case REQ_PUTCHAR:
- reply_putchar(&req);
- break;
- case REQ_KILL:
- reply_kill(&req);
- break;
- case REQ_BREAK:
- breakpoint();
- break;
- case REQ_IP:
- reply_ip(&req);
- break;
-#if TOKEN_ARBITRATION
- case REQ_BIF_TOKEN:
- have_token = 1;
- want_bif();
- break;
-#endif
- case REQ_OPENNET:
- net_started = 1;
- break;
- case REQ_BREAD:
- reply_bread(&req);
- break;
- case REQ_BOPEN:
- ap_open_reply(&req);
- break;
- case REQ_BWRITE:
- ap_complete(&req);
- break;
- case REQ_SCHEDULE:
- mpp_schedule(&req);
- break;
-
- default:
- for (r=reg_req_list;r;r=r->next)
- if (r->type == req.type) {
- r->fn(&req);
- return;
- }
- printk("Unknown request %d\n",req.type);
- break;
- }
-}
-
-
-static void bif_dma_complete(void)
-{
- extern int bif_rx(struct sk_buff *skb);
- enum dma_state old_state = dma_state;
- unsigned a;
-
- a = DMA_IN(DMA2_DMST);
-
- if (a & DMA_DMST_AC) return;
-
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_REQ<<DMA_INTR_NORMAL_SH);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_REQ<<DMA_INTR_ERROR_SH);
-
- if (old_state == DMA_INCOMING) {
- if (skb_in) bif_rx(skb_in);
- skb_in = NULL;
- }
- if (bread_req.type != -1) {
- ap_complete(&bread_req);
- bread_req.type = -1;
- }
-
- if (bif_dma_data) {
- kfree_s(bif_dma_data,bif_dma_out_size);
- bif_dma_data = NULL;
- }
-
- if (skb_out) {
- dev_kfree_skb(skb_out);
- skb_out = NULL;
- }
-
- dma_state = DMA_IDLE;
-
- if (a & (AP_INTR_REQ<<DMA_INTR_ERROR_SH)) {
- printk("BIF: got dma error\n");
- }
-}
-
-
-/* handle bif related interrupts. Currently handles 3 interrupts, the
- bif header interrupt, the bif get interrupt and the dma transfer
- complete interrupt */
-static void bif_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned flags;
-
- bif_pt_regs = regs;
-
- save_flags(flags); cli();
-
- mac_dma_complete();
-
- if (dma_state != DMA_IDLE) {
- bif_dma_complete();
- }
-
- bif_reset_interrupts();
-
- while (dma_state == DMA_IDLE && BIF_DATA_WAITING()) {
- bif_intr_receive(NULL);
- }
-
- if (dma_state != DMA_IDLE) {
- bif_dma_complete();
- }
-
- if (dma_state == DMA_IDLE && bif_queue_top && !HAVE_BIF()) {
- want_bif();
- }
-
- if (dma_state == DMA_IDLE && HAVE_BIF()) {
- waiting_for_bif = 0;
- bif_intr_runqueue();
- }
-
- if (dma_state == DMA_IDLE && HAVE_BIF()) {
- release_bif();
- }
-
- restore_flags(flags);
- bif_pt_regs = NULL;
-}
-
-
-/* handle the attention interrupt - used for BIF arbitration */
-static void attn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned flags;
-
- save_flags(flags); cli();
-
- attn_enable();
-
-#if SNET_ARBITRATION
- attn_mask();
- DEBUG(("|bif attn irq %d\n",irq));
-
- if (waiting_for_bif)
- want_bif();
-
- DEBUG(("|bif attn irq %d done\n",irq));
-#endif
-
- bif_interrupt(irq,dev_id,regs);
- restore_flags(flags);
-}
-
-
-void bif_timer(void)
-{
-#if 1
- if (interrupt_driven)
- bif_interrupt(0,NULL,NULL);
-#endif
-}
-
-static void tnet_ip_enable(void)
-{
- tnet_ip_enabled = 1;
- printk("tnet_ip_enabled=%d\n",tnet_ip_enabled);
-}
-
-static void tnet_ip_disable(void)
-{
- tnet_ip_enabled = 0;
- printk("tnet_ip_enabled=%d\n",tnet_ip_enabled);
-}
-
-/* initialise the bif code */
-void ap_bif_init(void)
-{
- int res;
- unsigned long flags;
- printk("doing ap_bif_init()\n");
-
- bif_add_debug_key('+',tnet_ip_enable,"enable Tnet based IP");
- bif_add_debug_key('-',tnet_ip_disable,"disable Tnet based IP");
-
- save_flags(flags); cli();
-
- /* register the BIF interrupt */
- if ((res=request_irq(APBIF_IRQ, bif_interrupt,
- SA_INTERRUPT, "apbif", NULL))) {
- printk("Failed to install bif interrupt handler\n");
- restore_flags(flags);
- return;
- }
-
- /* and the bus get interrupt */
- if ((res=request_irq(APBIFGET_IRQ, bif_interrupt,
- SA_INTERRUPT, "apbifget", NULL))) {
- printk("Failed to install bifget interrupt handler\n");
- restore_flags(flags);
- return;
- }
-
- /* dma complete interrupt */
- if ((res=request_irq(APDMA_IRQ, bif_interrupt, SA_INTERRUPT,
- "apdma", NULL))) {
- printk("Failed to install bifdma interrupt handler\n");
- restore_flags(flags);
- return;
- }
-
- /* attention interrupt */
- if ((res=request_irq(APATTN_IRQ, attn_interrupt, SA_INTERRUPT,
- "apattn", NULL))) {
- printk("Failed to install apattn interrupt handler\n");
- restore_flags(flags);
- return;
- }
-
- printk("Installed bif handlers\n");
-
- /* enable dma-request */
- BIF_OUT(BIF_SDCSR,BIF_SDCSR_DE);
-
- DMA_OUT(DMA2_DCMD,DMA_DCMD_SA);
- DMA_OUT(DMA2_DMST,DMA_DMST_RST);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_REQ<<DMA_INTR_NORMAL_SH);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_MASK<<DMA_INTR_NORMAL_SH);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_REQ<<DMA_INTR_ERROR_SH);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_MASK<<DMA_INTR_ERROR_SH);
-
- /* enable the attention interrupt */
- attn_enable();
-
- DMA_OUT(DMA_BIF_BCMD,DMA_BCMD_SA);
- DMA_OUT(DMA_BIF_BRST,DMA_DMST_RST);
-
- /* from now on we are interrupt driven */
- bread_req.type = -1;
- dma_state = DMA_IDLE;
- interrupt_driven = 1;
- use_dma = 1;
- bif_reset_interrupts();
-
- /* if theres something in the queue then we also want the bus */
- if (bif_queue_top)
- want_bif();
-
- /* tell the host that networking is now OK */
- start_apnet();
-
- printk("bif initialised\n");
-
- restore_flags(flags);
-}
-
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)