1 /* Jim - POSIX extension
2 * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
3 * Copyright 2007 Uwe Klein Habertwedt <antirez@invece.org>
5 * $Id: jim-hwio.c,v 1.16 2008/03/10 21:49:29 macc Exp $
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * A copy of the license is also included in the source distribution
14 * of Jim, as a TXT file name called LICENSE.
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
23 #include <sys/types.h>
35 static void Jim_PosixSetError(Jim_Interp
*interp
)
37 Jim_SetResultString(interp
, strerror(errno
), -1);
41 static int Jim_HwIoTemplateCommand(Jim_Interp
*interp
, int argc
,
47 Jim_WrongNumArgs(interp
, 1, argv
, "?template?");
50 if (Jim_GetLong(interp
, argv
[1], &longValue
) != JIM_OK
)
55 #define AREAINFOLEN 10
56 typedef struct areainfo
{
63 AREAINFO areainfo
[AREAINFOLEN
];
67 int placearea(const char *name
,int lbase
, int len
, int flag
)
71 int firstempty
= NOTFOUND
;
74 sscanf(name
,"%i",&numbase
);
75 // fprintf(stderr,"lb0 %s : %x \n",name,numbase);
77 for (i
=0;(i
<AREAINFOLEN
);i
++) {
78 if (lbase
&& (areainfo
[i
].base
== lbase
)) {
79 state
= FOUND
; break;
81 if ((lbase
==0) && areainfo
[i
].len
&& (strcmp(areainfo
[i
].name
, name
)==0)) {
82 //fprintf(stderr,"found an entry %s @ %x \n",areainfo[i].name,areainfo[i].base);
83 return areainfo
[i
].base
;
86 && (numbase
>= areainfo
[i
].base
)
87 && (numbase
< ( areainfo
[i
].base
+ areainfo
[i
].len
))
90 if (lbase
&& firstempty
<0 && areainfo
[i
].flag
== 0) {
92 //fprintf(stderr,"firstempty: %d\n",firstempty);
95 if ((state
==NOTFOUND
)&&(firstempty
>=0)) {
100 case NEW
: strcpy(areainfo
[i
].name
,name
);
101 //fprintf(stderr,"created an entry %s \n",areainfo[i].name);
102 case FOUND
: areainfo
[i
].len
= len
;
103 areainfo
[i
].base
= lbase
;
104 areainfo
[i
].flag
= flag
;
105 //fprintf(stderr,"refreshed an entry %s @ %x \n",areainfo[i].name,areainfo[i].base);
108 //fprintf(stderr,"notfound : entry %s \n",name);
111 return areainfo
[i
].base
;
114 int getbasefromID(const char *name
)
116 return placearea(name
,0,0,0);
120 static int Jim_HwIoAreaCommand(Jim_Interp
*interp
, int argc
,
121 Jim_Obj
*const *argv
)
125 const char *name
= NULL
;
131 case 5: if (Jim_GetLong(interp
, argv
[4], &len
) != JIM_OK
) {
132 Jim_WrongNumArgs(interp
, 1, argv
, "invalid len");
135 case 4: if (Jim_GetLong(interp
, argv
[3], &offset
) != JIM_OK
) {
136 Jim_WrongNumArgs(interp
, 1, argv
, "invalid offset");
139 case 3: if (name
= Jim_GetString(argv
[2], &strlen
),strlen
== 0) {
142 case 2: if (op
= Jim_GetString(argv
[1], &strlen
),strlen
== 0) {
149 Jim_WrongNumArgs(interp
, 1, argv
, "invalid offset");
152 if (strcmp(op
,"create") == 0 ) {
153 if ( ioperm( offset
, len
, 1) == 0 ) {
154 placearea(name
,offset
, len
,1 );
155 Jim_SetResult(interp
,argv
[2]);
157 } else if (strcmp(op
,"delete") == 0 ) {
158 res
= ioperm( offset
, len
, 0);
159 placearea(name
,offset
, len
, 0 );
160 Jim_SetResult(interp
, Jim_NewIntObj(interp
, res
));
161 } else if (strcmp(op
,"list") == 0 ) {
163 Jim_SetResult(interp
, Jim_NewIntObj(interp
, res
));
165 Jim_WrongNumArgs(interp
, 1, argv
, "unknown op");
171 static long base
= 0x300;
172 static long bcast
= 0x30a;
174 static int Jim_HwIoBaseCommand(Jim_Interp
*interp
, int argc
,
175 Jim_Obj
*const *argv
)
180 case 3: if (Jim_GetLong(interp
, argv
[2], &bcast
) != JIM_OK
) {
181 Jim_WrongNumArgs(interp
, 1, argv
, "invalid bcast");
184 case 2: if (Jim_GetLong(interp
, argv
[1], &base
) != JIM_OK
) {
185 Jim_WrongNumArgs(interp
, 1, argv
, "invalid base");
191 Jim_WrongNumArgs(interp
, 1, argv
, "invalid offset");
194 ret
= Jim_NewListObj(interp
, 0, 0);
195 Jim_ListAppendElement(interp
,ret
,Jim_NewIntObj(interp
, base
));
196 Jim_ListAppendElement(interp
,ret
,Jim_NewIntObj(interp
, bcast
));
197 Jim_SetResult(interp
, ret
);
202 // getIntsfromList retrieves a number of ints from a list (argv)
203 // first item must be a number consecutive elements can be numbers
204 // or '.' for repeat last number
205 // or '+' for increment last number by size
206 // or '-' for decrement last number by size
208 static int HwIo_getIntsfromList(Jim_Interp
*interp
,
209 Jim_Obj
*arg
, int size
, int *lastval
, int *pval
)
215 if (Jim_GetLong(interp
, arg
, &tmpval
) == JIM_OK
) {
217 //fprintf(stderr,"int conversion OK\n");
219 } else if (lastval
== 0) {
220 //fprintf(stderr,"tmpval: %ld lastval %p \n",tmpval, lastval);
222 } else if (strarg
= Jim_GetString(arg
, &strlen
),strlen
>0) {
223 // fprintf(stderr,"lastval: %ld %p %s\n",tmpval, strarg,strarg);
226 case '-': *pval
= *lastval
- size
; break;
227 case '.': *pval
= *lastval
; break;
228 case '+': *pval
= *lastval
+ size
; break;
230 //fprintf(stderr,"extra opt :%d %c %s\n",strlen,*strarg,strarg);
233 } while (strarg
++,*strarg
);
234 //fprintf(stderr,"pval: %d \n",*pval);
236 //fprintf(stderr,"else \n");
242 #define MASK(width) ((1<<width)-1)
245 #define ADDROFFS DATABITS
247 #define DATAMASK MASK(DATABITS)
248 #define ADDRMASK MASK(ADDRBITS)
249 #define COMPOSE(addr,value) (((addr&ADDRMASK)<<ADDROFFS)|((value&DATAMASK)<<DATAOFFS))
250 #define STRIP(value) (value&DATAMASK)
253 static int Jim_HwIoRregCommand(Jim_Interp
*interp
, int argc
,
254 Jim_Obj
*const *argv
)
262 Jim_Obj
*ret
= Jim_NewListObj(interp
, 0, 0);
265 for (idx
=1;(idx
< argc
);idx
++) {
266 if (HwIo_getIntsfromList(interp
, argv
[idx
],1,plast
,&addrval
) != JIM_OK
) {
269 // fprintf(stderr,"going for ID\n");
270 if ((idx
== 1) && (board
= Jim_GetString(argv
[idx
], &strlen
))) {
271 //fprintf(stderr,"cont for ID\n");
272 lbase
= getbasefromID(board
);
275 Jim_WrongNumArgs(interp
, 1, argv
, "Format!");
278 outvalue
= COMPOSE(ADDRREG
,addrval
);
279 // fprintf(stderr,"rreg lbase: %x addrval: %x outvalue: %08x\n",lbase,addrval,outvalue);
281 outl(outvalue
,lbase
);
291 Jim_ListAppendElement(interp
,ret
,Jim_NewIntObj(interp
, STRIP(inl(lbase
))));
295 Jim_SetResult(interp
, ret
);
302 static int Jim_HwIoRregBlkCommand(Jim_Interp
*interp
, int argc
,
303 Jim_Obj
*const *argv
)
307 int lbase
[MAXBOARD
] = {base
, 0, 0, 0 };
312 int rettype
=RETisUINT
;
315 int swaplist
[] = {0, 3, 2, 1};
316 char swaplen
= (sizeof(swaplist
)/sizeof(int));
317 long swapbuf
[2*swaplen
];
322 Jim_WrongNumArgs(interp
, 1, argv
, "wrong num args!");
325 // check if the board spec is a list
326 if ((argc
>=4) && (Jim_ListLength(interp
,argv
[1],&llength
),llength
> 1)) {
329 // fprintf(stderr,"larg length:%d \n",llength);
330 for (i
=0;(i
<llength
);i
++) {
331 Jim_ListIndex(interp
,argv
[1],i
,&bobj
,JIM_NONE
);
332 if ((board
= Jim_GetString(bobj
, &strlen
))) {
333 // fprintf(stderr,"larg Board: %s base %x \n",board,getbasefromID(board));
334 lbase
[bcnt
++] = getbasefromID(board
);
339 while ((argc
> 3) && (board
= Jim_GetString(argv
[1], &strlen
))) {
340 if (strcmp("int",board
)==0) {
345 if (strcmp("noswap",board
)==0) {
353 if (sscanf(board
,"swap:%i,%i,%i,%i",
354 &swaplist
[0],&swaplist
[1],&swaplist
[2],&swaplist
[3]
359 // fprintf(stderr,"marg Board: %s base %x \n",board,getbasefromID(board));
360 //fprintf(stderr,"cont for ID\n");
361 lbase
[bcnt
++] = getbasefromID(board
);
364 if (bcnt
> MAXBOARD
) {
365 Jim_WrongNumArgs(interp
, 1, argv
, "too many boards specified!");
368 if (!bcnt
) bcnt
= 1; // default base
370 if (Jim_GetLong(interp
, argv
[1], &addr
) != JIM_OK
) {
373 outvalue
= COMPOSE(ADDRREG
,addr
);
376 if (Jim_GetLong(interp
, argv
[2], &len
) != JIM_OK
) {
379 len
/= bcnt
; // fix for bcnt items per len--
380 for (i
=0;(i
<bcnt
);i
++) {
381 // fprintf(stderr,"rregmult:%d lbase: %x addr: %lx outvalue %08lx (len: %lx )\n",bcnt,lbase[i],addr,outvalue,len);
383 outl(outvalue
,lbase
[i
]);
394 ret
= Jim_NewListObj(interp
, 0, 0);
399 for (i
=0;(i
<bcnt
);i
++,j
++) {
401 swapbuf
[j
] = inl(lbase
[i
]);
405 for (k
=0;(k
<swaplen
);k
++) {
406 Jim_ListAppendElement(interp
,ret
,Jim_NewIntObj(interp
, swapbuf
[j
+swaplist
[k
]]));
415 for (i
=0;(i
<bcnt
);i
++,j
++) {
417 swapbuf
[j
] = inl(lbase
[i
]);
421 for (k
=0;(k
<swaplen
);k
++) {
422 Jim_ListAppendElement(interp
,ret
,Jim_NewIntObj(interp
, (int)swapbuf
[j
+swaplist
[k
]]));
428 Jim_SetResult(interp
, ret
);
432 static int Jim_HwIoWregCommand(Jim_Interp
*interp
, int argc
,
433 Jim_Obj
*const *argv
)
444 for (idx
=1;(idx
< argc
);idx
++) {
445 // fprintf(stderr,"argc %d idx %d\n",argc,idx);
446 if (HwIo_getIntsfromList(interp
, argv
[idx
],1,plast
,&addr
) != JIM_OK
) {
449 //fprintf(stderr,"going for ID\n");
450 if ((idx
== 1) && (board
= Jim_GetString(argv
[idx
], &strlen
))) {
451 //fprintf(stderr,"cont for ID\n");
452 lbase
= getbasefromID(board
);
455 Jim_WrongNumArgs(interp
, 1, argv
, "Format!");
461 fprintf(stderr
,"uneven number args @ %d\n",idx
);
462 if (Jim_GetLong(interp
, argv
[idx
], &val
) == JIM_OK
) {
463 outvalue
= COMPOSE(addr
,val
);
464 // fprintf(stderr,"wreg: lbase: %x addr: %x outvalue %08lx\n",lbase,addr,outvalue);
466 outl(outvalue
,lbase
);
468 // fprintf(stderr,"outb:%ld @ %d\n",outval,addrval);
472 //fprintf(stderr,"argc %d idx %d\n",argc,idx);
474 Jim_SetResult(interp
, Jim_NewIntObj(interp
, cnt
));
482 #undef INOUT_IN_CMDNAME
483 #undef INOUT_OUT_CMDNAME
487 #define INOUT_IN_OP inb
488 #define INOUT_OUT_OP outb
489 #define INOUT_IN_CMDNAME Jim_HwIoInbCommand
490 #define INOUT_OUT_CMDNAME Jim_HwIoOutbCommand
491 #include "jim-hwio.inoutblock.h"
494 #define INOUT_IN_OP inw
495 #define INOUT_OUT_OP outw
496 #define INOUT_IN_CMDNAME Jim_HwIoInwCommand
497 #define INOUT_OUT_CMDNAME Jim_HwIoOutwCommand
498 #include "jim-hwio.inoutblock.h"
501 #define INOUT_IN_OP inl
502 #define INOUT_OUT_OP outl
503 #define INOUT_IN_CMDNAME Jim_HwIoInlCommand
504 #define INOUT_OUT_CMDNAME Jim_HwIoOutlCommand
505 #include "jim-hwio.inoutblock.h"
508 static int Jim_HwIoMLockCommand( Jim_Interp
*interp
, int argc
,
509 Jim_Obj
*const *argv
)
511 const char *options
[] = {
512 "release", "current", "future", NULL
514 enum {RELEASE
, CURRENT
, FUTURE
} ;
520 case 3: // Address Range
521 if (Jim_GetWide(interp
, argv
[1], &start
) != JIM_OK
) {
522 Jim_WrongNumArgs(interp
, 1, argv
, "invalid Start");
525 if (Jim_GetWide(interp
, argv
[2], &len
) != JIM_OK
) {
526 Jim_WrongNumArgs(interp
, 1, argv
, "invalid Len");
529 if (mlock((void*)(long)start
,len
))
530 goto tell_posix_error
;
533 if (Jim_GetEnum(interp
, argv
[1], options
, &option
,
534 "mlock type", JIM_ERRMSG
) != JIM_OK
)
539 goto tell_posix_error
;
542 if (mlockall(MCL_CURRENT
))
543 goto tell_posix_error
;
546 if (mlockall(MCL_FUTURE
))
547 goto tell_posix_error
;
554 Jim_WrongNumArgs(interp
, 1, argv
, "?template?");
558 Jim_PosixSetError(interp
);
563 static int Jim_HwIoSchedPriorityCommand( Jim_Interp
*interp
, int argc
,
564 Jim_Obj
*const *argv
)
566 struct sched_param sched_param
;
568 const char *policies
[] = {
569 "other", "rr", "fifo", NULL
571 enum { OTHER
, RR
, FIFO
};
579 case 3: if (Jim_GetWide(interp
, argv
[2], &new) != JIM_OK
) {
580 Jim_WrongNumArgs(interp
, 1, argv
, "invalid Priority");
584 case 2: if (Jim_GetEnum(interp
, argv
[1], policies
, &policy
,
585 "Sched Priority Policy", JIM_ERRMSG
) != JIM_OK
)
588 case OTHER
: policy
= SCHED_OTHER
; break;
589 case RR
: policy
= SCHED_RR
; break;
590 case FIFO
: policy
= SCHED_FIFO
; break;
592 min
= sched_get_priority_min(policy
);
593 max
= sched_get_priority_max(policy
);
594 //fprintf(stderr,"mypolicy: %d min:%d max:%d new:%d newprio:%d :\n",mypolicy,min,max,(int)new,newprio);
595 if (( policy
>= 0) && newprio
&& (new <0)) {
596 sched_param
.sched_priority
= max
+ new;
597 //fprintf(stderr,"priorel : %d \n",sched_param.sched_priority);
598 if (sched_setscheduler(SELF
, policy
, &sched_param
))
599 goto tell_posix_error
;
602 if (( policy
>= 0) && newprio
&& (new >min
)) {
603 sched_param
.sched_priority
= new;
604 //fprintf(stderr,"prioabs: %d \n",sched_param.sched_priority);
605 if (sched_setscheduler(SELF
, policy
, &sched_param
))
606 goto tell_posix_error
;
612 mypolicy
= sched_getscheduler(SELF
);
614 case SCHED_OTHER
: mypolicy
= OTHER
; break;
615 case SCHED_RR
: mypolicy
= RR
; break;
616 case SCHED_FIFO
: mypolicy
= FIFO
; break;
618 if (sched_getparam(SELF
, &sched_param
))
619 goto tell_posix_error
;
620 sprintf(buff
,"%s %d",policies
[mypolicy
],sched_param
.sched_priority
);
621 Jim_SetResultString(interp
, buff
, -1);
625 Jim_WrongNumArgs(interp
, 1, argv
, "?template?");
630 sched_param
.sched_priority
= sched_get_priority_max(SCHED_FIFO
) - 10;
631 sched_setscheduler(0, SCHED_FIFO
, &sched_param
);
635 //fprintf(stderr,"telling posix error:");
636 Jim_PosixSetError(interp
);
640 int Jim_OnLoad(Jim_Interp
*interp
)
642 Jim_InitExtension(interp
);
643 if (Jim_PackageProvide(interp
, "hwio", "0.5", JIM_ERRMSG
) != JIM_OK
)
645 Jim_CreateCommand(interp
, "hwio.area", Jim_HwIoAreaCommand
, NULL
, NULL
);
647 Jim_CreateCommand(interp
, "hwio.base", Jim_HwIoBaseCommand
, NULL
, NULL
);
649 Jim_CreateCommand(interp
, "hwio.inb" , Jim_HwIoInbCommand
, NULL
, NULL
);
650 Jim_CreateCommand(interp
, "hwio.outb", Jim_HwIoOutbCommand
, NULL
, NULL
);
652 Jim_CreateCommand(interp
, "hwio.inw" , Jim_HwIoInwCommand
, NULL
, NULL
);
653 Jim_CreateCommand(interp
, "hwio.outw", Jim_HwIoOutwCommand
, NULL
, NULL
);
655 Jim_CreateCommand(interp
, "hwio.inl" , Jim_HwIoInlCommand
, NULL
, NULL
);
656 Jim_CreateCommand(interp
, "hwio.outl", Jim_HwIoOutlCommand
, NULL
, NULL
);
658 Jim_CreateCommand(interp
, "hwio.wreg", Jim_HwIoWregCommand
, NULL
, NULL
);
659 Jim_CreateCommand(interp
, "hwio.rreg", Jim_HwIoRregCommand
, NULL
, NULL
);
661 Jim_CreateCommand(interp
, "hwio.rblk", Jim_HwIoRregBlkCommand
, NULL
, NULL
);
663 Jim_CreateCommand(interp
, "hwio.mlock", Jim_HwIoMLockCommand
, NULL
, NULL
);
664 Jim_CreateCommand(interp
, "hwio.priority", Jim_HwIoSchedPriorityCommand
, NULL
, NULL
);
666 // get the delay port