00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <linux/kernel.h>
00021 #include <linux/module.h>
00022 #include <linux/version.h>
00023 #include <linux/timer.h>
00024 #include <linux/unistd.h>
00025 #include <asm/uaccess.h>
00026
00027 #include <net/ip.h>
00028
00029 #include <rtai_schedcore.h>
00030 #include <rtai_prinher.h>
00031 #include <rtai_netrpc.h>
00032 #include <rtai_sem.h>
00033 #include <rtai_mbx.h>
00034
00035 MODULE_LICENSE("GPL");
00036
00037 #define COMPILE_ANYHOW // RTNet is not available but we want to compile anyhow
00038 #include <rtdm.h>
00039 #include "rtnetP.h"
00040
00041
00042
00043 #define SOFT_RTNET 1
00044
00045 #ifdef CONFIG_RTAI_NETRPC_RTNET
00046 #define HARD_RTNET 1
00047 #else
00048 #define HARD_RTNET 0
00049 #endif
00050
00051
00052
00053 #if HARD_RTNET
00054 #ifndef COMPILE_ANYHOW
00055 #include <rtnet.h>
00056 #endif
00057 #define MSG_SOFT 0
00058 #define MSG_HARD 1
00059 #define hard_rt_socket rt_dev_socket
00060 #define hard_rt_bind rt_dev_bind
00061 #define hard_rt_close rt_dev_close
00062 #define hard_rt_socket_callback hard_rt_socket_callback
00063 #define hard_rt_recvfrom rt_dev_recvfrom
00064 #define hard_rt_sendto rt_dev_sendto
00065 #else
00066 #define MSG_SOFT 0
00067 #define MSG_HARD 0
00068 #define hard_rt_socket(a, b, c) portslot[i].socket[0]
00069 #define hard_rt_bind(a, b, c)
00070 #define hard_rt_close(a)
00071 #define hard_rt_socket_callback soft_rt_socket_callback
00072 #define hard_rt_recvfrom soft_rt_recvfrom
00073 #define hard_rt_sendto soft_rt_sendto
00074 #endif
00075
00076 #define LOCALHOST "127.0.0.1"
00077
00078 #define BASEPORT (NETRPC_BASEPORT)
00079
00080 #define NETRPC_STACK_SIZE 6000
00081
00082 static unsigned long MaxStubs = MAX_STUBS;
00083 RTAI_MODULE_PARM(MaxStubs, ulong);
00084 static int MaxStubsMone;
00085
00086 static unsigned long MaxSocks = MAX_SOCKS;
00087 RTAI_MODULE_PARM(MaxSocks, ulong);
00088
00089 static int StackSize = NETRPC_STACK_SIZE;
00090 RTAI_MODULE_PARM(StackSize, int);
00091
00092 static char *ThisNode = LOCALHOST;
00093 RTAI_MODULE_PARM(ThisNode, charp);
00094
00095 static char *ThisSoftNode = 0;
00096 RTAI_MODULE_PARM(ThisSoftNode, charp);
00097
00098 static char *ThisHardNode = 0;
00099 RTAI_MODULE_PARM(ThisHardNode, charp);
00100
00101 #define MAX_DFUN_EXT 16
00102 static struct rt_fun_entry *rt_net_rpc_fun_ext[MAX_DFUN_EXT];
00103
00104 static unsigned long this_node[2];
00105
00106 #define PRTSRVNAME 0xFFFFFFFF
00107 struct portslot_t { struct portslot_t *p; long task; int indx, place, socket[2], hard; unsigned long long owner; SEM sem; void *msg; struct sockaddr_in addr; MBX *mbx; unsigned long name; RTIME timeout; int recovered; };
00108 static spinlock_t portslot_lock = SPIN_LOCK_UNLOCKED;
00109 static volatile int portslotsp;
00110
00111 static spinlock_t stub_lock = SPIN_LOCK_UNLOCKED;
00112 static volatile int stubssp = 1;
00113
00114
00115 static struct portslot_t *portslot;
00116 static struct sockaddr_in SPRT_ADDR;
00117 struct recovery_msg { int hard, priority; unsigned long long owner; struct sockaddr addr; };
00118 static struct { int in, out; struct recovery_msg *msg; } recovery;
00119 static spinlock_t recovery_lock = SPIN_LOCK_UNLOCKED;
00120
00121 #if HARD_RTNET
00122 int hard_rt_socket_callback(int fd, void *func, void *arg)
00123 {
00124 struct rtnet_callback args = { func, arg };
00125 return(rt_dev_ioctl(fd, RTNET_RTIOC_CALLBACK, &args));
00126 }
00127 #endif
00128
00129 static inline struct portslot_t *get_portslot(void)
00130 {
00131 unsigned long flags;
00132
00133 flags = rt_spin_lock_irqsave(&portslot_lock);
00134 if (portslotsp < MaxSocks) {
00135 struct portslot_t *p;
00136 p = portslot[portslotsp++].p;
00137 rt_spin_unlock_irqrestore(flags, &portslot_lock);
00138 return p;
00139 }
00140 rt_spin_unlock_irqrestore(flags, &portslot_lock);
00141 return 0;
00142 }
00143
00144 static inline int gvb_portslot(struct portslot_t *portslotp)
00145 {
00146 unsigned long flags;
00147
00148 flags = rt_spin_lock_irqsave(&portslot_lock);
00149 if (portslotsp > MaxStubs) {
00150 struct portslot_t *tmp_p;
00151 int tmp_place;
00152 tmp_p = portslot[--portslotsp].p;
00153 tmp_place = portslotp->place;
00154 portslotp->place = portslotsp;
00155 portslot[portslotsp].p = portslotp;
00156 tmp_p->place = tmp_place;
00157 portslot[tmp_place].p = tmp_p;
00158 rt_spin_unlock_irqrestore(flags, &portslot_lock);
00159 return 0;
00160 }
00161 rt_spin_unlock_irqrestore(flags, &portslot_lock);
00162 return -EINVAL;
00163 }
00164
00165 static inline void check_portslot(unsigned long node, int port, struct portslot_t **p)
00166 {
00167
00168 int i;
00169 struct portslot_t *p_old;
00170
00171 p_old = *p;
00172
00173 for (i = MaxStubs; i < portslotsp; i++) {
00174 if (portslot[i].p->addr.sin_port == htons(port) && portslot[i].p->addr.sin_addr.s_addr == node) {
00175 *p = portslot[i].p;
00176 break;
00177 }
00178 }
00179
00180 if (p_old != *p) {
00181 gvb_portslot(p_old);
00182 }
00183
00184 }
00185
00186 #define NETRPC_TIMER_FREQ 50
00187 static struct timer_list timer;
00188 static SEM timer_sem;
00189
00190 static void timer_fun(unsigned long none)
00191 {
00192 if (timer_sem.count < 0) {
00193 rt_sem_signal(&timer_sem);
00194 timer.expires = jiffies + HZ/NETRPC_TIMER_FREQ;
00195 add_timer(&timer);
00196 }
00197 }
00198
00199 static int (*encode)(struct portslot_t *portslotp, void *msg, int size, int where);
00200 static int (*decode)(struct portslot_t *portslotp, void *msg, int size, int where);
00201
00202 void set_netrpc_encoding(void *encode_fun, void *decode_fun, void *ext)
00203 {
00204 encode = encode_fun;
00205 decode = decode_fun;
00206 rt_net_rpc_fun_ext[1] = ext;
00207 }
00208
00209 struct req_rel_msg { long long op, port, priority, hard; unsigned long long owner, name, rem_node, chkspare;};
00210
00211 struct par_t { long long mach, priority, base_priority, argsize, rsize, fun_ext_timed, type; unsigned long long owner, partypes; long a[1]; };
00212
00213 struct reply_t { long long wsize, w2size, myport; unsigned long long retval; char msg[1], msg1[1]; };
00214
00215 static inline int argconv(void *ain, void *aout, int send_mach, int argsize, unsigned int partypes)
00216 {
00217 #define recv_mach (sizeof(long))
00218 int argsizeout;
00219 if (send_mach == recv_mach) {
00220 memcpy(aout, ain, argsize);
00221 return argsize;
00222 }
00223 argsizeout = 0;
00224 if (send_mach == 4 && recv_mach == 8) {
00225 long *out = aout;
00226 int *in = ain;
00227 while (argsize) {
00228 argsize -= 4;
00229 argsizeout += 8;
00230 switch(partypes & WDWMSK) {
00231 case SINT:
00232 *out++ = *in++;
00233 break;
00234 case UINT:
00235 *out++ = (unsigned int)*in++;
00236 break;
00237 case VADR:
00238 *out++ = reset_kadr(*in++);
00239 break;
00240 case RTIM:
00241 *out++ = (long)*in++;
00242 in++;
00243 argsize -= 4;
00244 break;
00245 }
00246 partypes >>= WDW;
00247 }
00248 } else {
00249 unsigned long *out = aout;
00250 unsigned long long *in = ain;
00251 while (argsize) {
00252 argsize -= 8;
00253 argsizeout += 4;
00254 switch(partypes & WDWMSK) {
00255 case SINT:
00256 case UINT:
00257 case VADR:
00258 *out++ = *in++;
00259 break;
00260 case RTIM:
00261 *((unsigned long long *)out++) = *in++;
00262 out++;
00263 argsizeout += 4;
00264 break;
00265 }
00266 partypes >>= WDW;
00267 }
00268 }
00269 return argsizeout;
00270 #undef recv_mach
00271 }
00272
00273 static void net_resume_task(int sock, struct portslot_t *p)
00274 {
00275 int all_ok;
00276 RT_TASK *my;
00277 my = _rt_whoami();
00278 all_ok = 1;
00279 if ((p->indx > 0) && (p->indx < MaxStubs)) {
00280 if (!((p->task) && (p->hard == my->is_hard))) {
00281 all_ok = 0;
00282 }
00283 }
00284 if (all_ok) {
00285 rt_sem_signal(&p->sem);
00286 } else {
00287 long i;
00288 unsigned long flags;
00289 struct par_t *par;
00290 char msg[MAX_MSG_SIZE];
00291 struct sockaddr *addr;
00292 par = (void *)msg;
00293 addr = (struct sockaddr*)&p->addr;
00294
00295 if (my->is_hard) {
00296 while (hard_rt_recvfrom(p->socket[1], msg, MAX_MSG_SIZE, 0, addr, (void *)&i) == -EAGAIN);
00297 } else {
00298 soft_rt_recvfrom(p->socket[0], msg, MAX_MSG_SIZE, 0, addr, &i);
00299 }
00300
00301 flags = rt_spin_lock_irqsave(&recovery_lock);
00302 recovery.msg[recovery.in].priority = par->priority;
00303 recovery.msg[recovery.in].owner = par->owner;
00304 recovery.msg[recovery.in].addr = *addr;
00305 recovery.msg[recovery.in].hard = my->is_hard;
00306 recovery.in = (recovery.in + 1) & MaxStubsMone;
00307 rt_spin_unlock_irqrestore(flags, &recovery_lock);
00308 rt_sem_signal(&portslot[0].sem);
00309 }
00310 }
00311
00312 int get_min_tasks_cpuid(void);
00313 int set_rtext(RT_TASK *, int, int, void(*)(void), unsigned int, void *);
00314 int clr_rtext(RT_TASK *);
00315 void rt_schedule_soft(RT_TASK *);
00316
00317 static inline int soft_rt_fun_call(RT_TASK *task, void *fun, void *arg)
00318 {
00319 union { long long ll; long l; } retval;
00320 task->fun_args[0] = (long)arg;
00321 ((struct fun_args *)task->fun_args)->fun = fun;
00322 rt_schedule_soft(task);
00323 retval.ll = task->retval;
00324 return (int)retval.l;
00325 }
00326
00327 static inline long long soft_rt_genfun_call(RT_TASK *task, void *fun, void *args, int argsize)
00328 {
00329 memcpy(task->fun_args, args, argsize);
00330 ((struct fun_args *)task->fun_args)->fun = fun;
00331 rt_schedule_soft(task);
00332 return task->retval;
00333 }
00334
00335 extern void rt_daemonize(void);
00336 static void thread_fun(RT_TASK *task)
00337 {
00338 if (!set_rtext(task, task->fun_args[3], 0, 0, get_min_tasks_cpuid(), 0)) {
00339 rt_daemonize();
00340 sigfillset(¤t->blocked);
00341 rtai_set_linux_task_priority(current, SCHED_FIFO, MIN_LINUX_RTPRIO);
00342 soft_rt_fun_call(task, rt_task_suspend, task);
00343 ((void (*)(long))task->fun_args[1])(task->fun_args[2]);
00344 task->fun_args[1] = 0;
00345 }
00346 }
00347
00348 static int soft_kthread_init(RT_TASK *task, long fun, long arg, int priority)
00349 {
00350 task->magic = task->state = 0;
00351 (task->fun_args = (long *)(task + 1))[1] = fun;
00352 task->fun_args[2] = arg;
00353 task->fun_args[3] = priority;
00354 if (kernel_thread((void *)thread_fun, task, 0) > 0) {
00355 while (task->state != (RT_SCHED_READY | RT_SCHED_SUSPENDED)) {
00356 current->state = TASK_INTERRUPTIBLE;
00357 schedule_timeout(HZ/NETRPC_TIMER_FREQ);
00358 }
00359 return 0;
00360 }
00361 return -ENOEXEC;
00362 }
00363
00364 static int soft_kthread_delete(RT_TASK *task)
00365 {
00366 task->fun_args[1] = 1;
00367 while (task->fun_args[1]) {
00368 rt_task_masked_unblock(task, ~RT_SCHED_READY);
00369 current->state = TASK_INTERRUPTIBLE;
00370 schedule_timeout(HZ/NETRPC_TIMER_FREQ);
00371 }
00372 clr_rtext(task);
00373 return 0;
00374 }
00375
00376 #define ADRSZ sizeof(struct sockaddr)
00377
00378 static inline int get_stub(unsigned long long owner)
00379 {
00380 unsigned long flags;
00381 int i;
00382
00383 flags = rt_spin_lock_irqsave(&stub_lock);
00384 if (stubssp < MaxStubsMone) {
00385 struct portslot_t *p;
00386 i = 1;
00387 while(((p = portslot[i].p)->owner != owner) && (i < stubssp)) {
00388 i++;
00389 }
00390 if (p->owner != owner) {
00391 p = portslot[stubssp++].p;
00392 p->owner = owner;
00393 }
00394 rt_spin_unlock_irqrestore(flags, &stub_lock);
00395 return p->indx;
00396 }
00397 rt_spin_unlock_irqrestore(flags, &stub_lock);
00398 return 0;
00399 }
00400
00401 static inline int gvb_stub(int slot, unsigned long long owner)
00402 {
00403 unsigned long flags;
00404 RT_TASK *task;
00405
00406 flags = rt_spin_lock_irqsave(&stub_lock);
00407 if (stubssp > 1) {
00408 if (slot > 0 && slot < MaxStubs) {
00409 if (portslot[slot].owner == owner) {
00410 struct portslot_t *tmp_p;
00411 int tmp_place;
00412 task = (RT_TASK *)portslot[slot].task;
00413 portslot[slot].task = 0;
00414 portslot[slot].owner = 0;
00415 tmp_p = portslot[--stubssp].p;
00416 tmp_place = portslot[slot].place;
00417 portslot[slot].place = stubssp;
00418 portslot[stubssp].p = &portslot[slot];
00419 tmp_p->place = tmp_place;
00420 portslot[tmp_place].p = tmp_p;
00421 slot += BASEPORT;
00422 rt_spin_unlock_irqrestore(flags, &stub_lock);
00423 if (task->is_hard) {
00424 rt_task_delete(task);
00425 } else {
00426 soft_kthread_delete(task);
00427 }
00428 kfree(task);
00429 } else {
00430 slot = !portslot[slot].owner ? slot + BASEPORT : -ENXIO;
00431 rt_spin_unlock_irqrestore(flags, &stub_lock);
00432 }
00433 } else {
00434 rt_spin_unlock_irqrestore(flags, &stub_lock);
00435 }
00436 return slot;
00437 }
00438 rt_spin_unlock_irqrestore(flags, &stub_lock);
00439 return -EINVAL;
00440 }
00441
00442 static inline int find_stub(unsigned long long owner)
00443 {
00444 unsigned long flags;
00445 int i;
00446 struct portslot_t *p;
00447 i = 1;
00448 flags = rt_spin_lock_irqsave(&stub_lock);
00449 while(((p = portslot[i].p)->owner != owner) && (i < stubssp)) {
00450 i++;
00451 }
00452 rt_spin_unlock_irqrestore(flags, &stub_lock);
00453 return p->owner != owner ? 0 : p->indx;
00454 }
00455
00456 static void soft_stub_fun(struct portslot_t *portslotp)
00457 {
00458 char msg[MAX_MSG_SIZE];
00459 struct sockaddr *addr;
00460 RT_TASK *task;
00461 SEM *sem;
00462 struct par_t *par;
00463 long wsize, w2size, sock;
00464 long *ain;
00465 long type;
00466
00467 addr = (struct sockaddr *)&portslotp->addr;
00468 sock = portslotp->socket[0];
00469 sem = &portslotp->sem;
00470 ain = (par = (void *)msg)->a;
00471 task = (RT_TASK *)portslotp->task;
00472 sprintf(current->comm, "SFTSTB-%ld", sock);
00473
00474 recvrys:
00475
00476 while (soft_rt_fun_call(task, rt_sem_wait, sem) < RTE_LOWERR) {
00477 wsize = soft_rt_recvfrom(sock, msg, MAX_MSG_SIZE, 0, addr, &w2size);
00478 if (decode) {
00479 decode(portslotp, msg, wsize, RPC_SRV);
00480 }
00481 if (portslotp->owner != par->owner) {
00482 unsigned long flags;
00483
00484 flags = rt_spin_lock_irqsave(&recovery_lock);
00485 recovery.msg[recovery.in].priority = par->priority;
00486 recovery.msg[recovery.in].owner = par->owner;
00487 recovery.msg[recovery.in].addr = *addr;
00488 recovery.msg[recovery.in].hard = 0;
00489 recovery.in = (recovery.in + 1) & MaxStubsMone;
00490 rt_spin_unlock_irqrestore(flags, &recovery_lock);
00491 rt_sem_signal(&portslot[0].sem);
00492 } else {
00493 int argsize;
00494 long a[par->argsize/sizeof(long) + 1];
00495 if(par->priority >= 0 && par->priority < RT_SCHED_LINUX_PRIORITY) {
00496 if ((wsize = par->priority) < task->priority) {
00497 task->priority = wsize;
00498 rtai_set_linux_task_priority(task->lnxtsk, task->lnxtsk->policy, wsize >= MAX_LINUX_RTPRIO ? MIN_LINUX_RTPRIO : MAX_LINUX_RTPRIO - wsize);
00499 }
00500 task->base_priority = par->base_priority;
00501 }
00502 argsize = argconv(ain, a, par->mach, par->argsize, par->partypes);
00503 type = par->type;
00504 if (par->rsize) {
00505 a[USP_RBF1(type) - 1] = (long)((char *)ain + par->argsize);
00506 }
00507 if (NEED_TO_W(type)) {
00508 wsize = USP_WSZ1(type);
00509 wsize = wsize ? a[wsize - 1] : par->mach;
00510 } else {
00511 wsize = 0;
00512 }
00513 if (NEED_TO_W2ND(type)) {
00514 w2size = USP_WSZ2(type);
00515 w2size = w2size ? a[w2size - 1] : par->mach;
00516 } else {
00517 w2size = 0;
00518 }
00519 do {
00520 struct msg_t { struct reply_t arg; char bufspace[wsize + w2size]; } arg;
00521 arg.arg.myport = 0;
00522 if (wsize > 0) {
00523 arg.arg.wsize = wsize;
00524 a[USP_WBF1(type) - 1] = (long)arg.arg.msg;
00525 } else {
00526 arg.arg.wsize = 0;
00527 }
00528 if (w2size > 0) {
00529 arg.arg.w2size = w2size;
00530 a[USP_WBF2(type) - 1] = (long)(arg.arg.msg + arg.arg.wsize);
00531 } else {
00532 arg.arg.w2size = 0;
00533 }
00534 #ifndef NETRPC_ALIGN_RTIME
00535 if ((wsize = TIMED(par->fun_ext_timed) - 1) >= 0) {
00536 #else
00537 if ((wsize = TIMED(par->fun_ext_timed)) > 0) {
00538 wsize += (NETRPC_ALIGN_RTIME(wsize) - 1);
00539 #endif
00540 *((long long *)(a + wsize)) = nano2count(*((long long *)(a + wsize)));
00541 }
00542 arg.arg.retval = soft_rt_genfun_call(task, rt_net_rpc_fun_ext[EXT(par->fun_ext_timed)][FUN(par->fun_ext_timed)].fun, a, argsize);
00543 soft_rt_sendto(sock, &arg, encode ? encode(portslotp, &arg, sizeof(struct msg_t), RPC_RTR) : sizeof(struct msg_t), 0, addr, ADRSZ);
00544 } while (0);
00545 }
00546 }
00547 if (portslotp->recovered) {
00548 struct reply_t arg;
00549 portslotp->recovered = 0;
00550 arg.myport = sock + BASEPORT;
00551 arg.retval = portslotp->owner;
00552 soft_rt_sendto(sock, &arg, encode ? encode(portslotp, &arg, sizeof(struct reply_t), RPC_RTR) : sizeof(struct reply_t), 0, addr, ADRSZ);
00553 goto recvrys;
00554 }
00555
00556 }
00557
00558 static void hard_stub_fun(struct portslot_t *portslotp)
00559 {
00560 char msg[MAX_MSG_SIZE];
00561 struct sockaddr *addr;
00562 RT_TASK *task;
00563 SEM *sem;
00564 struct par_t *par;
00565 long wsize, w2size, sock;
00566 long *ain;
00567 long type;
00568
00569 addr = (struct sockaddr *)&portslotp->addr;
00570 sock = portslotp->socket[1];
00571 sem = &portslotp->sem;
00572 ain = (par = (void *)msg)->a;
00573 task = (RT_TASK *)portslotp->task;
00574 if (task->lnxtsk) {
00575 sprintf(current->comm, "HRDSTB-%ld", sock);
00576 }
00577
00578 recvryh:
00579
00580 while (rt_sem_wait(sem) < RTE_LOWERR) {
00581 wsize = hard_rt_recvfrom(sock, msg, MAX_MSG_SIZE, 0, addr, (void *)&w2size);
00582 if (decode) {
00583 decode(portslotp, msg, wsize, RPC_SRV);
00584 }
00585 if (portslotp->owner != par->owner) {
00586 unsigned long flags;
00587
00588 flags = rt_spin_lock_irqsave(&recovery_lock);
00589 recovery.msg[recovery.in].priority = par->priority;
00590 recovery.msg[recovery.in].owner = par->owner;
00591 recovery.msg[recovery.in].addr = *addr;
00592 recovery.msg[recovery.in].hard = 1;
00593 recovery.in = (recovery.in + 1) & MaxStubsMone;
00594 rt_spin_unlock_irqrestore(flags, &recovery_lock);
00595 rt_sem_signal(&portslot[0].sem);
00596 } else {
00597 int argsize;
00598 long a[par->argsize/sizeof(long) + 1];
00599 if(par->priority >= 0 && par->priority < RT_SCHED_LINUX_PRIORITY) {
00600 if ((wsize = par->priority) < task->priority) {
00601 task->priority = wsize;
00602 }
00603 task->base_priority = par->base_priority;
00604 }
00605 argsize = argconv(ain, a, par->mach, par->argsize, par->partypes);
00606 type = par->type;
00607 if (par->rsize) {
00608 a[USP_RBF1(type) - 1] = (long)((char *)ain + par->argsize);
00609 }
00610 if (NEED_TO_W(type)) {
00611 wsize = USP_WSZ1(type);
00612 wsize = wsize ? a[wsize - 1] : par->mach;
00613 } else {
00614 wsize = 0;
00615 }
00616 if (NEED_TO_W2ND(type)) {
00617 w2size = USP_WSZ2(type);
00618 w2size = w2size ? a[w2size - 1] : par->mach;
00619 } else {
00620 w2size = 0;
00621 }
00622 do {
00623 struct msg_t { struct reply_t arg; char bufspace[wsize + w2size]; } arg;
00624 arg.arg.myport = 0;
00625 if (wsize > 0) {
00626 arg.arg.wsize = wsize;
00627 a[USP_WBF1(type) - 1] = (long)arg.arg.msg;
00628 } else {
00629 arg.arg.wsize = 0;
00630 }
00631 if (w2size > 0) {
00632 arg.arg.w2size = w2size;
00633 a[USP_WBF2(type) - 1] = (long)(arg.arg.msg + arg.arg.wsize);
00634 } else {
00635 arg.arg.w2size = 0;
00636 }
00637 #ifndef NETRPC_ALIGN_RTIME
00638 if ((wsize = TIMED(par->fun_ext_timed) - 1) >= 0) {
00639 #else
00640 if ((wsize = TIMED(par->fun_ext_timed)) > 0) {
00641 wsize += (NETRPC_ALIGN_RTIME(wsize) - 1);
00642 #endif
00643 *((long long *)(a + wsize)) = nano2count(*((long long *)(a + wsize)));
00644 }
00645 arg.arg.retval = ((long long (*)(long, ...))rt_net_rpc_fun_ext[EXT(par->fun_ext_timed)][FUN(par->fun_ext_timed)].fun)(RTAI_FUN_A);
00646 hard_rt_sendto(sock, &arg, encode ? encode(portslotp, &arg, sizeof(struct msg_t), RPC_RTR) : sizeof(struct msg_t), 0, addr, ADRSZ);
00647 } while (0);
00648 }
00649 }
00650 if (portslotp->recovered) {
00651 struct reply_t arg;
00652 portslotp->recovered = 0;
00653 arg.myport = sock + BASEPORT;
00654 arg.retval = portslotp->owner;
00655 hard_rt_sendto(sock, &arg, encode ? encode(portslotp, &arg, sizeof(struct reply_t), RPC_RTR) : sizeof(struct reply_t), 0, addr, ADRSZ);
00656 goto recvryh;
00657 }
00658 rt_task_suspend(task);
00659 }
00660
00661 static void port_server_fun(RT_TASK *port_server)
00662 {
00663 short recovered;
00664 long i, rsize;
00665 RT_TASK *task;
00666 struct sockaddr *addr;
00667 struct req_rel_msg msg;
00668
00669 addr = (struct sockaddr *)&portslot[0].addr;
00670 sprintf(current->comm, "PRTSRV");
00671
00672 while (soft_rt_fun_call(port_server, rt_sem_wait, &portslot[0].sem) < RTE_LOWERR) {
00673 if (recovery.out != recovery.in) {
00674 recovered = 1;
00675 msg.priority = recovery.msg[recovery.out].priority;
00676 msg.hard = recovery.msg[recovery.out].hard;
00677 msg.owner = recovery.msg[recovery.out].owner;
00678 msg.name = TSK_FRM_WNR(recovery.msg[recovery.out].owner);
00679 *addr = recovery.msg[recovery.out].addr;
00680 msg.op = 0;
00681 msg.port = 0;
00682 recovery.out = (recovery.out + 1) & MaxStubsMone;
00683 } else {
00684 recovered = 0;
00685 rsize = soft_rt_recvfrom(portslot[0].socket[0], &msg, sizeof(msg), 0, addr, &i);
00686 if (decode) {
00687 decode(&portslot[0], &msg, rsize, PRT_SRV);
00688 }
00689 }
00690 if (msg.op) {
00691 msg.port = gvb_stub(msg.op - BASEPORT, msg.owner);
00692 goto ret;
00693 }
00694 if (!(msg.port = get_stub(msg.owner))) {
00695 msg.port = -ENODEV;
00696 goto ret;
00697 }
00698 if (!portslot[msg.port].task) {
00699 if ((task = kmalloc(sizeof(RT_TASK) + 2*sizeof(struct fun_args), GFP_KERNEL))) {
00700 if ((msg.hard ? rt_task_init(task, (void *)hard_stub_fun, (long)(portslot + msg.port), StackSize + 2*MAX_MSG_SIZE, msg.priority, 0, NULL) : soft_kthread_init(task, (long)soft_stub_fun, (long)(portslot + msg.port), msg.priority < BASE_SOFT_PRIORITY ? msg.priority + BASE_SOFT_PRIORITY : msg.priority))) {
00701 kfree(task);
00702 task = 0;
00703 }
00704 }
00705 if (!task) {
00706 portslot[msg.port].owner = 0;
00707 msg.port = -ENOMEM;
00708 goto ret;
00709 }
00710 portslot[msg.port].name = msg.name;
00711 portslot[msg.port].task = (long)task;
00712 if (msg.hard) {
00713 portslot[msg.port].hard = MSG_HARD;
00714 } else {
00715 portslot[msg.port].hard = MSG_SOFT;
00716 }
00717 portslot[msg.port].sem.count = 0;
00718 portslot[msg.port].sem.queue.prev = portslot[msg.port].sem.queue.next = &portslot[msg.port].sem.queue;
00719 portslot[msg.port].addr = portslot[0].addr;
00720 rt_task_resume(task);
00721 }
00722 portslot[msg.port].recovered = recovered;
00723 msg.rem_node = this_node[msg.hard];
00724 msg.port += BASEPORT;
00725 msg.chkspare = sizeof(long);
00726 ret:
00727 if (recovered) {
00728 rt_task_masked_unblock((RT_TASK *)portslot[msg.port-BASEPORT].task,~RT_SCHED_READY);
00729 } else {
00730 soft_rt_sendto(portslot[0].socket[0], &msg, encode ? encode(&portslot[0], &msg, sizeof(msg), PRT_RTR) : sizeof(msg), 0, addr, ADRSZ);
00731 }
00732 }
00733
00734 }
00735
00736 static int mod_timer_srq;
00737
00738 RTAI_SYSCALL_MODE int rt_send_req_rel_port(unsigned long node, int op, unsigned long id, MBX *mbx, int hard)
00739 {
00740 RT_TASK *task;
00741 long i, msgsize;
00742 struct portslot_t *portslotp;
00743 struct req_rel_msg msg;
00744
00745 op >>= PORT_SHF;
00746 if (!node || (op && (op < MaxStubs || op >= MaxSocks))) {
00747 return -EINVAL;
00748 }
00749 if (!(portslotp = get_portslot())) {
00750 return -ENODEV;
00751 }
00752 portslotp->name = PRTSRVNAME;
00753 portslotp->addr = SPRT_ADDR;
00754 portslotp->addr.sin_addr.s_addr = node;
00755 task = _rt_whoami();
00756 if (op) {
00757 msg.op = ntohs(portslot[op].addr.sin_port);
00758 id = portslot[op].name;
00759 hard = portslot[op].hard;
00760 } else {
00761 msg.op = 0;
00762 if (!id) {
00763 id = (unsigned long)task;
00764 }
00765 }
00766 msg.port = portslotp->sem.count = 0;
00767 portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
00768 msg.hard = hard ? MSG_HARD : MSG_SOFT;
00769 msg.name = id;
00770 msg.owner = OWNER(this_node[0], id);
00771 msg.rem_node = 0;
00772 msg.priority = task->base_priority;
00773 msgsize = encode ? encode(&portslot[0], &msg, sizeof(msg), PRT_REQ) : sizeof(msg);
00774 for (i = 0; i < NETRPC_TIMER_FREQ && !portslotp->sem.count; i++) {
00775 soft_rt_sendto(portslotp->socket[0], &msg, msgsize, 0, (void *)&portslotp->addr, ADRSZ);
00776 rt_pend_linux_srq(mod_timer_srq);
00777 rt_sem_wait(&timer_sem);
00778 }
00779 if (portslotp->sem.count >= 1) {
00780 msgsize = soft_rt_recvfrom(portslotp->socket[0], &msg, sizeof(msg), 0, (void *)&portslotp->addr, &i);
00781 if (decode) {
00782 decode(&portslot[0], &msg, msgsize, PRT_RCV);
00783 }
00784 if (msg.port > 0) {
00785 if (op) {
00786 portslot[op].task = 0;
00787 gvb_portslot(portslot + op);
00788 gvb_portslot(portslotp);
00789 return op;
00790 } else {
00791 check_portslot(node, msg.port, &portslotp);
00792 portslotp->sem.count = 0;
00793 portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
00794 portslotp->hard = msg.hard;
00795 portslotp->owner = msg.owner;
00796 portslotp->name = msg.name;
00797 portslotp->addr.sin_port = htons(msg.port);
00798 portslotp->mbx = mbx;
00799 portslotp->recovered = 1;
00800 portslotp->addr.sin_addr.s_addr = msg.rem_node;
00801 if (msg.chkspare == 4) {
00802 return (portslotp->indx << PORT_SHF);
00803 } else {
00804 return (portslotp->indx << PORT_SHF) + PORT_INC;
00805 }
00806 }
00807 }
00808 }
00809 gvb_portslot(portslotp);
00810 return msg.port ? msg.port : -ETIMEDOUT;
00811 }
00812
00813 RTAI_SYSCALL_MODE int rt_set_netrpc_timeout(int port, RTIME timeout)
00814 {
00815 portslot[port >> PORT_SHF].timeout = timeout;
00816 return 0;
00817 }
00818
00819 RTAI_SYSCALL_MODE RT_TASK *rt_find_asgn_stub(unsigned long long owner, int asgn)
00820 {
00821 int i;
00822 i = asgn ? get_stub(owner) : find_stub(owner);
00823 return i > 0 ? (RT_TASK *)portslot[i].task : 0;
00824 }
00825
00826 RTAI_SYSCALL_MODE int rt_rel_stub(unsigned long long owner)
00827 {
00828 int i;
00829 i = find_stub(owner);
00830 if (i)
00831 {
00832 i = gvb_stub(i,owner);
00833 return i;
00834 } else {
00835 return -ESRCH;
00836 }
00837 }
00838
00839 RTAI_SYSCALL_MODE int rt_waiting_return(unsigned long node, int port)
00840 {
00841 struct portslot_t *portslotp;
00842 portslotp = portslot + (abs(port) >> PORT_SHF);
00843 return portslotp->task < 0 && !portslotp->sem.count;
00844 }
00845
00846 #if 0
00847
00848 static inline void mbx_send_if(MBX *mbx, void *sendmsg, int msg_size)
00849 {
00850 #define MOD_SIZE(indx) ((indx) < mbx->size ? (indx) : (indx) - mbx->size)
00851
00852 unsigned long flags;
00853 int tocpy, avbs;
00854 char *msg;
00855
00856 if (!mbx) {
00857 return;
00858 }
00859 msg = sendmsg;
00860 if (msg_size <= mbx->frbs) {
00861 RT_TASK *task;
00862 avbs = mbx->avbs;
00863 while (msg_size > 0 && mbx->frbs) {
00864 if ((tocpy = mbx->size - mbx->lbyte) > msg_size) {
00865 tocpy = msg_size;
00866 }
00867 if (tocpy > mbx->frbs) {
00868 tocpy = mbx->frbs;
00869 }
00870 memcpy(mbx->bufadr + mbx->lbyte, msg, tocpy);
00871 flags = rt_spin_lock_irqsave(&mbx->lock);
00872 mbx->frbs -= tocpy;
00873 rt_spin_unlock_irqrestore(flags, &mbx->lock);
00874 avbs += tocpy;
00875 msg_size -= tocpy;
00876 *msg += tocpy;
00877 mbx->lbyte = MOD_SIZE(mbx->lbyte + tocpy);
00878 }
00879 mbx->avbs = avbs;
00880 flags = rt_global_save_flags_and_cli();
00881 if ((task = mbx->waiting_task)) {
00882 rem_timed_task(task);
00883 mbx->waiting_task = (void *)0;
00884 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_MBXSUSP | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
00885 enq_ready_task(task);
00886 rt_schedule();
00887 }
00888 }
00889 rt_global_restore_flags(flags);
00890 }
00891 }
00892
00893 #else
00894
00895 static inline void mbx_signal(MBX *mbx)
00896 {
00897 unsigned long flags;
00898 RT_TASK *task;
00899
00900 flags = rt_global_save_flags_and_cli();
00901 if ((task = mbx->waiting_task)) {
00902 rem_timed_task(task);
00903 task->blocked_on = NULL;
00904 mbx->waiting_task = NULL;
00905 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_MBXSUSP | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
00906 enq_ready_task(task);
00907 RT_SCHEDULE(task, rtai_cpuid());
00908 }
00909 }
00910 rt_global_restore_flags(flags);
00911 }
00912
00913 #define MOD_SIZE(indx) ((indx) < mbx->size ? (indx) : (indx) - mbx->size)
00914
00915 static inline void mbxput(MBX *mbx, char **msg, int msg_size)
00916 {
00917 unsigned long flags;
00918 int tocpy;
00919
00920 while (msg_size > 0 && mbx->frbs) {
00921 if ((tocpy = mbx->size - mbx->lbyte) > msg_size) {
00922 tocpy = msg_size;
00923 }
00924 if (tocpy > mbx->frbs) {
00925 tocpy = mbx->frbs;
00926 }
00927 memcpy(mbx->bufadr + mbx->lbyte, *msg, tocpy);
00928 flags = rt_spin_lock_irqsave(&(mbx->lock));
00929 mbx->frbs -= tocpy;
00930 mbx->avbs += tocpy;
00931 rt_spin_unlock_irqrestore(flags, &(mbx->lock));
00932 msg_size -= tocpy;
00933 *msg += tocpy;
00934 mbx->lbyte = MOD_SIZE(mbx->lbyte + tocpy);
00935 }
00936 }
00937
00938 static void mbx_send_if(MBX *mbx, void *msg, int msg_size)
00939 {
00940 unsigned long flags;
00941 RT_TASK *rt_current;
00942
00943 if (!mbx || mbx->magic != RT_MBX_MAGIC) {
00944 return;
00945 }
00946
00947 flags = rt_global_save_flags_and_cli();
00948 rt_current = RT_CURRENT;
00949 if (mbx->sndsem.count > 0 && msg_size <= mbx->frbs) {
00950 mbx->sndsem.count = 0;
00951 if (mbx->sndsem.type > 0) {
00952 mbx->sndsem.owndby = rt_current;
00953 enqueue_resqel(&mbx->sndsem.resq, rt_current);
00954 }
00955 rt_global_restore_flags(flags);
00956 mbxput(mbx, (char **)(&msg), msg_size);
00957 mbx_signal(mbx);
00958 rt_sem_signal(&mbx->sndsem);
00959 }
00960 rt_global_restore_flags(flags);
00961 }
00962
00963 #endif
00964
00965 #define RETURN_ERR(err) \
00966 do { \
00967 union { long long ll; long l; } retval; \
00968 retval.l = err; \
00969 return retval.ll; \
00970 } while (0)
00971
00972 RTAI_SYSCALL_MODE long long _rt_net_rpc(long fun_ext_timed, long type, void *args, int argsize, int space, unsigned long partypes)
00973 {
00974 char msg[MAX_MSG_SIZE];
00975 struct reply_t *reply;
00976 long rsize, port;
00977 struct portslot_t *portslotp;
00978
00979 if ((port = PORT(fun_ext_timed)) > 0) {
00980 port >>= PORT_SHF;
00981 if ((portslotp = portslot + port)->task < 0) {
00982 long i;
00983 struct sockaddr addr;
00984
00985 if (portslotp->timeout) {
00986 if(rt_sem_wait_timed(&portslotp->sem,portslotp->timeout) == RTE_TIMOUT)
00987 RETURN_ERR(RTE_NETIMOUT);
00988 } else {
00989 rt_sem_wait(&portslotp->sem);
00990 }
00991 if ((rsize = portslotp->hard ? hard_rt_recvfrom(portslotp->socket[1], msg, MAX_MSG_SIZE, 0, &addr, (void *)&i) : soft_rt_recvfrom(portslotp->socket[0], msg, MAX_MSG_SIZE, 0, &addr, &i))) {
00992 if (decode) {
00993 rsize = decode(portslotp, msg, rsize, RPC_RCV);
00994 }
00995 if((reply = (void *)msg)->myport) {
00996 if (reply->myport < 0) {
00997 RETURN_ERR(-RTE_CHGPORTERR);
00998 }
00999 portslotp->addr.sin_port = htons(reply->myport);
01000 portslotp->sem.count = 0;
01001 portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
01002 portslotp->owner = reply->retval;
01003 portslotp->name = (unsigned long)(_rt_whoami());
01004 RETURN_ERR(-RTE_CHGPORTOK);
01005 }
01006 mbx_send_if(portslotp->mbx, msg, offsetof(struct reply_t, msg) + reply->wsize + reply->w2size);
01007
01008 }
01009 portslotp->task = 1;
01010 }
01011 portslotp->msg = msg;
01012 } else {
01013 port = -(abs(port) >> PORT_SHF);
01014 if ((portslotp = portslot - port)->task < 0) {
01015 if (!rt_sem_wait_if(&portslotp->sem)) {
01016 return 0;
01017 } else {
01018 long i;
01019 struct sockaddr addr;
01020
01021 if ((rsize = portslotp->hard ? hard_rt_recvfrom(portslotp->socket[1], msg, MAX_MSG_SIZE, 0, &addr, (void *)&i) : soft_rt_recvfrom(portslotp->socket[0], msg, MAX_MSG_SIZE, 0, &addr, &i))) {
01022 if (decode) {
01023 rsize = decode(portslotp, msg, rsize, RPC_RCV);
01024 }
01025 if((reply = (void *)msg)->myport) {
01026 if (reply->myport < 0) {
01027 RETURN_ERR(-RTE_CHGPORTERR);
01028 }
01029
01030 portslotp->addr.sin_port = htons(reply->myport);
01031 portslotp->sem.count = 0;
01032 portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
01033 portslotp->owner = reply->retval;
01034 portslotp->name = (unsigned long)(_rt_whoami());
01035 RETURN_ERR(-RTE_CHGPORTOK);
01036 }
01037 mbx_send_if(portslotp->mbx, msg, offsetof(struct reply_t, msg) + reply->wsize + reply->w2size);
01038
01039 }
01040 }
01041 } else {
01042 portslotp->task = -1;
01043 }
01044 }
01045 if (FUN(fun_ext_timed) == SYNC_NET_RPC) {
01046 RETURN_ERR(1);
01047 }
01048 if (NEED_TO_R(type)) {
01049 rsize = USP_RSZ1(type);
01050 rsize = rsize ? ((long *)args)[rsize - 1] : sizeof(long);
01051 } else {
01052 rsize = 0;
01053 }
01054 do {
01055 struct par_t *arg;
01056 RT_TASK *task;
01057
01058 arg = (void *)msg;
01059 arg->priority = (task = _rt_whoami())->priority;
01060 arg->base_priority = task->base_priority;
01061 arg->argsize = argsize;
01062 arg->rsize = rsize;
01063 arg->fun_ext_timed = fun_ext_timed;
01064 arg->type = type;
01065 arg->owner = portslotp->owner;
01066 arg->partypes = partypes;
01067 memcpy(arg->a, args, argsize);
01068 if (rsize > 0) {
01069 if (space) {
01070 memcpy((char *)arg->a + argsize, (void *)((long *)args + USP_RBF1(type) - 1)[0], rsize);
01071 } else {
01072 rt_copy_from_user((char *)arg->a + argsize, (void *)((long *)args + USP_RBF1(type) - 1)[0], rsize);
01073 }
01074 }
01075 rsize = sizeof(struct par_t) - sizeof(long) + argsize + rsize;
01076 if (encode) {
01077 rsize = encode(portslotp, msg, rsize, RPC_REQ);
01078 }
01079 arg->mach = sizeof(long);
01080 if (portslotp->hard) {
01081 hard_rt_sendto(portslotp->socket[1], msg, rsize, 0, (struct sockaddr *)&portslotp->addr, ADRSZ);
01082 } else {
01083 soft_rt_sendto(portslotp->socket[0], msg, rsize, 0, (struct sockaddr *)&portslotp->addr, ADRSZ);
01084 }
01085 } while (0);
01086 if (port > 0) {
01087 struct sockaddr addr;
01088
01089 if (portslotp->timeout) {
01090 if(rt_sem_wait_timed(&portslotp->sem,portslotp->timeout) == RTE_TIMOUT)
01091 RETURN_ERR(-RTE_NETIMOUT);
01092 } else {
01093 rt_sem_wait(&portslotp->sem);
01094 }
01095 rsize = portslotp->hard ? hard_rt_recvfrom(portslotp->socket[1], msg, MAX_MSG_SIZE, 0, &addr, (void *)&port) : soft_rt_recvfrom(portslotp->socket[0], msg, MAX_MSG_SIZE, 0, &addr, &port);
01096 if (decode) {
01097 decode(portslotp, portslotp->msg, rsize, RPC_RCV);
01098 }
01099 if((reply = (void *)msg)->myport) {
01100 if (reply->myport < 0) {
01101 RETURN_ERR(-RTE_CHGPORTERR);
01102 }
01103 portslotp->addr.sin_port = htons(reply->myport);
01104 portslotp->sem.count = 0;
01105 portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
01106 portslotp->owner = reply->retval;
01107 portslotp->name = (unsigned long)(_rt_whoami());
01108 RETURN_ERR(-RTE_CHGPORTOK);
01109 } else {
01110 if (reply->wsize) {
01111 if (space) {
01112 memcpy((char *)(*((long *)args + USP_WBF1(type) - 1)), reply->msg, reply->wsize);
01113 } else {
01114 rt_copy_to_user((char *)(*((long *)args + USP_WBF1(type) - 1)), reply->msg, reply->wsize);
01115 }
01116 if (reply->w2size) {
01117 if (space) {
01118 memcpy((char *)(*((long *)args + USP_WBF2(type) - 1)), reply->msg + reply->wsize, reply->w2size);
01119 } else {
01120 rt_copy_to_user((char *)(*((long *)args + USP_WBF2(type) - 1)), reply->msg + reply->wsize, reply->w2size);
01121 }
01122 }
01123 }
01124
01125 return reply->retval;
01126 }
01127 }
01128 return 0;
01129 }
01130
01131 int rt_get_net_rpc_ret(MBX *mbx, unsigned long long *retval, void *msg1, int *msglen1, void *msg2, int *msglen2, RTIME timeout, int type)
01132 {
01133 struct reply_t reply;
01134 int ret;
01135
01136 if ((ret = ((int (*)(MBX *, ...))rt_net_rpc_fun_ext[NET_RPC_EXT][type].fun)(mbx, &reply, offsetof(struct reply_t, msg), timeout))) {
01137 return ret;
01138 }
01139 *retval = reply.retval;
01140 if (reply.wsize) {
01141 if (*msglen1 > reply.wsize) {
01142 *msglen1 = reply.wsize;
01143 }
01144 _rt_mbx_receive(mbx, &msg1, *msglen1, 1);
01145 } else {
01146 *msglen1 = 0;
01147 }
01148 if (reply.w2size) {
01149 if (*msglen2 > reply.w2size) {
01150 *msglen2 = reply.w2size;
01151 }
01152 _rt_mbx_receive(mbx, &msg2, *msglen2, 1);
01153 } else {
01154 *msglen2 = 0;
01155 }
01156 return 0;
01157 }
01158
01159 RTAI_SYSCALL_MODE unsigned long ddn2nl(const char *ddn)
01160 {
01161 int p, n, c;
01162 union { unsigned long l; char c[4]; } u;
01163
01164 p = n = 0;
01165 while ((c = *ddn++)) {
01166 if (c != '.') {
01167 n = n*10 + c - '0';
01168 } else {
01169 if (n > 0xFF) {
01170 return 0;
01171 }
01172 u.c[p++] = n;
01173 n = 0;
01174 }
01175 }
01176 u.c[3] = n;
01177
01178 return u.l;
01179 }
01180
01181 RTAI_SYSCALL_MODE unsigned long rt_set_this_node(const char *ddn, unsigned long node, int hard)
01182 {
01183 return this_node[hard ? MSG_HARD : MSG_SOFT] = ddn ? ddn2nl(ddn) : node;
01184 }
01185
01186 #ifdef CONFIG_RTAI_RT_POLL
01187
01188 RTAI_SYSCALL_MODE int rt_poll_netrpc(struct rt_poll_s *pdsa1, struct rt_poll_s *pdsa2, unsigned long pdsa_size, RTIME timeout)
01189 {
01190 int retval = pdsa_size/sizeof(struct rt_poll_s);
01191 if (sizeof(long) == 8 && !((unsigned long)pdsa1[0].what & 0xFFFFFFFF00000000ULL)) {
01192 int i;
01193 for (i = 0; i < retval; i++) {
01194 pdsa1[i].what = (void *)reset_kadr((unsigned long)pdsa1[i].what);
01195 }
01196 }
01197 retval = _rt_poll(pdsa1, retval, timeout, 1);
01198 memcpy(pdsa2, pdsa1, pdsa_size);
01199 return retval;
01200 }
01201
01202 EXPORT_SYMBOL(rt_poll_netrpc);
01203
01204 #endif
01205
01206
01207
01208 struct rt_native_fun_entry rt_netrpc_entries[] = {
01209 { { 1, _rt_net_rpc }, NETRPC },
01210 { { 0, rt_set_netrpc_timeout }, SET_NETRPC_TIMEOUT },
01211 { { 1, rt_send_req_rel_port }, SEND_REQ_REL_PORT },
01212 { { 0, ddn2nl }, DDN2NL },
01213 { { 0, rt_set_this_node }, SET_THIS_NODE },
01214 { { 0, rt_find_asgn_stub }, FIND_ASGN_STUB },
01215 { { 0, rt_rel_stub }, REL_STUB },
01216 { { 0, rt_waiting_return }, WAITING_RETURN },
01217 #ifdef CONFIG_RTAI_RT_POLL
01218 { { 1, rt_poll_netrpc }, RT_POLL_NETRPC },
01219 #endif
01220 { { 0, 0 }, 000 }
01221 };
01222
01223 extern int set_rt_fun_entries(struct rt_native_fun_entry *entry);
01224 extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry);
01225
01226 static RT_TASK *port_server;
01227
01228 static int init_softrtnet(void);
01229 static void cleanup_softrtnet(void);
01230
01231 void do_mod_timer(void)
01232 {
01233 mod_timer(&timer, jiffies + HZ/NETRPC_TIMER_FREQ);
01234 }
01235
01236 static struct sock_t *socks;
01237
01238 int soft_rt_socket(int domain, int type, int protocol)
01239 {
01240 int i;
01241 for (i = 0; i < MaxSocks; i++) {
01242 if (!cmpxchg(&socks[i].opnd, 0, 1)) {
01243 return i;
01244 }
01245 }
01246 return -1;
01247 }
01248
01249 int soft_rt_close(int sock)
01250 {
01251 if (sock >= 0 && sock < MaxSocks) {
01252 return socks[sock].opnd = 0;
01253 }
01254 return -1;
01255 }
01256
01257 int soft_rt_bind(int sock, struct sockaddr *addr, int addrlen)
01258 {
01259 return 0;
01260 }
01261
01262 int soft_rt_socket_callback(int sock, int (*func)(int sock, void *arg), void *arg)
01263 {
01264 if (sock >= 0 && sock < MaxSocks && func > 0) {
01265 socks[sock].callback = func;
01266 socks[sock].arg = arg;
01267 return 0;
01268 }
01269 return -1;
01270 }
01271
01272 static int MaxSockSrq;
01273 static struct { int srq, in, out, *sockindx; } sysrq;
01274 static spinlock_t sysrq_lock = SPIN_LOCK_UNLOCKED;
01275
01276 int soft_rt_sendto(int sock, const void *msg, int msglen, unsigned int sflags, struct sockaddr *to, int tolen)
01277 {
01278 unsigned long flags;
01279 if (sock >= 0 && sock < MaxSocks) {
01280 if (msglen > MAX_MSG_SIZE) {
01281 msglen = MAX_MSG_SIZE;
01282 }
01283 memcpy(socks[sock].msg, msg, socks[sock].tosend = msglen);
01284 memcpy(&socks[sock].addr, to, tolen);
01285 flags = rt_spin_lock_irqsave(&sysrq_lock);
01286 sysrq.sockindx[sysrq.in] = sock;
01287 sysrq.in = (sysrq.in + 1) & MaxSockSrq;
01288 rt_spin_unlock_irqrestore(flags, &sysrq_lock);
01289 rt_pend_linux_srq(sysrq.srq);
01290 return msglen;
01291 }
01292 return -1;
01293 }
01294
01295 int soft_rt_recvfrom(int sock, void *msg, int msglen, unsigned int flags, struct sockaddr *from, long *fromlen)
01296 {
01297 if (sock >= 0 && sock < MaxSocks) {
01298 if (msglen > socks[sock].recvd) {
01299 msglen = socks[sock].recvd;
01300 }
01301 memcpy(msg, socks[sock].msg, msglen);
01302 if (from && fromlen) {
01303 memcpy(from, &socks[sock].addr, socks[sock].addrlen);
01304 *fromlen = socks[sock].addrlen;
01305 }
01306 return msglen;
01307 }
01308 return -1;
01309 }
01310
01311 #include <linux/unistd.h>
01312 #include <linux/poll.h>
01313 #include <linux/net.h>
01314
01315 int errno;
01316
01317 #define SYSCALL_BGN() \
01318 do { int retval; mm_segment_t svdfs = get_fs(); set_fs(KERNEL_DS)
01319 #define SYSCALL_END() \
01320 set_fs(svdfs); return retval; } while (0)
01321
01322 #ifdef __NR_socketcall
01323
01324 extern void *sys_call_table[];
01325
01326
01327 static inline int kpoll(struct pollfd *ufds, unsigned int nfds, int timeout)
01328 {
01329 SYSCALL_BGN();
01330 retval = ((asmlinkage int (*)(struct pollfd *, ... ))sys_call_table[__NR_poll])(ufds, nfds, timeout);
01331
01332 SYSCALL_END();
01333 }
01334
01335
01336 static inline int ksocketcall(int call, void *args)
01337 {
01338 SYSCALL_BGN();
01339 retval = ((asmlinkage int (*)(int, ... ))sys_call_table[__NR_socketcall])(call, args);
01340
01341 SYSCALL_END();
01342 }
01343
01344 static inline int ksocket(int family, int type, int protocol)
01345 {
01346 struct { int family; int type; int protocol; } args = { family, type, protocol };
01347 return ksocketcall(SYS_SOCKET, &args);
01348 }
01349
01350 static inline int kbind(int fd, struct sockaddr *umyaddr, int addrlen)
01351 {
01352 struct { int fd; struct sockaddr *umyaddr; int addrlen; } args = { fd, umyaddr, addrlen };
01353 return ksocketcall(SYS_BIND, &args);
01354 }
01355
01356 static inline int kconnect(int fd, struct sockaddr *serv_addr, int addrlen)
01357 {
01358 struct { int fd; struct sockaddr *serv_addr; int addrlen; } args = { fd, serv_addr, addrlen };
01359 return ksocketcall(SYS_CONNECT, &args);
01360 }
01361
01362 static inline int klisten(int fd, int backlog)
01363 {
01364 struct { int fd; int backlog; } args = { fd, backlog };
01365 return ksocketcall(SYS_LISTEN, &args);
01366 }
01367
01368 static inline int kaccept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
01369 {
01370 struct { int fd; struct sockaddr *upeer_sockaddr; int *upeer_addrlen; } args = { fd, upeer_sockaddr, upeer_addrlen };
01371 return ksocketcall(SYS_ACCEPT, &args);
01372 }
01373
01374 static inline int kgetsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
01375 {
01376 struct { int fd; struct sockaddr *usockaddr; int *usockaddr_len; } args = { fd, usockaddr, usockaddr_len };
01377 return ksocketcall(SYS_GETSOCKNAME, &args);
01378 }
01379
01380 static inline int kgetpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
01381 {
01382 struct { int fd; struct sockaddr *usockaddr; int *usockaddr_len; } args = { fd, usockaddr, usockaddr_len };
01383 return ksocketcall(SYS_GETPEERNAME, &args);
01384 }
01385
01386 static inline int ksocketpair(int family, int type, int protocol, int *usockvec)
01387 {
01388 struct { int family; int type; int protocol; int *usockvec; } args = { family, type, protocol, usockvec };
01389 return ksocketcall(SYS_SOCKETPAIR, &args);
01390 }
01391
01392 static inline int ksendto(int fd, void *buff, size_t len, unsigned flags, struct sockaddr *addr, int addr_len)
01393 {
01394 struct { int fd; void *buff; size_t len; unsigned flags; struct sockaddr *addr; int addr_len; } args = { fd, buff, len, flags, addr, addr_len };
01395 return ksocketcall(SYS_SENDTO, &args);
01396 }
01397
01398 static inline int krecvfrom(int fd, void *ubuf, size_t len, unsigned flags, struct sockaddr *addr, int *addr_len)
01399 {
01400 struct { int fd; void *ubuf; size_t len; unsigned flags; struct sockaddr *addr; int *addr_len; } args = { fd, ubuf, len, flags, addr, addr_len };
01401 return ksocketcall(SYS_RECVFROM, &args);
01402 }
01403
01404 static inline int kshutdown(int fd, int how)
01405 {
01406 struct { int fd; int how; } args = { fd, how };
01407 return ksocketcall(SYS_SHUTDOWN, &args);
01408 }
01409
01410 static inline int ksetsockopt(int fd, int level, int optname, void *optval, int optlen)
01411 {
01412 struct { int fd; int level; int optname; void *optval; int optlen; } args = { fd, level, optname, optval, optlen };
01413 return ksocketcall(SYS_SETSOCKOPT, &args);
01414 }
01415
01416 static inline int kgetsockopt(int fd, int level, int optname, char *optval, int *optlen)
01417 {
01418 struct { int fd; int level; int optname; void *optval; int *optlen; } args = { fd, level, optname, optval, optlen };
01419 return ksocketcall(SYS_GETSOCKOPT, &args);
01420 }
01421
01422 static inline int ksendmsg(int fd, struct msghdr *msg, unsigned flags)
01423 {
01424 struct { int fd; struct msghdr *msg; unsigned flags; } args = { fd, msg, flags };
01425 return ksocketcall(SYS_SENDMSG, &args);
01426 }
01427
01428 static inline int krecvmsg(int fd, struct msghdr *msg, unsigned flags)
01429 {
01430 struct { int fd; struct msghdr *msg; unsigned flags; } args = { fd, msg, flags };
01431 return ksocketcall(SYS_RECVMSG, &args);
01432 }
01433
01434 #else
01435
01436 #if 0 // just for compiling
01437 #define __NR_socket 1
01438 #define __NR_bind 1
01439 #define __NR_connect 1
01440 #define __NR_accept 1
01441 #define __NR_listen 1
01442 #define __NR_getsockname 1
01443 #define __NR_getpeername 1
01444 #define __NR_socketpair 1
01445 #define __NR_sendto 1
01446 #define __NR_recvfrom 1
01447 #define __NR_shutdown 1
01448 #define __NR_setsockopt 1
01449 #define __NR_getsockopt 1
01450 #define __NR_sendmsg 1
01451 #define __NR_recvmsg 1
01452 #endif
01453
01454 extern void *sys_call_table[];
01455
01456
01457 static inline int kpoll(struct pollfd *ufds, unsigned int nfds, int timeout)
01458 {
01459 SYSCALL_BGN();
01460 retval = ((int (*)(void *, unsigned int, int))sys_call_table[__NR_poll])(ufds, nfds, timeout);
01461
01462 SYSCALL_END();
01463 }
01464
01465
01466 static inline int ksocket(int family, int type, int protocol)
01467 {
01468 SYSCALL_BGN();
01469 retval = ((int (*)(int, int, int))sys_call_table[__NR_socket])(family, type, protocol);
01470
01471 SYSCALL_END();
01472 }
01473
01474
01475 static inline int kbind(int fd, struct sockaddr *umyaddr, int addrlen)
01476 {
01477 SYSCALL_BGN();
01478 retval = ((int (*)(int, struct sockaddr *, int))sys_call_table[__NR_bind])(fd, umyaddr, addrlen);
01479
01480 SYSCALL_END();
01481 }
01482
01483
01484 static inline int kconnect(int fd, struct sockaddr *serv_addr, int addrlen)
01485 {
01486 SYSCALL_BGN();
01487 retval = ((int (*)(int, struct sockaddr *, int))sys_call_table[__NR_connect])(fd, serv_addr, addrlen);
01488
01489 SYSCALL_END();
01490 }
01491
01492
01493 static inline int klisten(int fd, int backlog)
01494 {
01495 SYSCALL_BGN();
01496 retval = ((int (*)(int, int))sys_call_table[__NR_listen])(fd, backlog);
01497
01498 SYSCALL_END();
01499 }
01500
01501
01502 static inline int kaccept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
01503 {
01504 SYSCALL_BGN();
01505 retval = ((int (*)(int, struct sockaddr *, int *))sys_call_table[__NR_accept])(fd, upeer_sockaddr, upeer_addrlen);
01506
01507 SYSCALL_END();
01508 }
01509
01510
01511 static inline int kgetsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
01512 {
01513 SYSCALL_BGN();
01514 retval = ((int (*)(int, struct sockaddr *, int *))sys_call_table[__NR_getsockname])(fd, usockaddr, usockaddr_len);
01515
01516 SYSCALL_END();
01517 }
01518
01519
01520 static inline int kgetpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
01521 {
01522 SYSCALL_BGN();
01523 retval = ((int (*)(int, struct sockaddr *, int *))sys_call_table[__NR_getpeername])(fd, usockaddr, usockaddr_len);
01524
01525 SYSCALL_END();
01526 }
01527
01528
01529 static inline int ksocketpair(int family, int type, int protocol, int *usockvec)
01530 {
01531 SYSCALL_BGN();
01532 retval = ((int (*)(int, int, int, int *))sys_call_table[__NR_socketpair])(family, type, protocol, usockvec);
01533
01534 SYSCALL_END();
01535 }
01536
01537
01538 static inline int ksendto(int fd, void *buff, size_t len, unsigned flags, struct sockaddr *addr, int addr_len)
01539 {
01540 SYSCALL_BGN();
01541 retval = ((int (*)(int, void *, size_t, unsigned, struct sockaddr *, int))sys_call_table[__NR_sendto])(fd, buff, len, flags, addr, addr_len);
01542
01543 SYSCALL_END();
01544 }
01545
01546
01547 static inline int krecvfrom(int fd, void *ubuf, size_t len, unsigned flags, struct sockaddr *addr, int *addr_len)
01548 {
01549 SYSCALL_BGN();
01550 retval = ((int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))sys_call_table[__NR_recvfrom])(fd, ubuf, len, flags, addr, addr_len);
01551
01552 SYSCALL_END();
01553 }
01554
01555
01556 static inline int kshutdown(int fd, int how)
01557 {
01558 SYSCALL_BGN();
01559 retval = ((int (*)(int, int))sys_call_table[__NR_shutdown])(fd, how);
01560
01561 SYSCALL_END();
01562 }
01563
01564
01565 static inline int ksetsockopt(int fd, int level, int optname, void *optval, int optlen)
01566 {
01567 SYSCALL_BGN();
01568 retval = ((int (*)(int, int, int, void *, int))sys_call_table[__NR_setsockopt])(fd, level, optname, optval, optlen);
01569
01570 SYSCALL_END();
01571 }
01572
01573
01574 static inline int kgetsockopt(int fd, int level, int optname, char *optval, int *optlen)
01575 {
01576 SYSCALL_BGN();
01577 retval = ((int (*)(int, int, int, void *, int *))sys_call_table[__NR_getsockopt])(fd, level, optname, optval, optlen);
01578
01579 SYSCALL_END();
01580 }
01581
01582
01583 static inline int ksendmsg(int fd, struct msghdr *msg, unsigned flags)
01584 {
01585 SYSCALL_BGN();
01586 retval = ((int (*)(int, struct msghdr *, unsigned))sys_call_table[__NR_sendmsg])(fd, msg, flags);
01587
01588 SYSCALL_END();
01589 }
01590
01591
01592 static inline int krecvmsg(int fd, struct msghdr *msg, unsigned flags)
01593 {
01594 SYSCALL_BGN();
01595 retval = ((int (*)(int, struct msghdr *, unsigned))sys_call_table[__NR_recvmsg])(fd, msg, flags);
01596
01597 SYSCALL_END();
01598 }
01599
01600 #endif
01601
01602 static inline int ksend(int fd, void *buff, size_t len, unsigned flags)
01603 {
01604 return ksendto(fd, buff, len, flags, NULL, 0);
01605 }
01606
01607 static inline int krecv(int fd, void *ubuf, size_t size, unsigned flags)
01608 {
01609 return krecvfrom(fd, ubuf, size, flags, NULL, NULL);
01610 }
01611
01612 #ifndef DECLARE_MUTEX_LOCKED
01613 #ifndef __DECLARE_SEMAPHORE_GENERIC
01614 #define DECLARE_MUTEX_LOCKED(name) \
01615 struct semaphore name = __SEMAPHORE_INITIALIZER(name, 0)
01616 #else
01617 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
01618 #endif
01619 #endif
01620 static DECLARE_MUTEX_LOCKED(mtx);
01621 static unsigned long end_softrtnet;
01622
01623 static void send_thread(void)
01624 {
01625 int i;
01626
01627 sprintf(current->comm, "SNDSRV");
01628 rtai_set_linux_task_priority(current,SCHED_FIFO,MAX_LINUX_RTPRIO);
01629 sigfillset(¤t->blocked);
01630 while (!end_softrtnet) {
01631 i = down_interruptible(&mtx);
01632 while (sysrq.out != sysrq.in) {
01633 i = sysrq.sockindx[sysrq.out];
01634 ksendto(socks[i].sock, socks[i].msg, socks[i].tosend, MSG_DONTWAIT, &socks[i].addr, ADRSZ);
01635 sysrq.out = (sysrq.out + 1) & MaxSockSrq;
01636 }
01637 }
01638 set_bit(1, &end_softrtnet);
01639 }
01640
01641 static struct pollfd *pollv;
01642 static struct task_struct *recv_handle;
01643
01644 static void recv_thread(void)
01645 {
01646 int i, nevents;
01647
01648 recv_handle = current;
01649 sprintf(current->comm, "RCVSRV");
01650 rtai_set_linux_task_priority(current,SCHED_RR,MAX_LINUX_RTPRIO);
01651 sigfillset(¤t->blocked);
01652 while (!end_softrtnet) {
01653 if ((nevents = kpoll(pollv, MaxSocks, 1000)) > 0) {
01654 i = -1;
01655 do {
01656 while (!pollv[++i].revents);
01657 if ((socks[i].recvd = krecvfrom(socks[i].sock, socks[i].msg, MAX_MSG_SIZE, MSG_DONTWAIT, &socks[i].addr, &socks[i].addrlen)) > 0) {
01658 socks[i].callback(i, socks[i].arg);
01659 }
01660 } while (--nevents);
01661 }
01662 }
01663 set_bit(2, &end_softrtnet);
01664 }
01665
01666 static void softrtnet_hdl(void)
01667 {
01668 up(&mtx);
01669 }
01670
01671 static int init_softrtnet(void)
01672 {
01673 int i;
01674 for (i = 8*sizeof(unsigned long) - 1; !test_bit(i, &MaxSocks); i--);
01675 MaxSockSrq = ((1 << i) != MaxSocks ? 1 << (i + 1) : MaxSocks) - 1;
01676 if ((sysrq.srq = rt_request_srq(0xbadbeef2, softrtnet_hdl, 0)) < 0) {
01677 printk("SOFT RTNet: no sysrq available.\n");
01678 return sysrq.srq;
01679 }
01680 if (!(sysrq.sockindx = (int *)kmalloc((MaxSockSrq + 1)*sizeof(int), GFP_KERNEL))) {
01681 printk("SOFT RTNet: no memory available for socket queus.\n");
01682 return -ENOMEM;
01683 }
01684 if (!(socks = (struct sock_t *)kmalloc(MaxSocks*sizeof(struct sock_t), GFP_KERNEL))) {
01685 kfree(sysrq.sockindx);
01686 printk("SOFT RTNet: no memory available for socks.\n");
01687 return -ENOMEM;
01688 }
01689 if (!(pollv = (struct pollfd *)kmalloc(MaxSocks*sizeof(struct pollfd), GFP_KERNEL))) {
01690 kfree(sysrq.sockindx);
01691 kfree(socks);
01692 printk("SOFT RTNet: no memory available for polling.\n");
01693 return -ENOMEM;
01694 }
01695 memset(socks, 0, MaxSocks*sizeof(struct sock_t));
01696 for (i = 0; i < MaxSocks; i++) {
01697 SPRT_ADDR.sin_port = htons(BASEPORT + i);
01698 if ((socks[i].sock = ksocket(AF_INET, SOCK_DGRAM, 0)) < 0 || kbind(socks[i].sock, (struct sockaddr *)&SPRT_ADDR, ADRSZ) < 0) {
01699 rt_free_srq(sysrq.srq);
01700 kfree(socks);
01701 kfree(pollv);
01702 kfree(sysrq.sockindx);
01703 printk("SOFT RTNet: unable to set up Linux support sockets.\n");
01704 return -ESOCKTNOSUPPORT;
01705 }
01706 socks[i].addrlen = ADRSZ;
01707 pollv[i].fd = socks[i].sock;
01708 pollv[i].events = POLLIN;
01709 }
01710 if (kernel_thread((void *)send_thread, 0, 0) <= 0 || kernel_thread((void *)recv_thread, 0, 0) <= 0) {
01711 kfree(sysrq.sockindx);
01712 kfree(socks);
01713 kfree(pollv);
01714 printk("SOFT RTNet: unable to set up Linux support kernel threads.\n");
01715 return -EINVAL;
01716 }
01717 while (!recv_handle) {
01718 current->state = TASK_INTERRUPTIBLE;
01719 schedule_timeout(HZ/2);
01720 }
01721 return 0;
01722 }
01723
01724 static void cleanup_softrtnet(void)
01725 {
01726 int i;
01727 rt_free_srq(sysrq.srq);
01728 end_softrtnet = 1;
01729
01730
01731
01732
01733 softrtnet_hdl();
01734 while (end_softrtnet < 7) {
01735 current->state = TASK_INTERRUPTIBLE;
01736 schedule_timeout(HZ/2);
01737 }
01738 for (i = 0; i < MaxSocks; i++) {
01739 kshutdown(socks[i].sock, 2);
01740 }
01741 kfree(sysrq.sockindx);
01742 kfree(socks);
01743 kfree(pollv);
01744 }
01745
01746
01747
01748
01749
01750 void **rt_net_rpc_fun_hook = (void *)rt_net_rpc_fun_ext;
01751
01752 int __rtai_netrpc_init(void)
01753 {
01754 int i;
01755
01756 MaxStubsMone = MaxStubs - 1;
01757 if ((mod_timer_srq = rt_request_srq(0xbadbeef1, do_mod_timer, 0)) < 0) {
01758 printk("MOD_TIMER: no sysrq available.\n");
01759 return mod_timer_srq;
01760 }
01761 if (!(recovery.msg = (struct recovery_msg *)kmalloc((MaxStubs)*sizeof(struct recovery_msg), GFP_KERNEL))) {
01762 printk("Init MODULE no memory for recovery queue.\n");
01763 rt_free_srq(mod_timer_srq);
01764 return -ENOMEM;
01765 }
01766 MaxSocks += MaxStubs;
01767 SPRT_ADDR.sin_family = AF_INET;
01768 SPRT_ADDR.sin_addr.s_addr = htonl(INADDR_ANY);
01769 if (init_softrtnet()) {
01770 return 1;
01771 }
01772 rt_net_rpc_fun_ext[NET_RPC_EXT] = rt_fun_lxrt;
01773 set_rt_fun_entries(rt_netrpc_entries);
01774 if (!(portslot = kmalloc(MaxSocks*sizeof(struct portslot_t), GFP_KERNEL))) {
01775 printk("KMALLOC FAILED ALLOCATING PORT SLOTS\n");
01776 }
01777 if (!ThisSoftNode) {
01778 ThisSoftNode = ThisNode;
01779 }
01780 if (!ThisHardNode) {
01781 ThisHardNode = ThisNode;
01782 }
01783 this_node[0] = ddn2nl(ThisSoftNode);
01784 this_node[1] = ddn2nl(ThisHardNode);
01785
01786 for (i = 0; i < MaxSocks; i++) {
01787 portslot[i].p = portslot + i;
01788 portslot[i].indx = portslot[i].place = i;
01789 SPRT_ADDR.sin_port = htons(BASEPORT + i);
01790 portslot[i].addr = SPRT_ADDR;
01791 portslot[i].socket[0] = soft_rt_socket(AF_INET, SOCK_DGRAM, 0);
01792 soft_rt_bind(portslot[i].socket[0], (struct sockaddr *)&SPRT_ADDR, ADRSZ);
01793 portslot[i].socket[1] = hard_rt_socket(AF_INET, SOCK_DGRAM, 0);
01794 hard_rt_bind(portslot[i].socket[1], (struct sockaddr *)&SPRT_ADDR, ADRSZ);
01795 soft_rt_socket_callback(portslot[i].socket[0], (void *)net_resume_task, &portslot[i].p);
01796 hard_rt_socket_callback(portslot[i].socket[1], (void *)net_resume_task, &portslot[i].p);
01797 portslot[i].owner = 0;
01798 rt_typed_sem_init(&portslot[i].sem, 0, BIN_SEM | FIFO_Q);
01799 portslot[i].task = 0;
01800 portslot[i].timeout = 0;
01801 }
01802 SPRT_ADDR.sin_port = htons(BASEPORT);
01803 portslotsp = MaxStubs;
01804 portslot[0].hard = 0;
01805 portslot[0].name = PRTSRVNAME;
01806 portslot[0].owner = OWNER(this_node[0], (unsigned long)port_server);
01807 port_server = kmalloc(sizeof(RT_TASK) + 3*sizeof(struct fun_args), GFP_KERNEL);
01808 soft_kthread_init(port_server, (long)port_server_fun, (long)port_server, RT_SCHED_LOWEST_PRIORITY);
01809 portslot[0].task = (long)port_server;
01810 rt_task_resume(port_server);
01811 rt_typed_sem_init(&timer_sem, 0, BIN_SEM | FIFO_Q);
01812 init_timer(&timer);
01813 timer.function = timer_fun;
01814 return 0 ;
01815 }
01816
01817 void __rtai_netrpc_exit(void)
01818 {
01819 int i;
01820
01821 reset_rt_fun_entries(rt_netrpc_entries);
01822 del_timer(&timer);
01823 rt_sem_delete(&timer_sem);
01824 for (i = 0; i < MaxStubs; i++) {
01825 if (portslot[i].task) {
01826 if (portslot[i].hard) {
01827 rt_task_delete((RT_TASK *)portslot[i].task);
01828 } else {
01829 soft_kthread_delete((RT_TASK *)portslot[i].task);
01830 kfree((RT_TASK *)portslot[i].task);
01831 }
01832 }
01833 }
01834 for (i = 0; i < MaxSocks; i++) {
01835 rt_sem_delete(&portslot[i].sem);
01836 soft_rt_close(portslot[i].socket[0]);
01837 hard_rt_close(portslot[i].socket[1]);
01838 }
01839 kfree(portslot);
01840 cleanup_softrtnet();
01841 rt_free_srq(mod_timer_srq);
01842 return;
01843 }
01844
01845 #ifndef CONFIG_RTAI_NETRPC_BUILTIN
01846 module_init(__rtai_netrpc_init);
01847 module_exit(__rtai_netrpc_exit);
01848 #endif
01849
01850 EXPORT_SYMBOL(set_netrpc_encoding);
01851 EXPORT_SYMBOL(rt_send_req_rel_port);
01852 EXPORT_SYMBOL(rt_find_asgn_stub);
01853 EXPORT_SYMBOL(rt_rel_stub);
01854 EXPORT_SYMBOL(rt_waiting_return);
01855 EXPORT_SYMBOL(_rt_net_rpc);
01856 EXPORT_SYMBOL(rt_get_net_rpc_ret);
01857 EXPORT_SYMBOL(rt_set_this_node);
01858 EXPORT_SYMBOL(rt_set_netrpc_timeout);
01859
01860
01861 #ifdef SOFT_RTNET
01862 EXPORT_SYMBOL(soft_rt_socket);
01863 EXPORT_SYMBOL(soft_rt_close);
01864 EXPORT_SYMBOL(soft_rt_bind);
01865 EXPORT_SYMBOL(soft_rt_socket_callback);
01866 EXPORT_SYMBOL(soft_rt_sendto);
01867 EXPORT_SYMBOL(soft_rt_recvfrom);
01868 EXPORT_SYMBOL(ddn2nl);
01869 #endif
01870
01871 EXPORT_SYMBOL(rt_net_rpc_fun_hook);