patch-2.3.42 linux/arch/sparc/ap1000/aplib.c
Next file: linux/arch/sparc/ap1000/apmmu.c
Previous file: linux/arch/sparc/ap1000/apinline.h
Back to the patch index
Back to the overall index
- Lines: 497
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.3.41/linux/arch/sparc/ap1000/aplib.c
- Orig date:
Mon Jul 5 20:35:17 1999
diff -u --recursive --new-file v2.3.41/linux/arch/sparc/ap1000/aplib.c linux/arch/sparc/ap1000/aplib.c
@@ -1,496 +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
- */
-
-/* kernel based aplib.
-
- This was initially implemented in user space, but we eventually
- relented when we discovered some really nasty MSC hardware bugs and
- decided to disallow access to the device registers by users. Pity :-(
-
- Andrew Tridgell, November 1996
-*/
-
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-
- #include <asm/ap1000/pgtapmmu.h>
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/aplib.h>
-
-
-extern int *tnet_rel_cid_table;
-extern unsigned _cid, _ncel, _ncelx, _ncely, _cidx, _cidy;
-
-
-/* this is used to stop the task hogging the MSC while paging in data */
-static inline void page_in(char *addr,long size)
-{
- unsigned sum = 0;
- while (size > 0) {
- sum += *(volatile char *)addr;
- addr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-}
-
-
-/* this sets up the aplib structures using info passed in from user space
- it should only be called once, and should be the first aplib call
- it should be followed by APLIB_SYNC
- */
-static inline int aplib_init(struct aplib_init *init)
-{
- struct aplib_struct *aplib;
- int error,i;
- int old_uid;
-
- error = verify_area(VERIFY_READ,init,sizeof(*init));
- if (error) return error;
- error = verify_area(VERIFY_READ,init->phys_cells,
- sizeof(int)*init->numcells);
- if (error) return error;
- error = verify_area(VERIFY_WRITE,
- init->ringbuffer,
- init->ringbuf_size * sizeof(int));
- if (error) return error;
- error = verify_area(VERIFY_WRITE,
- (char *)APLIB_PAGE_BASE,
- APLIB_PAGE_LEN);
- if (error) return error;
-
- if (!MPP_IS_PAR_TASK(current->taskid))
- return -EINVAL;
-
- if (current->aplib)
- return -EINVAL;
-
- aplib = current->aplib = (struct aplib_struct *)APLIB_PAGE_BASE;
-
- /* lock the aplib structure in memory */
- old_uid = current->euid;
- current->euid = 0;
- memset(aplib,0,APLIB_PAGE_LEN);
- error = sys_mlock(aplib,APLIB_PAGE_LEN);
- current->euid = old_uid;
- if (error) {
- printk("mlock1 failed\n");
- return error;
- }
-
- /* lock the ringbuffer in memory */
- old_uid = current->euid;
- current->euid = 0;
- memset(init->ringbuffer,0,init->ringbuf_size*4);
- error = sys_mlock(init->ringbuffer,init->ringbuf_size*4);
- current->euid = old_uid;
- if (error) {
- printk("mlock2 failed\n");
- return error;
- }
-
- aplib->ringbuf = init->ringbuffer;
- aplib->ringbuf_size = init->ringbuf_size;
- aplib->numcells = init->numcells;
- aplib->cid = init->cid;
- aplib->tid = current->taskid;
- aplib->numcells_x = init->numcells_x;
- aplib->numcells_y = init->numcells_y;
- aplib->cidx = init->cid % init->numcells_x;
- aplib->cidy = init->cid / init->numcells_x;
-
- aplib->physical_cid = (unsigned *)(aplib+1);
- aplib->rel_cid = aplib->physical_cid + init->numcells;
-
- if ((char *)(aplib->rel_cid + init->numcells) >
- (char *)(APLIB_PAGE_BASE + APLIB_PAGE_LEN)) {
- return -ENOMEM;
- }
-
- memcpy(aplib->physical_cid,init->phys_cells,
- sizeof(int)*init->numcells);
-
- /* initialise the relative cid table */
- for (i=0;i<aplib->numcells;i++)
- aplib->rel_cid[i] =
- tnet_rel_cid_table[aplib->physical_cid[i]];
-
- return 0;
-}
-
-
-/* n == which sync line (ignored)
- returns logical or of the stat values across the cells (1 bit resolution)
-
- This has to be done very carefully as the tasks can startup on the cells
- in any order, so we don't know which tasks have started up when this
- is called
-*/
-static inline int aplib_sync(int n,int stat)
-{
- struct aplib_struct *aplib = current->aplib;
- static int sync_flags[MPP_NUM_TASKS];
- int i,err;
- int tsk = current->taskid;
-
- stat &= 1;
-
- if (aplib->numcells < 2)
- return stat;
-
- tsk -= MPP_TASK_BASE;
-
- if (aplib->cid == 0) {
- if ((err=wait_on_int(&sync_flags[tsk],
- aplib->numcells-1,5)))
- return err;
- sync_flags[tsk] = 0;
- if (aplib->numcells == _ncel) {
- ap_bput(0,0,0,(u_long)&sync_flags[tsk],0);
- } else {
- for (i=1;i<aplib->numcells;i++)
- ap_put(aplib->physical_cid[i],
- 0,0,0,(u_long)&sync_flags[tsk],0);
- }
- } else {
- ap_put(aplib->physical_cid[0],
- 0,0,0,(u_long)&sync_flags[tsk],0);
- if ((err=wait_on_int(&sync_flags[tsk],1,5)))
- return err;
- sync_flags[tsk] = 0;
- }
-
- /* I haven't written the xy_ calls yet ... */
- /* aplib_xy_ior(stat,&stat); */
-
- return stat;
-}
-
-
-
-static inline void _putget(unsigned q,
- unsigned rcell,
- unsigned *src_addr,
- unsigned size,unsigned *dest_addr,
- unsigned *dest_flag,unsigned *src_flag)
-{
- unsigned flags;
- volatile unsigned *entry = (volatile unsigned *)q;
-
- save_flags(flags); cli();
-
- *entry = rcell;
- *entry = size;
- *entry = (unsigned)dest_addr;
- *entry = 0;
- *entry = (unsigned)dest_flag;
- *entry = (unsigned)src_flag;
- *entry = (unsigned)src_addr;
- *entry = 0;
-
- restore_flags(flags);
-}
-
-
-/* a basic put() operation. Note the avoidance of odd word boundaries
- and transfers sizes beyond what the hardware can deal with */
-static inline int aplib_put(struct aplib_putget *put)
-{
- int error;
- struct aplib_struct *aplib = current->aplib;
-
- error = verify_area(VERIFY_WRITE,put,sizeof(*put));
- if (error) return error;
-
- if (put->cid >= aplib->numcells)
- return -EINVAL;
-
- do {
- int n;
-
- if (put->size && (((unsigned)put->src_addr) & 4)) {
- n = 1;
- } else if (put->size > MAX_PUT_SIZE) {
- n = MAX_PUT_SIZE;
- } else {
- n = put->size;
- }
-
- put->size -= n;
-
- page_in((char *)put->src_addr,n<<2);
-
- _putget(MSC_PUT_QUEUE,
- aplib->rel_cid[put->cid],
- put->src_addr,
- n,
- put->dest_addr,
- put->size?0:put->dest_flag,
- put->size?0:put->src_flag);
-
- put->dest_addr += n;
- put->src_addr += n;
- } while (put->size);
-
- if (put->ack) {
- aplib->ack_request++;
- _putget(MSC_GET_QUEUE,
- aplib->rel_cid[put->cid],
- 0, 0, 0,
- &aplib->ack_flag, 0);
- }
-
- return 0;
-}
-
-
-/* a basic get() operation */
-static inline int aplib_get(struct aplib_putget *get)
-{
- struct aplib_struct *aplib = current->aplib;
- int error = verify_area(VERIFY_WRITE,get,sizeof(*get));
- if (error) return error;
-
- if (get->cid >= aplib->numcells)
- return -EINVAL;
-
- do {
- int n;
-
- if (get->size && (((unsigned)get->src_addr) & 4)) {
- n = 1;
- } else if (get->size > MAX_PUT_SIZE) {
- n = MAX_PUT_SIZE;
- } else {
- n = get->size;
- }
-
- get->size -= n;
-
- page_in((char *)get->dest_addr,n<<2);
-
- _putget(MSC_GET_QUEUE,
- aplib->rel_cid[get->cid],
- get->src_addr,
- n,
- get->dest_addr,
- get->size?0:get->dest_flag,
- get->size?0:get->src_flag);
-
- get->dest_addr += n;
- get->src_addr += n;
- } while (get->size);
-
- return 0;
-}
-
-
-/* we have received a protocol message - now do the get
- This function is called from interrupt level with interrupts
- disabled
-
- note that send->size is now in words
-*/
-void aplib_bigrecv(unsigned *msgp)
-{
- struct aplib_struct *aplib;
- struct aplib_send *send = (struct aplib_send *)(msgp+2);
- unsigned tid = (msgp[1]&0x3FF);
- unsigned cid = (msgp[0]>>22)&0x1FF;
- unsigned octx, ctx;
- struct task_struct *tsk;
- unsigned room;
-
- tsk = task[tid];
- if (!tsk || !tsk->aplib)
- return;
-
- octx = apmmu_get_context();
- ctx = MPP_TASK_TO_CTX(tid);
- if (octx != ctx)
- apmmu_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 < (send->size+2)) {
- send_sig(SIGLOST,tsk,1);
- goto finished;
- }
-
- aplib->ringbuf[aplib->write_pointer++] = send->info1;
- aplib->ringbuf[aplib->write_pointer++] = send->info2;
-
- /* now finally do the get() */
- _putget(MSC_GET_QUEUE,
- aplib->rel_cid[cid],
- send->src_addr,
- send->size,
- &aplib->ringbuf[aplib->write_pointer],
- &aplib->rbuf_flag2,
- send->flag_addr);
-
- aplib->write_pointer += send->size;
- if (aplib->write_pointer >= aplib->ringbuf_size)
- aplib->write_pointer -= aplib->ringbuf_size;
-
-finished:
- if (octx != ctx)
- apmmu_set_context(octx);
-}
-
-
-/* note the 8 byte alignment fix for the MSC bug */
-static inline int aplib_send(struct aplib_send *send)
-{
- struct aplib_struct *aplib = current->aplib;
- int wordSize;
- int byteAlign, byteFix;
- u_long src;
- u_long info1, info2;
- volatile unsigned *q = (volatile unsigned *)MSC_SEND_QUEUE_S;
- extern long system_recv_flag;
- int error;
- unsigned flags, rcell;
- unsigned flag_ptr;
-
- error = verify_area(VERIFY_WRITE,send,sizeof(*send));
- if (error) return error;
-
- if (send->cid >= aplib->numcells)
- return -EINVAL;
-
- if (send->tag == RBUF_SYSTEM || send->tag == RBUF_BIGSEND)
- return -EINVAL;
-
- error = verify_area(VERIFY_READ,(char *)send->src_addr,send->size);
- if (error) return error;
-
- page_in((char *)send->src_addr,send->size);
-
- rcell = aplib->rel_cid[send->cid];
-
- byteAlign = send->src_addr & 0x3;
- byteFix = send->size & 0x3;
-
- wordSize = (send->size + byteAlign + 3) >> 2;
-
- src = send->src_addr & ~3;
-
- /* this handles the MSC alignment bug */
- if (wordSize > 1 &&
- (src & 4)) {
- info1 |= 0x80000000;
- src -= 4;
- wordSize++;
- }
-
- info1 = (aplib->cid<<22) | (byteFix<<20) | wordSize;
- info2 = (send->tag<<28) | (byteAlign<<26) |
- (send->type<<10) | aplib->tid;
- flag_ptr = (unsigned)&send->flag;
-
- if (send->size > SMALL_SEND_THRESHOLD) {
- send->info1 = info1;
- send->info2 = info2;
- send->size = wordSize;
- send->src_addr = src;
- send->flag_addr = (unsigned)&send->flag;
- flag_ptr = 0;
-
- wordSize = sizeof(*send)>>2;
- src = (unsigned)send;
-
- info1 = (aplib->cid<<22) | wordSize;
- info2 = (RBUF_BIGSEND<<28) | aplib->tid;
- }
-
- save_flags(flags); cli();
-
- *q = rcell;
- *q = wordSize;
- *q = (u_long)&system_recv_flag;
- *q = flag_ptr;
- *q = (u_long)src;
- *q = 0;
- *q = info1;
- *q = info2;
-
- restore_flags(flags);
-
- return 0;
-}
-
-
-static inline int aplib_probe(void)
-{
- tnet_check_completion();
- return 0;
-}
-
-static inline int aplib_poll(unsigned counter)
-{
- struct aplib_struct *aplib = current->aplib;
-
- while (counter == aplib->rbuf_flag1 + aplib->rbuf_flag2) {
- tnet_check_completion();
- if (current->need_resched)
- break;
- if (signal_pending(current)) break;
- }
- return 0;
-}
-
-int sys_aplib(unsigned call,int a1,int a2,int a3,int a4)
-{
-
- if (!current->aplib && call != APLIB_INIT)
- return -EINVAL;
-
- switch (call) {
- case APLIB_INIT:
- return aplib_init((struct aplib_init *)a1);
-
- case APLIB_SYNC:
- return aplib_sync(a1,a2);
-
- case APLIB_PUT:
- return aplib_put((struct aplib_putget *)a1);
-
- case APLIB_GET:
- return aplib_get((struct aplib_putget *)a1);
-
- case APLIB_SEND:
- return aplib_send((struct aplib_send *)a1);
-
- case APLIB_PROBE:
- return aplib_probe();
-
- case APLIB_POLL:
- return aplib_poll((unsigned)a1);
- }
-
- return -EINVAL;
-}
-
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)