1 /* $Id: timod.c,v 1.4 1999/09/01 08:07:47 davem Exp $
2 * timod.c: timod emulation.
4 * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
6 * Streams & timod emulation based on code
7 * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/smp.h>
15 #include <linux/smp_lock.h>
16 #include <linux/ioctl.h>
18 #include <linux/netdevice.h>
19 #include <linux/poll.h>
21 #include <asm/uaccess.h>
22 #include <asm/termios.h>
27 extern char *getname32(u32 filename
);
28 #define putname32 putname
30 extern asmlinkage
int sys_ioctl(unsigned int fd
, unsigned int cmd
,
32 extern asmlinkage
int sys32_ioctl(unsigned int fd
, unsigned int cmd
,
34 asmlinkage
int solaris_ioctl(unsigned int fd
, unsigned int cmd
, u32 arg
);
36 spinlock_t timod_pagelock
= SPIN_LOCK_UNLOCKED
;
37 static char * page
= NULL
;
39 #ifndef DEBUG_SOLARIS_KMALLOC
41 #define mykmalloc kmalloc
46 void * mykmalloc(size_t s
, int gfp
)
49 static size_t free
= 0;
53 SOLD("too big size, calling real kmalloc");
54 return kmalloc(s
, gfp
);
57 /* we are wasting memory, but we don't care */
58 page
= (char *)__get_free_page(gfp
);
75 #define BUF_SIZE PAGE_SIZE
76 #define PUT_MAGIC(a,m)
77 #define SCHECK_MAGIC(a,m)
79 #define MKCTL_TRAILER 0
83 #define BUF_SIZE (PAGE_SIZE-2*sizeof(u64))
84 #define BUFPAGE_MAGIC 0xBADC0DEDDEADBABEL
85 #define MKCTL_MAGIC 0xDEADBABEBADC0DEDL
86 #define PUT_MAGIC(a,m) do{(*(u64*)(a))=(m);}while(0)
87 #define SCHECK_MAGIC(a,m) do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
88 __FILE__,__LINE__,__FUNCTION__,(m),(a));}while(0)
89 #define BUF_OFFSET sizeof(u64)
90 #define MKCTL_TRAILER sizeof(u64)
94 static char *getpage( void )
98 spin_lock(&timod_pagelock
);
102 spin_unlock(&timod_pagelock
);
104 return r
+ BUF_OFFSET
;
106 spin_unlock(&timod_pagelock
);
108 r
= (char *)__get_free_page(GFP_KERNEL
);
109 PUT_MAGIC(r
,BUFPAGE_MAGIC
);
110 PUT_MAGIC(r
+PAGE_SIZE
-sizeof(u64
),BUFPAGE_MAGIC
);
111 return r
+ BUF_OFFSET
;
114 static void putpage(char *p
)
116 SOLD("putting page");
118 SCHECK_MAGIC(p
,BUFPAGE_MAGIC
);
119 SCHECK_MAGIC(p
+PAGE_SIZE
-sizeof(u64
),BUFPAGE_MAGIC
);
120 spin_lock(&timod_pagelock
);
122 spin_unlock(&timod_pagelock
);
123 free_page((unsigned long)p
);
127 spin_unlock(&timod_pagelock
);
132 static struct T_primsg
*timod_mkctl(int size
)
136 SOLD("creating primsg");
137 it
= (struct T_primsg
*)mykmalloc(size
+sizeof(*it
)-sizeof(s32
)+2*MKCTL_TRAILER
, GFP_KERNEL
);
142 PUT_MAGIC((char*)((u64
)(((char *)&it
->type
)+size
+7)&~7),MKCTL_MAGIC
);
147 static void timod_wake_socket(unsigned int fd
)
151 SOLD("wakeing socket");
152 sock
= ¤t
->files
->fd
[fd
]->f_dentry
->d_inode
->u
.socket_i
;
153 wake_up_interruptible(&sock
->wait
);
154 if (sock
->fasync_list
&& !(sock
->flags
& SO_WAITDATA
))
155 kill_fasync(sock
->fasync_list
, SIGIO
);
159 static void timod_queue(unsigned int fd
, struct T_primsg
*it
)
161 struct sol_socket_struct
*sock
;
163 SOLD("queuing primsg");
164 sock
= (struct sol_socket_struct
*)current
->files
->fd
[fd
]->private_data
;
165 it
->next
= sock
->pfirst
;
169 timod_wake_socket(fd
);
173 static void timod_queue_end(unsigned int fd
, struct T_primsg
*it
)
175 struct sol_socket_struct
*sock
;
177 SOLD("queuing primsg at end");
178 sock
= (struct sol_socket_struct
*)current
->files
->fd
[fd
]->private_data
;
181 sock
->plast
->next
= it
;
188 static void timod_error(unsigned int fd
, int prim
, int terr
, int uerr
)
192 SOLD("making error");
193 it
= timod_mkctl(sizeof(struct T_error_ack
));
195 struct T_error_ack
*err
= (struct T_error_ack
*)&it
->type
;
198 err
->PRIM_type
= T_ERROR_ACK
;
199 err
->ERROR_prim
= prim
;
200 err
->TLI_error
= terr
;
201 err
->UNIX_error
= uerr
; /* FIXME: convert this */
207 static void timod_ok(unsigned int fd
, int prim
)
212 SOLD("creating ok ack");
213 it
= timod_mkctl(sizeof(*ok
));
216 ok
= (struct T_ok_ack
*)&it
->type
;
217 ok
->PRIM_type
= T_OK_ACK
;
218 ok
->CORRECT_prim
= prim
;
224 static int timod_optmgmt(unsigned int fd
, int flag
, char *opt_buf
, int opt_len
, int do_ret
)
227 int ret_space
, ret_len
;
229 char *ret_pos
,*ret_buf
;
230 int (*sys_socketcall
)(int, unsigned long *) =
231 (int (*)(int, unsigned long *))SYS(socketcall
);
232 mm_segment_t old_fs
= get_fs();
235 SOLDD(("fd %u flg %u buf %p len %u doret %u",fd
,flag
,opt_buf
,opt_len
,do_ret
));
236 if (!do_ret
&& (!opt_buf
|| opt_len
<= 0))
238 SOLD("getting page");
239 ret_pos
= ret_buf
= getpage();
240 ret_space
= BUF_SIZE
;
245 while(opt_len
>= sizeof(struct opthdr
)) {
249 opt
= (struct opthdr
*)ret_pos
;
250 if (ret_space
< sizeof(struct opthdr
)) {
254 SOLD("getting opthdr");
255 if (copy_from_user(opt
, opt_buf
, sizeof(struct opthdr
)) ||
256 opt
->len
> opt_len
) {
261 if (flag
== T_NEGOTIATE
) {
264 SOLD("handling T_NEGOTIATE");
265 buf
= ret_pos
+ sizeof(struct opthdr
);
266 if (ret_space
< opt
->len
+ sizeof(struct opthdr
) ||
267 copy_from_user(buf
, opt_buf
+sizeof(struct opthdr
), opt
->len
)) {
273 args
[1] = opt
->level
;
277 SOLD("calling SETSOCKOPT");
279 error
= sys_socketcall(SYS_SETSOCKOPT
, args
);
285 SOLD("SETSOCKOPT ok");
287 orig_opt_len
= opt
->len
;
288 opt
->len
= ret_space
- sizeof(struct opthdr
);
294 args
[1] = opt
->level
;
296 args
[3] = (long)(ret_pos
+sizeof(struct opthdr
));
297 args
[4] = (long)&opt
->len
;
298 SOLD("calling GETSOCKOPT");
300 error
= sys_socketcall(SYS_GETSOCKOPT
, args
);
306 SOLD("GETSOCKOPT ok");
307 ret_space
-= sizeof(struct opthdr
) + opt
->len
;
308 ret_len
+= sizeof(struct opthdr
) + opt
->len
;
309 ret_pos
+= sizeof(struct opthdr
) + opt
->len
;
310 opt_len
-= sizeof(struct opthdr
) + orig_opt_len
;
311 opt_buf
+= sizeof(struct opthdr
) + orig_opt_len
;
316 SOLD("generating ret msg");
318 timod_error(fd
, T_OPTMGMT_REQ
, failed
, -error
);
321 it
= timod_mkctl(sizeof(struct T_optmgmt_ack
) + ret_len
);
323 struct T_optmgmt_ack
*ack
=
324 (struct T_optmgmt_ack
*)&it
->type
;
326 ack
->PRIM_type
= T_OPTMGMT_ACK
;
327 ack
->OPT_length
= ret_len
;
328 ack
->OPT_offset
= sizeof(struct T_optmgmt_ack
);
329 ack
->MGMT_flags
= (failed
? T_FAILURE
: flag
);
330 memcpy(((char*)ack
)+sizeof(struct T_optmgmt_ack
),
336 SOLDD(("put_page %p\n", ret_buf
));
342 int timod_putmsg(unsigned int fd
, char *ctl_buf
, int ctl_len
,
343 char *data_buf
, int data_len
, int flags
)
345 int ret
, error
, terror
;
349 struct sol_socket_struct
*sock
;
350 mm_segment_t old_fs
= get_fs();
352 int (*sys_socketcall
)(int, unsigned long *) =
353 (int (*)(int, unsigned long *))SYS(socketcall
);
354 int (*sys_sendto
)(int, void *, size_t, unsigned, struct sockaddr
*, int) =
355 (int (*)(int, void *, size_t, unsigned, struct sockaddr
*, int))SYS(sendto
);
356 filp
= current
->files
->fd
[fd
];
357 ino
= filp
->f_dentry
->d_inode
;
358 sock
= (struct sol_socket_struct
*)filp
->private_data
;
360 if (get_user(ret
, (int *)A(ctl_buf
)))
365 struct T_bind_req req
;
367 SOLDD(("bind %016lx(%016lx)\n", sock
, filp
));
369 if (sock
->state
!= TS_UNBND
) {
370 timod_error(fd
, T_BIND_REQ
, TOUTSTATE
, 0);
374 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
375 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
379 if (req
.ADDR_offset
&& req
.ADDR_length
) {
380 if (req
.ADDR_length
> BUF_SIZE
) {
381 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
386 if (copy_from_user(buf
, ctl_buf
+ req
.ADDR_offset
, req
.ADDR_length
)) {
387 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
391 SOLD("got ctl data");
394 args
[2] = req
.ADDR_length
;
395 SOLD("calling BIND");
397 error
= sys_socketcall(SYS_BIND
, args
);
400 SOLD("BIND returned");
405 if (req
.CONIND_number
) {
407 args
[1] = req
.CONIND_number
;
408 SOLD("calling LISTEN");
410 error
= sys_socketcall(SYS_LISTEN
, args
);
414 it
= timod_mkctl(sizeof(struct T_bind_ack
)+sizeof(struct sockaddr
));
416 struct T_bind_ack
*ack
;
418 ack
= (struct T_bind_ack
*)&it
->type
;
419 ack
->PRIM_type
= T_BIND_ACK
;
420 ack
->ADDR_offset
= sizeof(*ack
);
421 ack
->ADDR_length
= sizeof(struct sockaddr
);
422 ack
->CONIND_number
= req
.CONIND_number
;
424 args
[1] = (long)(ack
+sizeof(*ack
));
425 args
[2] = (long)&ack
->ADDR_length
;
427 sys_socketcall(SYS_GETSOCKNAME
,args
);
429 sock
->state
= TS_IDLE
;
430 timod_ok(fd
, T_BIND_REQ
);
431 timod_queue_end(fd
, it
);
455 timod_error(fd
, T_BIND_REQ
, terror
, -error
);
461 struct T_conn_req req
;
462 unsigned short oldflags
;
465 if (sock
->state
!= TS_UNBND
&& sock
->state
!= TS_IDLE
) {
466 timod_error(fd
, T_CONN_REQ
, TOUTSTATE
, 0);
470 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
471 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
475 if (ctl_len
> BUF_SIZE
) {
476 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
481 if (copy_from_user(buf
, ctl_buf
, ctl_len
)) {
482 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
490 printk("returned data (%d bytes): ",len
);
494 printk("%02x",(unsigned char)*ptr
++);
499 SOLD("got ctl data");
501 args
[1] = (long)buf
+req
.DEST_offset
;
502 args
[2] = req
.DEST_length
;
503 oldflags
= filp
->f_flags
;
504 filp
->f_flags
&= ~O_NONBLOCK
;
505 SOLD("calling CONNECT");
507 error
= sys_socketcall(SYS_CONNECT
, args
);
509 filp
->f_flags
= oldflags
;
510 SOLD("CONNECT done");
512 struct T_conn_con
*con
;
514 it
= timod_mkctl(ctl_len
);
519 con
= (struct T_conn_con
*)&it
->type
;
524 printk("returned data (%d bytes): ",len
);
528 printk("%02x",(unsigned char)*ptr
++);
533 memcpy(con
, buf
, ctl_len
);
534 SOLD("copied ctl_buf");
535 con
->PRIM_type
= T_CONN_CON
;
536 sock
->state
= TS_DATA_XFER
;
538 struct T_discon_ind
*dis
;
540 it
= timod_mkctl(sizeof(*dis
));
546 dis
= (struct T_discon_ind
*)&it
->type
;
547 dis
->PRIM_type
= T_DISCON_IND
;
548 dis
->DISCON_reason
= -error
; /* FIXME: convert this as in iABI_errors() */
552 timod_ok(fd
, T_CONN_REQ
);
554 timod_queue_end(fd
, it
);
555 SOLD("CONNECT done");
560 struct T_optmgmt_req req
;
562 if (copy_from_user(&req
, ctl_buf
, sizeof(req
)))
565 return timod_optmgmt(fd
, req
.MGMT_flags
,
566 req
.OPT_offset
> 0 ? ctl_buf
+ req
.OPT_offset
: NULL
,
571 struct T_unitdata_req req
;
574 SOLD("T_UNITDATA_REQ");
575 if (sock
->state
!= TS_IDLE
&& sock
->state
!= TS_DATA_XFER
) {
576 timod_error(fd
, T_CONN_REQ
, TOUTSTATE
, 0);
580 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
581 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
587 char * ptr
= ctl_buf
+req
.DEST_offset
;
588 int len
= req
.DEST_length
;
589 printk("socket address (%d bytes): ",len
);
595 printk("%02x",(unsigned char)c
);
601 err
= sys_sendto(fd
, data_buf
, data_len
, 0, req
.DEST_length
> 0 ? (struct sockaddr
*)(ctl_buf
+req
.DEST_offset
) : NULL
, req
.DEST_length
);
605 printk("timod: sendto failed to send all the data\n");
608 timod_error(fd
, T_CONN_REQ
, TSYSERR
, -err
);
612 printk("timod_putmsg: unsuported command %u.\n", ret
);
618 /* copied directly from fs/select.c */
620 static void free_wait(poll_table
* p
)
622 struct poll_table_entry
* entry
= p
->entry
+ p
->nr
;
628 remove_wait_queue(entry
->wait_address
,&entry
->wait
);
634 int timod_getmsg(unsigned int fd
, char *ctl_buf
, int ctl_maxlen
, s32
*ctl_len
,
635 char *data_buf
, int data_maxlen
, s32
*data_len
, int *flags_p
)
641 struct sol_socket_struct
*sock
;
642 struct T_unitdata_ind udi
;
643 mm_segment_t old_fs
= get_fs();
647 int (*sys_socketcall
)(int, unsigned long *) =
648 (int (*)(int, unsigned long *))SYS(socketcall
);
649 int (*sys_recvfrom
)(int, void *, size_t, unsigned, struct sockaddr
*, int *);
652 SOLDD(("%u %p %d %p %p %d %p %d\n", fd
, ctl_buf
, ctl_maxlen
, ctl_len
, data_buf
, data_maxlen
, data_len
, *flags_p
));
653 filp
= current
->files
->fd
[fd
];
654 ino
= filp
->f_dentry
->d_inode
;
655 sock
= (struct sol_socket_struct
*)filp
->private_data
;
656 SOLDD(("%p %p\n", sock
->pfirst
, sock
->pfirst
? sock
->pfirst
->next
: NULL
));
657 if ( ctl_maxlen
> 0 && !sock
->pfirst
&& ino
->u
.socket_i
.type
== SOCK_STREAM
658 && sock
->state
== TS_IDLE
) {
659 SOLD("calling LISTEN");
663 sys_socketcall(SYS_LISTEN
, args
);
667 if (!(filp
->f_flags
& O_NONBLOCK
)) {
668 poll_table wait_table
, *wait
;
669 struct poll_table_entry
*entry
;
670 SOLD("getting poll_table");
671 entry
= (struct poll_table_entry
*)__get_free_page(GFP_KERNEL
);
676 wait_table
.entry
= entry
;
680 set_current_state(TASK_INTERRUPTIBLE
);
681 /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
682 /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
683 /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
684 /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */
685 /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */
686 /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */
687 if (ctl_maxlen
>= 0 && sock
->pfirst
&& (*flags_p
!= MSG_HIPRI
|| sock
->pfirst
->pri
== MSG_HIPRI
))
689 SOLD("cond 1 passed");
692 *flags_p
!= MSG_HIPRI
&&
694 ((filp
->f_op
->poll(filp
, wait
) & POLLIN
) ||
695 (filp
->f_op
->poll(filp
, NULL
) & POLLIN
) ||
696 signal_pending(current
))
700 if( *flags_p
== MSG_HIPRI
) {
701 SOLD("avoiding lockup");
708 current
->state
= TASK_RUNNING
;
709 free_wait(&wait_table
);
710 free_page((unsigned long)entry
);
711 if (signal_pending(current
)) {
712 SOLD("signal pending");
716 if (ctl_maxlen
>= 0 && sock
->pfirst
) {
717 struct T_primsg
*it
= sock
->pfirst
;
719 #define min(a,b) ((a)<(b)?(a):(b))
721 int l
= min(ctl_maxlen
, it
->length
);
722 SCHECK_MAGIC((char*)((u64
)(((char *)&it
->type
)+sock
->offset
+it
->length
+7)&~7),MKCTL_MAGIC
);
723 SOLD("purting ctl data");
724 if(copy_to_user(ctl_buf
,
725 (char*)&it
->type
+ sock
->offset
, l
))
728 if(put_user(l
, ctl_len
))
738 SOLD("removing message");
739 sock
->pfirst
= it
->next
;
742 SOLDD(("getmsg kfree %016lx->%016lx\n", it
, sock
->pfirst
));
750 if (ctl_maxlen
>= 0) {
751 SOLD("ACCEPT perhaps?");
752 if (ino
->u
.socket_i
.type
== SOCK_STREAM
&& sock
->state
== TS_IDLE
) {
753 struct T_conn_ind ind
;
754 char *buf
= getpage();
757 SOLD("trying ACCEPT");
758 if (put_user(ctl_maxlen
- sizeof(ind
), ctl_len
))
762 args
[2] = (long)&len
;
763 oldflags
= filp
->f_flags
;
764 filp
->f_flags
|= O_NONBLOCK
;
765 SOLD("calling ACCEPT");
767 error
= sys_socketcall(SYS_ACCEPT
, args
);
769 filp
->f_flags
= oldflags
;
778 if (sizeof(ind
) > ctl_maxlen
) {
779 SOLD("generating CONN_IND");
780 ind
.PRIM_type
= T_CONN_IND
;
781 ind
.SRC_length
= len
;
782 ind
.SRC_offset
= sizeof(ind
);
783 ind
.OPT_length
= ind
.OPT_offset
= 0;
784 ind
.SEQ_number
= error
;
785 if(copy_to_user(ctl_buf
, &ind
, sizeof(ind
))||
786 put_user(sizeof(ind
)+ind
.SRC_length
,ctl_len
))
788 SOLD("CONN_IND created");
790 if (data_maxlen
>= 0)
791 put_user(0, data_len
);
792 SOLD("CONN_IND done");
795 if (len
>ctl_maxlen
) {
796 SOLD("data don't fit");
798 return -EFAULT
; /* XXX - is this ok ? */
800 if(copy_to_user(ctl_buf
,buf
,len
) || put_user(len
,ctl_len
)){
801 SOLD("can't copy data");
809 SOLD("checking data req");
810 if (data_maxlen
<= 0) {
811 if (data_maxlen
== 0)
812 put_user(0, data_len
);
814 put_user(0, ctl_len
);
818 if (ctl_maxlen
> sizeof(udi
) && sock
->state
== TS_IDLE
) {
820 tmpbuf
= ctl_buf
+ sizeof(udi
);
821 tmplen
= ctl_maxlen
- sizeof(udi
);
823 SOLD("udi does not fit");
827 if (put_user(tmplen
, ctl_len
))
830 oldflags
= filp
->f_flags
;
831 filp
->f_flags
|= O_NONBLOCK
;
832 SOLD("calling recvfrom");
833 sys_recvfrom
= (int (*)(int, void *, size_t, unsigned, struct sockaddr
*, int *))SYS(recvfrom
);
834 error
= sys_recvfrom(fd
, data_buf
, min(0,data_maxlen
), 0, (struct sockaddr
*)tmpbuf
, ctl_len
);
835 filp
->f_flags
= oldflags
;
838 SOLD("error >= 0" ) ;
839 if (error
&& ctl_maxlen
> sizeof(udi
) && sock
->state
== TS_IDLE
) {
840 SOLD("generating udi");
841 udi
.PRIM_type
= T_UNITDATA_IND
;
842 get_user(udi
.SRC_length
, ctl_len
);
843 udi
.SRC_offset
= sizeof(udi
);
844 udi
.OPT_length
= udi
.OPT_offset
= 0;
845 copy_to_user(ctl_buf
, &udi
, sizeof(udi
));
846 put_user(sizeof(udi
)+udi
.SRC_length
, ctl_len
);
849 put_user(0, ctl_len
);
850 put_user(error
, data_len
);
855 asmlinkage
int solaris_getmsg(unsigned int fd
, u32 arg1
, u32 arg2
, u32 arg3
)
859 struct strbuf
*ctlptr
, *datptr
;
860 struct strbuf ctl
, dat
;
867 if(fd
>= NR_OPEN
) goto out
;
869 filp
= current
->files
->fd
[fd
];
872 ino
= filp
->f_dentry
->d_inode
;
878 ctlptr
= (struct strbuf
*)A(arg1
);
879 datptr
= (struct strbuf
*)A(arg2
);
880 flgptr
= (int *)A(arg3
);
885 if (copy_from_user(&ctl
,ctlptr
,sizeof(struct strbuf
)) ||
886 put_user(-1,&ctlptr
->len
))
892 if (copy_from_user(&dat
,datptr
,sizeof(struct strbuf
)) ||
893 put_user(-1,&datptr
->len
))
898 if (get_user(flags
,flgptr
))
912 error
= timod_getmsg(fd
,(char*)A(ctl
.buf
),ctl
.maxlen
,&ctlptr
->len
,
913 (char*)A(dat
.buf
),dat
.maxlen
,&datptr
->len
,&flags
);
915 if (!error
&& put_user(flags
,flgptr
))
923 asmlinkage
int solaris_putmsg(unsigned int fd
, u32 arg1
, u32 arg2
, u32 arg3
)
927 struct strbuf
*ctlptr
, *datptr
;
928 struct strbuf ctl
, dat
;
929 int flags
= (int) arg3
;
934 if(fd
>= NR_OPEN
) goto out
;
936 filp
= current
->files
->fd
[fd
];
939 ino
= filp
->f_dentry
->d_inode
;
943 (MAJOR(ino
->i_rdev
) != 30 || MINOR(ino
->i_rdev
) != 1))
946 ctlptr
= (struct strbuf
*)A(arg1
);
947 datptr
= (struct strbuf
*)A(arg2
);
952 if (copy_from_user(&ctl
,ctlptr
,sizeof(ctl
)))
954 if (ctl
.len
< 0 && flags
) {
964 if (copy_from_user(&dat
,datptr
,sizeof(dat
)))
971 error
= timod_putmsg(fd
,(char*)A(ctl
.buf
),ctl
.len
,
972 (char*)A(dat
.buf
),dat
.len
,flags
);