Nov 2, 1999 onl8v1: Solaris 7 cc ドライバのテスト. cc ドライバのデバッグ#02 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (http://www-online.kek.jp/~inoue/CAMAC/ onl8v1-sol7/debug-step02.txt) 高エネルギー加速器研究機構 素粒子原子核研究所 物理、オンライングループ 井上 栄二 (1). 現状確認 (A). SPARC CPU-8VT、Solaris7、VMEドライバが届いた。 (B). CPU-8VT に Solaris7 のシステムをインストールした。 (C). /etc の下の各設定、および /export/home の作成をやった。 (D). CPU-8VT に Solaris7用の VMEドライバ、FRCdrv-2.7(FRCvme v2.4.1) をインストールした。 (E). CPU-8VT(onl8v1) に ccドライバをインストールした。 "make load" を実行すると attach 時にエラーを起こす。 (F). attach 時にエラーを起こす件は直った。 (2). ここでやるべきこと ccドライバプログラムをデバッグする。 "make" 時に warning が出る件について調べる。 (3). 症状確認 (3-1). コンパイラバージョン 4.2.1 を使った場合 onl8v1[43]% which cc /kek/compilers/volume5/SUNWspro/bin/cc onl8v1[44]% cc -V cc: WorkShop Compilers 4.2.1 04 Feb 1997 C 4.2.1 usage: cc [ options] files. Use 'cc -flags' for details onl8v1[45]% onl8v1[45]% pwd /export/home/onl8v1/inoue/CAMAC/Driver/FORCE-50T-sol2.6 onl8v1[46]% make clean \rm -f cc *.o libcamac.a cam1 cam2 cam3 *~ core onl8v1[47]% make ./script/cc_build.sh [Building for sun4m] "cc.c", line 174: warning: initialization type mismatch "cc.c", line 945: warning: improper pointer/integer combination: arg #1 "cc.c", line 1021: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 1021: warning: improper pointer/integer combination: op "=" "cc.c", line 1031: warning: improper pointer/integer combination: arg #1 "cc.c", line 2811: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 2811: warning: improper pointer/integer combination: op "=" rm -f cc.o cc -O -c camlib.c -o camlib.o -I. cc -O -c forlib.c -o forlib.o -I. rm -f libcamac.a ar rcv libcamac.a camlib.o forlib.o a - camlib.o a - forlib.o ar: writing libcamac.a cc -O cam1.c -o cam1 -I. -L. -lcamac f77 -fast -O3 -u cam2.f -o cam2 -I. -L. -lcamac cam2.f: MAIN: cc -O cam3.c -o cam3 -I. -L. -lcamac onl8v1[48]% (3-2). コンパイラバージョン 5.0 を使った場合 コンパイラバージョン 5.0 が利用できるようになった。 これ以降は 5.0の バージョンでテストする。 (3-2-1). .cshrcファイルを修正 onl8v1[87]% vi ~/.cshrc : set path=( /kek/compilers/ws5.0/SUNWspro/bin) set path=($path /kek/compilers/volume5/SUNWspro/bin) : setenv MANPATH /usr/local/man:/kek/compilers/ws5.0/SUNWspro/man:/kek/compilers/v olume5/SUNWspro/man:/usr/man:/kek/local/man:/kek/local/X11R6/man:/usr/openwin/ma n #setenv LD_LIBRARY_PATH /kek/compilers/volume5/SUNWspro/lib:/usr/ucblib setenv LD_LIBRARY_PATH /kek/compilers/ws5.0/SUNWspro/lib:/kek/compilers/volume5/ SUNWspro/lib #setenv LD_RUN_PATH /usr/openwin/lib:/kek/compilers/volume5/SUNWspro/lib:/usr/uc blib setenv LD_RUN_PATH /kek/compilers/ws5.0/SUNWspro/lib:/kek/compilers/volume5/SUNW spro/lib:/usr/openwin/lib : onl8v1[88]% source ~/.cshrc onl8v1[93]% which cc /kek/compilers/ws5.0/SUNWspro/bin/cc onl8v1[94]% cc -V cc: WorkShop Compilers 5.0 98/12/15 C 5.0 usage: cc [ options] files. Use 'cc -flags' for details onl8v1[95]% (3-2-2). cc.cファイルをコンパイルする onl8v1[95]% pwd /export/home/onl8v1/inoue/CAMAC/Driver/FORCE-50T-sol2.6 onl8v1[96]% ls Makefile cam2.f camlib.o cc.h k2917.h README cam3* cc cc_common.h libcamac.a cam1* cam3.c cc.c cc_config.h script/ cam1.c camlib.c cc.c-org forlib.c cam2* camlib.h cc.conf forlib.o onl8v1[97]% make clean \rm -f cc *.o libcamac.a cam1 cam2 cam3 *~ core onl8v1[98]% make ./script/cc_build.sh [Building for sun4m] "cc.c", line 174: warning: initialization type mismatch "cc.c", line 945: warning: improper pointer/integer combination: arg #1 "cc.c", line 1021: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 1021: warning: improper pointer/integer combination: op "=" "cc.c", line 1031: warning: improper pointer/integer combination: arg #1 "cc.c", line 2811: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 2811: warning: improper pointer/integer combination: op "=" rm -f cc.o cc -O -c camlib.c -o camlib.o -I. cc -O -c forlib.c -o forlib.o -I. rm -f libcamac.a ar rcv libcamac.a camlib.o forlib.o a - camlib.o a - forlib.o ar: writing libcamac.a cc -O cam1.c -o cam1 -I. -L. -lcamac f77 -fast -O3 -u cam2.f -o cam2 -I. -L. -lcamac cam2.f: MAIN: cc -O cam3.c -o cam3 -I. -L. -lcamac onl8v1[99]% バージョン4.2.1 を使ってコンパイルした時と同じ結果になった。 (4). デバッグ バージョン5.0 のコンパイラを使って warning が出る原因を追求する。 (4-1). cc.cファイルをチェックする warning を出している行番号 174、945、1021、1031、2811 を確認。 onl8v1[48]% vi cc.c : 135 static int cc_ioctl(dev_t dev, int cmd, int arg, int flag, cred_t *cred_ p, 136 int *rval_p); : 166 static struct cb_ops cc_cb_ops = { 167 cc_open, /* open */ 168 cc_close, /* close */ 169 nodev, /* strategy (not block device) */ 170 nodev, /* print (no print routine) */ 171 nodev, /* dump (no dump routine) */ 172 nodev, /* read (no read routine; write-only device */ 173 cc_write, /* write */ 174 cc_ioctl, /* ioctl */ 175 nodev, /* devmap (no devmap routine) */ 176 nodev, /* mmap (no mmap routine) */ 177 nodev, /* segmap (no segmap routine) */ 178 nochpoll, /* poll (no chpoll routine) */ 179 ddi_prop_op, /* cb_prop_op */ 180 0, /* streamtab */ 181 D_NEW | D_MP /* Driver comaptibility flag */ 182 }; : 945 untimeout(cc->timeout_id); : 956 static int 957 cc_ioctl(dev_t dev, int cmd, int arg, int flag, cred_t *cred_p, int *rva l_p) 958 { : 1021 cc->timeout_id = timeout(cc_timeout, (caddr_t)&unit, cc->data1 * hz); : 1031 untimeout(cc->timeout_id); : 2811 cc->timeout_id = timeout(cc_timeout, (caddr_t)&unit, CC_TIMEOUT_DMA * hz); : onl8v1[49]% (4-2). cc.cファイルを修正(その1) "cc.c", line 174: warning: initialization type mismatch の warning について調べる。 ioctl() を man でチェック。 onl8v1[83]% man -k ioctl /usr/local/man/windex: No such file or directory IOC_CONVERT_FROM IOC_CONVERT_FROM (9f) - determine if there is a need to translate M_IOCTL contents. iocblk iocblk (9s) - STREAMS data structure for the M_IOCTL message type ioctl ioctl (2) - control device ioctl ioctl (9e) - control a character device mkiocb mkiocb (9f) - allocates a STREAMS ioctl block for M_IOCTL messages in the kernel. smart2cfg smart2cfg (1) - Compaq Smart-2 EISA/PCI and Smart-2SL PCI Array Controller ioctl utility sockio sockio (7i) - ioctls that operate directly on sockets streamio streamio (7i) - STREAMS ioctl commands /kek/local/man/windex: No such file or directory /kek/local/X11R6/man/windex: No such file or directory onl8v1[84]% onl8v1[85]% man -s 9e ioctl Driver Entry Points ioctl(9E) NAME ioctl - control a character device SYNOPSIS #include #include #include #include #include #include int prefixioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p); INTERFACE LEVEL Architecture independent level 1 (DDI/DKI). This entry point is optional. ARGUMENTS dev Device number. cmd Command argument the driver ioctl() routine interprets as the operation to be performed. arg Passes parameters between a user program and the driver. When used with terminals, the argument is the address of a user program structure containing driver or hardware settings. Alternatively, the argument may be a value that has meaning only to the driver. The interpretation of the argument is driver dependent and usually depends on the com- mand type; the kernel does not interpret the argu- ment. mode A bit field that contains: o Information set when the device was opened. The driver may use it to determine if the device was opened for reading or writing. The driver can make this determination by checking the FREAD or FWRITE flags. See the flag argument description of the open() routine for further values. o Information on whether the caller is a 32- bit or 64-bit thread. o In some circumstances address space informa- tion about the arg argument. See below. cred_p Pointer to the user credential structure. SunOS 5.7 Last change: 3 Dec 1996 1 Driver Entry Points ioctl(9E) rval_p Pointer to return value for calling process. The driver may elect to set the value which is valid only if the ioctl() succeeds. DESCRIPTION ioctl() provides character-access drivers with an alternate entry point that can be used for almost any operation other than a simple transfer of characters in and out of buffers. Most often, ioctl() is used to control device hardware parameters and establish the protocol used by the driver in processing data. The kernel determines that this is a character device, and looks up the entry point routines in cb_ops(9S). The kernel then packages the user request and arguments as integers and passes them to the driver's ioctl() routine. The kernel itself does no processing of the passed command, so it is up to the user program and the driver to agree on what the arguments mean. I/O control commands are used to implement the terminal set- tings passed from ttymon(1M) and stty(1), to format disk devices, to implement a trace driver for debugging, and to clean up character queues. Since the kernel does not inter- pret the command type that defines the operation, a driver is free to define its own commands. Drivers that use an ioctl() routine typically have a com- mand to ``read'' the current ioctl() settings, and at least one other that sets new settings. Drivers can use the mode argument to determine if the device unit was opened for reading or writing, if necessary, by checking the FREAD or FWRITE setting. If the third argument, arg, is a pointer to a user buffer, the driver can call the copyin(9F) and copyout(9F) func- tions to transfer data between kernel and user space. Other kernel subsystems may need to call into the drivers ioctl() routine. Drivers that intend to allow their ioctl() routine to be used in this way should publish the ddi- kernel-ioctl property on the associated devinfo node(s). When the ddi-kernel-ioctl property is present, the mode argument is used to pass address space information about arg through to the driver. If the driver expects arg to contain a buffer address, and the FKIOCTL flag is set in mode, then the driver should assume that it is being handed a kernel buffer address. Otherwise, arg may be the address of a buffer from a user program. The driver can use ddi_copyin(9F) and ddi_copyout(9F) perform the correct type of copy operation for either kernel or user address spaces. SunOS 5.7 Last change: 3 Dec 1996 2 Driver Entry Points ioctl(9E) See the example on ddi_copyout(9F). Drivers have to interact with 32-bit and 64-bit applica- tions. If a device driver shares data structures with the application (for example, through exported kernel memory) and the driver gets recompiled for a 64-bit kernel but the application remains 32-bit, binary layout of any data struc- tures will be incompatible if they contain longs or pointers. The driver needs to know whether there is a model mismatch between the current thread and the kernel and take necessary action. The mode argument has additional bits set to determine the C Language Type Model which the current thread expects. mode has FILP32 set if the current thread expects 32-bit ( ILP32) semantics, or FLP64 if the current thread expects 64-bit ( LP64) semantics. mode is used in combination with ddi_model_convert_from(9F) and the FMODELS mask to determine whether there is a data model mismatch between the current thread and the device driver (see the example below). The device driver might have to adjust the shape of data structures before exporting them to a user thread which supports a different data model. To implement I/O control commands for a driver the following two steps are required: 1. Define the I/O control command names and the associ- ated value in the driver's header and comment the com- mands. 2. Code the ioctl() routine in the driver that defines the functionality for each I/O control command name that is in the header. The ioctl() routine is coded with instructions on the proper action to take for each command. It is commonly a switch statement, with each case definition corresponding to an ioctl() name to identify the action that should be taken. However, the command passed to the driver by the user process is an integer value associated with the command name in the header. RETURN VALUES ioctl() should return 0 on success, or the appropriate error number. The driver may also set the value returned to the calling process through rval_p. EXAMPLES Example 1: ioctl() entry point The following is an example of the ioctl() entry point and how to support 32-bit and 64-bit applications with the same device driver. SunOS 5.7 Last change: 3 Dec 1996 3 Driver Entry Points ioctl(9E) struct passargs32 { int len; caddr32_t addr; }; struct passargs { int len; caddr_t addr; }; xxioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { struct passargs pa; #ifdef _MULTI_DATAMODEL switch (ddi_model_convert_from(mode & FMODELS)) { case DDI_MODEL_ILP32: { struct passargs32 pa32; ddi_copyin(arg, &pa32, sizeof (struct passargs32), mode); pa.len = pa32.len; pa.address = pa32.address; break; } case DDI_MODEL_NONE: ddi_copyin(arg, &pa, sizeof (struct passargs), mode); break; } #else /* _MULTI_DATAMODEL */ ddi_copyin(arg, &pa, sizeof (struct passargs), mode); #endif /* _MULTI_DATAMODEL */ do_ioctl(&pa); .... } SEE ALSO stty(1), ttymon(1M), dkio(7I), fbio(7I), termio(7I), open(9E), put(9E), srv(9E), copyin(9F), copyout(9F), ddi_copyin(9F), ddi_copyout(9F), ddi_model_convert_from(9F), cb_ops(9S) WARNINGS Non-STREAMS driver ioctl() routines must make sure that user data is copied into or out of the kernel address space explicitly using copyin(9F), copyout(9F), ddi_copyin(9F), or ddi_copyout(9F), as appropriate. It is a severe error to simply dereference pointers to the user address space, even when in user context. SunOS 5.7 Last change: 3 Dec 1996 4 Driver Entry Points ioctl(9E) Failure to use the appropriate copying routines can result in panics under load on some platforms, and reproducible panics on others. NOTES STREAMS drivers do not have ioctl() routines. The stream head converts I/O control commands to M_IOCTL messages, which are handled by the driver's put(9E) or srv(9E) rou- tine. SunOS 5.7 Last change: 3 Dec 1996 5 (4-2-1). cc.cファイルの問題点 (A). man によると xx_ioctl()を使用する場合には、"sys/cred.h" を インクルードすることになっているが、cc.cファイルでは直接には "cred.h"をインクルードしてない。 どのヘッダファイル中でやって いるかチェック。 onl8v1[89]% : #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* add logichouse */ #include #include /* end */ #include #include "cc_config.h" #include "cc_common.h" #include "cc.h" #include "k2917.h" : onl8v1[90]% onl8v1[92]% grep cred.h * onl8v1[93]% grep cred.h /usr/include/sys/* /usr/include/sys/class.h:#include /usr/include/sys/conf.h:#include /usr/include/sys/cred.h:#pragma ident "@(#)cred.h 1.21 97/01/09 SMI" /* SVr4.0 1.8 */ /usr/include/sys/cred.h:struct proc; /* cred.h is included in proc.h */ /usr/include/sys/devops.h:#include /usr/include/sys/flock_impl.h:#include /usr/include/sys/fs_subr.h:#include /usr/include/sys/pathname.h:#include /usr/include/sys/proc.h:#include /usr/include/sys/rce.h:#include /usr/include/sys/socketvar.h:#include /usr/include/sys/stream.h:#include /usr/include/sys/strredir.h:#include /usr/include/sys/t_kuser.h:#include /usr/include/sys/vfs.h:#include /usr/include/sys/vnode.h:#include onl8v1[94]% onl8v1[97]% vi /usr/include/sys/conf.h : #include : onl8v1[98]% "sys/conf.h"ファイル中でインクルードしていた。 ok. (B). man によると arg引数のタイプは intptr_t になっているが、 cc.cファイルでは intタイプになっている。 チェック。 cc.cファイル中の arg引数のタイプは intptr_t に変更してコンパイル し直してみる。 onl8v1[106]% vi cc.c : 134 static int cc_write(dev_t dev, struct uio *uio, cred_t *cred_p); 135 /* E.Inoue 136 static int cc_ioctl(dev_t dev, int cmd, int arg, int flag, cred_t *cred_ p, 137 int *rval_p); 138 end */ 139 static int cc_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t * cred_p, 140 int *rval_p); 141 static int cc_strategy(struct buf *bp); : "cc.c" 2937 lines, 75225 characters onl8v1[108]% onl8v1[114]% pwd /export/home/onl8v1/inoue/CAMAC/Driver/FORCE-50T-sol2.6 onl8v1[115]% make clean \rm -f cc *.o libcamac.a cam1 cam2 cam3 *~ core onl8v1[116]% make ./script/cc_build.sh [Building for sun4m] "cc.c", line 949: warning: improper pointer/integer combination: arg #1 "cc.c", line 962: identifier redeclared: cc_ioctl current : function(ulong, int, int, int, pointer to struct cred {uint cr_ref, int cr_uid, int cr_gid, int cr_ruid, int cr_rgid, int cr... previous: function(ulong, int, long, int, pointer to struct cred {uint cr_ref, int cr_uid, int cr_gid, int cr_ruid, int cr_rgid, int c... : "cc.c", line 139 "cc.c", line 1025: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 1025: warning: improper pointer/integer combination: op "=" "cc.c", line 1035: warning: improper pointer/integer combination: arg #1 "cc.c", line 2815: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 2815: warning: improper pointer/integer combination: op "=" "cc.c", line 2938: warning: static function called but not defined: cc_ioctl() cc: acomp failed for cc.c ld: fatal: file cc.o: open failed: No such file or directory *** Error code 1 make: Fatal error: Command failed for target `cc' onl8v1[117]% ok. 174行目の warning "initialization type mismatch" は出なくなった。 しかし、新たに "cc.c", line 2938: warning: static function called but not defined: cc_ioctl() の warning が出た。 チェック。 onl8v1[46]% vi cc.c : 2935 *retlen = cc->retlen; 2936 return cc->status; 2937 } ~ 2938行は存在しない。 cc_ioctl()をチェック。 : 960 static int 961 cc_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p) 962 /* E.Inoue 963 cc_ioctl(dev_t dev, int cmd, int arg, int flag, cred_t *cred_p, int *rva l_p) 964 end */ 965 { 966 /* register struct cc_device *cc = &ccdevice[0]; */ 967 register struct cc_device *cc; : "cc.c" 2940 lines, 75326 characters onl8v1[50]% onl8v1[50]% make clean \rm -f cc *.o libcamac.a cam1 cam2 cam3 *~ core onl8v1[51]% make ./script/cc_build.sh [Building for sun4m] "cc.c", line 949: warning: improper pointer/integer combination: arg #1 "cc.c", line 1028: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 1028: warning: improper pointer/integer combination: op "=" "cc.c", line 1038: warning: improper pointer/integer combination: arg #1 "cc.c", line 2818: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 2818: warning: improper pointer/integer combination: op "=" rm -f cc.o cc -O -c camlib.c -o camlib.o -I. cc -O -c forlib.c -o forlib.o -I. rm -f libcamac.a ar rcv libcamac.a camlib.o forlib.o a - camlib.o a - forlib.o ar: writing libcamac.a cc -O cam1.c -o cam1 -I. -L. -lcamac f77 -fast -O3 -u cam2.f -o cam2 -I. -L. -lcamac cam2.f: MAIN: cc -O cam3.c -o cam3 -I. -L. -lcamac onl8v1[52]% ok. 行番号2938 の warning "static function called but not defined: cc_ioctl()" は出なくなった。 (4-3). cc.cファイルを修正(その2) "cc.c", line 949: warning: improper pointer/integer combination: arg #1 の warning について調べる。 onl8v1[52]% vi cc.c : 62 struct cc_device { 63 int status; /* current system status */ : 102 int timeout_id; : 116 int data1; 117 /* end */ 118 } ccdevice[NCC]; : 907 static u_int 908 cc_intr(int unit) 909 { 910 /* register struct cc_device *cc = &ccdevice[0]; */ 911 register struct cc_device *cc; 912 /* register struct K_REG *k = cc->k; */ 913 914 cc = ddi_get_soft_state(cc_state,unit); 915 : 949 untimeout(cc->timeout_id); : onl8v1[53]% untimeout についてチェック。 onl8v1[54]% man untimeout Kernel Functions for Drivers untimeout(9F) NAME untimeout - cancel previous timeout function call SYNOPSIS #include #include clock_t untimeout(timeout_id_t id); INTERFACE LEVEL Architecture independent level 1 (DDI/DKI). PARAMETERS id Opaque timeout ID from a previous timeout(9F) call. DESCRIPTION untimeout() cancels a pending timeout(9F) request. untimeout() will not return until the pending callback is cancelled or has run. Because of this, locks acquired by the callback routine should not be held across the call to untimeout() or a deadlock may result. Since no mutex should be held across the call to untimeout(), there is a race condition between the occurrence of an expected event and the execution of the timeout handler. In particular, it should be noted that no problems will result from calling untimeout() for a timeout which is either running on another CPU, or has already com- pleted. Drivers should be structured with the understanding that the arrival of both an interrupt and a timeout for that interrupt can occasionally occur, in either order. RETURN VALUES untimeout() returns -1 if the id is not found. Otherwise, it returns an integer value greater than or equal to 0. CONTEXT untimeout() can be called from user or interrupt context. EXAMPLES Example 1: In the following example, the device driver has issued an IO request and is waiting for the device to respond. If the device does not respond within 5 seconds, the device driver will print out an error message to the console. static void xxtimeout_handler(void *arg) { struct xxstate *xsp = (struct xxstate *)arg; SunOS 5.7 Last change: 18 Feb 1998 1 Kernel Functions for Drivers untimeout(9F) mutex_enter(&xsp->lock); cv_signal(&xsp->cv); xsp->flags |= TIMED_OUT; mutex_exit(&xsp->lock); xsp->timeout_id = 0; } static uint_t xxintr(caddr_t arg) { struct xxstate *xsp = (struct xxstate *)arg; . . . mutex_enter(&xsp->lock); /* Service interrupt */ cv_signal(&xsp->cv); mutex_exit(&xsp->lock); if (xsp->timeout_id != 0) { (void) untimeout(xsp->timeout_id); xsp->timeout_id = 0; } return(DDI_INTR_CLAIMED); } static void xxcheckcond(struct xxstate *xsp) { . . . xsp->timeout_id = timeout(xxtimeout_handler, xsp, (5 * drv_usectohz(1000000))); mutex_enter(&xsp->lock); while (/* Waiting for interrupt or timeout*/) cv_wait(&xsp->cv, &xsp->lock); if (xsp->flags & TIMED_OUT) cmn_err(CE_WARN, "Device not responding"); . . . mutex_exit(&xsp->lock); . . . } SEE ALSO open(9E), cv_signal(9F), cv_wait_sig(9F), delay(9F), timeout(9F) Writing Device Drivers SunOS 5.7 Last change: 18 Feb 1998 2 (4-3-1). cc.cファイルの問題点 (A). man によると untimeout()で使用する引数は、timeout_id_tタイプ であるがcc.cファイルではこの引数を int で定義している。 timeout_id変数を timeout_id_tタイプで定義してコンパイルしてみる。 onl8v1[58]% vi cc.c : /* E.Inoue int timeout_id; end */ timeout_id_t timeout_id; struct buf *bp; : "cc.c" 2943 lines, 75374 characters onl8v1[59]% onl8v1[59]% pwd /export/home/onl8v1/inoue/CAMAC/Driver/FORCE-50T-sol2.6 onl8v1[60]% make clean \rm -f cc *.o libcamac.a cam1 cam2 cam3 *~ core onl8v1[61]% make ./script/cc_build.sh [Building for sun4m] "cc.c", line 1031: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void "cc.c", line 2821: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/include/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void rm -f cc.o cc -O -c camlib.c -o camlib.o -I. cc -O -c forlib.c -o forlib.o -I. rm -f libcamac.a ar rcv libcamac.a camlib.o forlib.o a - camlib.o a - forlib.o ar: writing libcamac.a cc -O cam1.c -o cam1 -I. -L. -lcamac f77 -fast -O3 -u cam2.f -o cam2 -I. -L. -lcamac cam2.f: MAIN: cc -O cam3.c -o cam3 -I. -L. -lcamac onl8v1[62]% ok. 行番号949 の warning "improper pointer/integer combination: arg #1" は出なくなった。 (4-4). cc.cファイルを修正(その3) "cc.c", line 1031: warning: argument #1 is incompatible with prototype: prototype: pointer to function(pointer to void) returning void : "/usr/i nclude/sys/systm.h", line 100 argument : pointer to function(pointer to char) returning void の warning について調べる。 onl8v1[116]% vi cc.c : 149 static void cc_timeout(caddr_t unit); : 963 static int 964 cc_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p) 968 { : 979 minor_t unit; 980 981 unit = getminor(dev); : 1031 cc->timeout_id = timeout(cc_timeout, (caddr_t)&unit, cc->data1 * hz); : onl8v1[117]% onl8v1[127]% man -k timeout /usr/local/man/windex: No such file or directory devmap_set_ctx_timeout devmap_set_ctx_timeout (9f) - set the timeout value for the context management callback ldap_ufn_timeout ldap_ufn (3n) - LDAP user friendly search functions notimeout curs_inopts (3x) - curses terminal input option control routines notimeout notimeout (3xc) - set timed blocking or non-blocking read qtimeout qtimeout (9f) - execute a function after a specified length of time quntimeout quntimeout (9f) - cancel previous qtimeout function call timeout curs_inopts (3x) - curses terminal input option control routines timeout notimeout (3xc) - set timed blocking or non-blocking read timeout timeout (9f) - execute a function after a specified length of time untimeout untimeout (9f) - cancel previous timeout function call wtimeout curs_inopts (3x) - curses terminal input option control routines wtimeout notimeout (3xc) - set timed blocking or non-blocking read /kek/local/man/windex: No such file or directory /kek/local/X11R6/man/windex: No such file or directory XtAddInput XtAddInput (3) - register input, timeout, and workprocs XtAddTimeOut XtAddInput (3) - register input, timeout, and workprocs XtAddWorkProc XtAddInput (3) - register input, timeout, and workprocs XtAppAddTimeOut XtAppAddTimeOut (3) - register and remove timeouts XtAppGetSelectionTimeout XtAppGetSelectionTimeout (3) - set and obtain selection timeout values XtAppSetSelectionTimeout XtAppGetSelectionTimeout (3) - set and obtain selection timeout values XtGetSelectionTimeout XtGetSelectionTimeout (3) - set and obtain selection timeout values XtRemoveTimeOut XtAppAddTimeOut (3) - register and remove timeouts XtSetSelectionTimeout XtGetSelectionTimeout (3) - set and obtain selection timeout values onl8v1[128]% onl8v1[128]% man -s 9f timeout Kernel Functions for Drivers timeout(9F) NAME timeout - execute a function after a specified length of time SYNOPSIS #include #include timeout_id_t timeout(void (* func)(void *), void *arg, clock_t ticks); INTERFACE LEVEL Architecture independent level 1 (DDI/DKI). PARAMETERS func Kernel function to invoke when the time increment expires. arg Argument to the function. ticks Number of clock ticks to wait before the function is called. DESCRIPTION The timeout() function schedules the specified function to be called after a specified time interval. The exact time interval over which the timeout takes effect cannot be guaranteed, but the value given is a close approximation. The function called by timeout() must adhere to the same restrictions as a driver soft interrupt handler. The function called by timeout() is run in interrupt context and must not sleep or call other functions which may sleep. RETURN VALUES timeout() returns an opaque non-zero timeout identifier that can be passed to untimeout(9F) to cancel the request. CONTEXT timeout() can be called from user or interrupt context. EXAMPLES Example 1: Using timeout() In the following example, the device driver has issued an IO request and is waiting for the device to respond. If the device does not respond within 5 seconds, the device driver will print out an error message to the console. static void xxtimeout_handler(void *arg) SunOS 5.7 Last change: 19 Feb 1998 1 Kernel Functions for Drivers timeout(9F) { struct xxstate *xsp = (struct xxstate *)arg; mutex_enter(>lock); cv_signal(>cv); xsp->flags |= TIMED_OUT; mutex_exit(>lock); xsp->timeout_id = 0; } static uint_t xxintr(caddr_t arg) { struct xxstate *xsp = (struct xxstate *)arg; . . . mutex_enter(>lock); /* Service interrupt */ cv_signal(>cv); mutex_exit(>lock); if (xsp->timeout_id != 0) { (void) untimeout(xsp->timeout_id); xsp->timeout_id = 0; } return(DDI_INTR_CLAIMED); } static void xxcheckcond(struct xxstate *xsp) { . . . xsp->timeout_id = timeout(xxtimeout_handler, xsp, 5 * drv_usectohz(1000000)); mutex_enter(>lock); while (/* Waiting for interrupt or timeout*/) cv_wait(>cv, >lock); if (xsp->flags & TIMED_OUT) cmn_err(CE_WARN, "Device not responding"); . . . mutex_exit(>lock); . SunOS 5.7 Last change: 19 Feb 1998 2 Kernel Functions for Drivers timeout(9F) . . } SEE ALSO bufcall(9F), delay(9F), untimeout(9F) Writing Device Drivers SunOS 5.7 Last change: 19 Feb 1998 3 onl8v1[129]% onl8v1[120]% man getminor : Kernel Functions for Drivers getminor(9F) NAME getminor - get minor device number SYNOPSIS #include #include #include minor_t getminor(dev_t dev); INTERFACE LEVEL Architecture independent level 1 (DDI/DKI). PARAMETERS dev Device number. DESCRIPTION getminor() extracts the minor number from a device number. RETURN VALUES The minor number. CONTEXT getminor() can be called from user or interrupt context. EXAMPLES See the getmajor(9F) manual page for an example of how to use getminor(). SEE ALSO getmajor(9F), makedevice(9F) Writing Device Drivers WARNINGS No validity checking is performed. If dev is invalid, an invalid number is returned. SunOS 5.7 Last change: 11 Apr 1991 1 onl8v1[121]% onl8v1[121]% vi /usr/include/sys/systm.h : 100 timeout_id_t timeout(void (*)(void *), void *, clock_t); 101 timeout_id_t realtime_timeout(void (*)(void *), void *, clock_t); 102 clock_t untimeout(timeout_id_t); : onl8v1[122]% 参考のために Solaris2.6 での timeout(9F) を man でチェックする。 onlsun3[45]% rlogin onlsun1 Last login: Fri Oct 29 10:42:47 from onlsun4 Sun Microsystems Inc. SunOS 5.6 Generic August 1997 onlsun1[33]% man -s 9f timeout Kernel Functions for Drivers timeout(9F) NAME timeout - execute a function after a specified length of time SYNOPSIS #include #include int timeout(void (*func )(), caddr_t arg, clock_t ticks); INTERFACE LEVEL Architecture independent level 1 (DDI/DKI). ARGUMENTS func Kernel function to invoke when the time increment expires. arg Argument to the function. ticks Number of clock ticks to wait before the function is called. DESCRIPTION The timeout() function schedules the specified function to be called after a specified time interval. The exact time interval over which the timeout takes effect cannot be guaranteed, but the value given is a close approximation. The function called by timeout() must adhere to the same restrictions as a driver soft interrupt handler. The timeout() function returns an identifier that may be passed to the untimeout(9F) function to cancel a pending request.%) timeout() can be called from user or interrupt context. The function called by timeout() is run in interrupt context and must not sleep or call other functions which may sleep. RETURN VALUES%) Under normal conditions, timeout() returns an integer timeout identifier not equal to zero. If, however, the timeout table is full, the system will panic with the fol- lowing panic message: PANIC: Timeout table overflow CONTEXT timeout() can be called from user or interrupt context. SunOS 5.6 Last change: 19 Sep 1996 1 Kernel Functions for Drivers timeout(9F) EXAMPLES In the following example, the device driver has issued an IO request and is waiting for the device to respond. If the device does not respond within 5 seconds, the device driver will print out an error message to the console. static void xxtimeout_handler(caddr_t arg) { struct xxstate *xsp = (struct xxstate *)arg; mutex_enter(&xsp->lock); cv_signal(&xsp->cv); xsp->flags |= TIMED_OUT; mutex_exit(&xsp->lock); xsp->timeout_id = 0; } static u_int xxintr(caddr_t arg) { struct xxstate *xsp = (struct xxstate *)arg; . . . mutex_enter(&xsp->lock); /* Service interrupt */ cv_signal(&xsp->cv); mutex_exit(&xsp->lock); if (xsp->timeout_id != 0) { (void) untimeout(xsp->timeout_id); xsp->timeout_id = 0; }) return(DDI_INTR_CLAIMED); } static void xxcheckcond(struct xxstate *xsp) { . . . xsp->timeout_id = timeout(xxtimeout_handler, (caddr_t)xsp, 5 * drv_usectohz(1000000)); mutex_enter(&xsp->lock); while (/* Waiting for interrupt or timeout*/) SunOS 5.6 Last change: 19 Sep 1996 2 Kernel Functions for Drivers timeout(9F) cv_wait(&xsp->cv, &xsp->lock); if (xsp->flags & TIMED_OUT) cmn_err(CE_WARN, "Device not responding"); . . . mutex_exit(&xsp->lock); . . . } SEE ALSO bufcall(9F), delay(9F), untimeout(9F) Writing Device Drivers SunOS 5.6 Last change: 19 Sep 1996 3 onlsun1[34]% 参考のために Solaris2.6 での getminor(9F) を man でチェックする。 onlsun1[35]% man getminor Kernel Functions for Drivers getminor(9F) NAME getminor - get minor device number SYNOPSIS #include #include #include minor_t getminor(dev_t dev); INTERFACE LEVEL Architecture independent level 1 (DDI/DKI). ARGUMENTS dev Device number. DESCRIPTION getminor() extracts the minor number from a device number. RETURN VALUES The minor number. CONTEXT getminor() can be called from user or interrupt context. EXAMPLE See the getmajor(9F) manual page for an example of how to use getminor. SEE ALSO getmajor(9F), makedevice(9F) Writing Device Drivers WARNINGS No validity checking is performed. If dev is invalid, an invalid number is returned. SunOS 5.6 Last change: 11 Apr 1991 1 onlsun1[36]% (4-4-1). cc.cファイルの問題点 (A). man によると timeout()のタイプおよびtimeout()で使用する引数の タイプが Solaris2.6 と Solaris7 とでは異なっている。 Solris7 timeout_id_t timeout(void (* func)(void *), void *arg, clock_t ticks); Solris2.6 int timeout(void (*func )(), caddr_t arg, clock_t ticks); 処置. (1). cc->timeout_id のタイプを "int" から "timeout_id_t" へ変更。 (2). cc_timeout エントリーポイント宣言文の引数のタイプ "caddr_t" を削除。 (3). cc_timeout() ルーチンの引数のタイプ "caddr_t"を削除。 (4). timeout()カーネル関数呼び出し時に2番目の引数のタイプを "caddr_t" としていたのを削除。 以上の変更をしてコンパイルし直してみる。 onl8v1[42]% vi cc.c : 102 /* E.Inoue 103 int timeout_id; 104 end */ 105 timeout_id_t timeout_id; : 149 /* E.Inoue 150 static void cc_timeout(caddr_t unit); 151 end */ 152 static void cc_timeout(void *unit); : 876 static void 877 cc_timeout( void *unit) 878 /* E.Inoue 879 cc_timeout(caddr_t unit) 880 end */ 881 { 882 /* register struct cc_device *cc = &ccdevice[0]; */ 883 register struct cc_device *cc; : 970 static int 971 cc_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p) 972 /* E.Inoue 973 cc_ioctl(dev_t dev, int cmd, int arg, int flag, cred_t *cred_p, int *rva l_p) 974 end */ 975 { : 1038 /* E.Inoue 1039 cc->timeout_id = timeout(cc_timeout, (caddr_t)&unit, cc->data1 * hz); 1040 end */ 1041 cc->timeout_id = timeout(cc_timeout, unit, cc->data1 * hz); : 2695 static int cc_strategy(struct buf *bp) 2696 { 2697 /* register struct cc_device *cc = &ccdevice[0]; */ 2698 register struct cc_device *cc; : 2831 /* E.Inoue 2832 cc->timeout_id = timeout(cc_timeout, (caddr_t)&unit, CC_TIMEOUT_DMA * hz); 2833 end */ 2834 cc->timeout_id = timeout(cc_timeout, unit, CC_TIMEOUT_DMA * hz); : "cc.c" 2956 lines, 75695 characters onl8v1[43]% コンパイル再実行。 onl8v1[43]% pwd /export/home/onl8v1/inoue/CAMAC/Driver/FORCE-50T-sol2.6 onl8v1[44]% make clean \rm -f cc *.o libcamac.a cam1 cam2 cam3 *~ core onl8v1[45]% make ./script/cc_build.sh [Building for sun4m] "cc.c", line 886: warning: improper pointer/integer combination: arg #2 "cc.c", line 1041: warning: improper pointer/integer combination: arg #2 "cc.c", line 2834: warning: improper pointer/integer combination: arg #2 rm -f cc.o cc -O -c camlib.c -o camlib.o -I. cc -O -c forlib.c -o forlib.o -I. rm -f libcamac.a ar rcv libcamac.a camlib.o forlib.o a - camlib.o a - forlib.o ar: writing libcamac.a cc -O cam1.c -o cam1 -I. -L. -lcamac f77 -fast -O3 -u cam2.f -o cam2 -I. -L. -lcamac cam2.f: MAIN: cc -O cam3.c -o cam3 -I. -L. -lcamac onl8v1[46]% cc.c 一部、再変更をしてコンパイルし直す。 onl8v1[46]% vi cc.c : 876 static void 877 cc_timeout( void *unit) 878 /* E.Inoue 879 cc_timeout(caddr_t unit) 880 end */ 881 { 882 /* register struct cc_device *cc = &ccdevice[0]; */ 883 register struct cc_device *cc; 884 885 /* cc = ddi_get_soft_state(cc_state,unit); */ 886 /* cc = ddi_get_soft_state(cc_state,(int)*unit); */ 887 cc = ddi_get_soft_state(cc_state, (int)unit); : 1039 cc->timeout_id = timeout(cc_timeout, (caddr_t)&unit, cc->data1 * hz); 1040 end */ 1041 cc->timeout_id = timeout(cc_timeout, (void *)unit, cc->data1 * hz ); : 2832 cc->timeout_id = timeout(cc_timeout, (caddr_t)&unit, CC_TIMEOUT_DMA * hz); 2833 end */ 2834 cc->timeout_id = timeout(cc_timeout, (void *)unit, CC_TIMEOUT_DMA * hz); : "cc.c" 2956 lines, 75716 characters onl8v1[47]% コンパイル再実行。 onl8v1[49]% pwd /export/home/onl8v1/inoue/CAMAC/Driver/FORCE-50T-sol2.6 onl8v1[50]% make clean \rm -f cc *.o libcamac.a cam1 cam2 cam3 *~ core onl8v1[51]% make ./script/cc_build.sh [Building for sun4m] rm -f cc.o cc -O -c camlib.c -o camlib.o -I. cc -O -c forlib.c -o forlib.o -I. rm -f libcamac.a ar rcv libcamac.a camlib.o forlib.o a - camlib.o a - forlib.o ar: writing libcamac.a cc -O cam1.c -o cam1 -I. -L. -lcamac f77 -fast -O3 -u cam2.f -o cam2 -I. -L. -lcamac cam2.f: MAIN: cc -O cam3.c -o cam3 -I. -L. -lcamac onl8v1[52]% ok. コンパイル時の warning は出なくなった。 続いて、ccドライバをロードして camac の実行テストを行う。 ---xxxx ( ここまでやった 継続中) --- (6). セクション (6-1). サブセクション (6-1-1). サブサブセクション