diff options
Diffstat (limited to 'arch/sparc/ap1000/bnet.c')
-rw-r--r-- | arch/sparc/ap1000/bnet.c | 1205 |
1 files changed, 0 insertions, 1205 deletions
diff --git a/arch/sparc/ap1000/bnet.c b/arch/sparc/ap1000/bnet.c deleted file mode 100644 index e87d01181..000000000 --- a/arch/sparc/ap1000/bnet.c +++ /dev/null @@ -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); -} - - |