Make manual page rendering easier.
[jimtcl/wkoszek.git] / jim-hwio.c
blob72b3d01b06f5922cb87cbd54162cadce895c9147
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>
24 #include <unistd.h>
25 #include <string.h>
26 #include <errno.h>
28 #include <sys/io.h>
29 #include <sys/mman.h>
30 #include <sched.h>
32 #define JIM_EXTENSION
33 #include "jim.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,
42 Jim_Obj *const *argv)
44 long longValue;
46 if (argc != 2) {
47 Jim_WrongNumArgs(interp, 1, argv, "?template?");
48 return JIM_ERR;
50 if (Jim_GetLong(interp, argv[1], &longValue) != JIM_OK)
51 return JIM_ERR;
52 // body
53 return JIM_OK;
55 #define AREAINFOLEN 10
56 typedef struct areainfo {
57 int len;
58 int base;
59 int flag;
60 char name[20];
61 } AREAINFO;
63 AREAINFO areainfo[AREAINFOLEN];
64 #define NEW 0
65 #define FOUND 1
66 #define NOTFOUND -1
67 int placearea(const char *name,int lbase, int len, int flag)
69 int i;
70 int state = NOTFOUND;
71 int firstempty = NOTFOUND;
72 int numbase = 0;
73 if (lbase==0) {
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;
85 if (numbase
86 && (numbase >= areainfo[i].base)
87 && (numbase < ( areainfo[i].base + areainfo[i].len))
89 return(numbase);
90 if (lbase && firstempty<0 && areainfo[i].flag == 0) {
91 firstempty = i;
92 //fprintf(stderr,"firstempty: %d\n",firstempty);
95 if ((state==NOTFOUND)&&(firstempty>=0)) {
96 i = firstempty;
97 state = NEW;
99 switch (state) {
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);
106 break;
107 default:
108 //fprintf(stderr,"notfound : entry %s \n",name);
109 return lbase;
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)
123 const char *op ;
124 int strlen;
125 const char *name = NULL;
126 long offset = -1;
127 long len = -1;
128 long res;
130 switch (argc) {
131 case 5: if (Jim_GetLong(interp, argv[4], &len) != JIM_OK) {
132 Jim_WrongNumArgs(interp, 1, argv, "invalid len");
133 return JIM_ERR;
135 case 4: if (Jim_GetLong(interp, argv[3], &offset) != JIM_OK) {
136 Jim_WrongNumArgs(interp, 1, argv, "invalid offset");
137 return JIM_ERR;
139 case 3: if (name = Jim_GetString(argv[2], &strlen),strlen == 0) {
140 return JIM_ERR;
142 case 2: if (op = Jim_GetString(argv[1], &strlen),strlen == 0) {
143 return JIM_ERR;
145 break;
146 case 1: op = "list";
147 break;
148 default:
149 Jim_WrongNumArgs(interp, 1, argv, "invalid offset");
150 return JIM_ERR;
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 ) {
162 res = 0;
163 Jim_SetResult(interp, Jim_NewIntObj(interp, res));
164 } else {
165 Jim_WrongNumArgs(interp, 1, argv, "unknown op");
166 return JIM_ERR;
168 return JIM_OK;
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)
177 Jim_Obj *ret = NULL;
179 switch (argc) {
180 case 3: if (Jim_GetLong(interp, argv[2], &bcast) != JIM_OK) {
181 Jim_WrongNumArgs(interp, 1, argv, "invalid bcast");
182 return JIM_ERR;
184 case 2: if (Jim_GetLong(interp, argv[1], &base) != JIM_OK) {
185 Jim_WrongNumArgs(interp, 1, argv, "invalid base");
186 return JIM_ERR;
188 case 1:
189 break;
190 default:
191 Jim_WrongNumArgs(interp, 1, argv, "invalid offset");
192 return JIM_ERR;
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);
199 return JIM_OK;
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)
211 long tmpval;
212 const char *strarg;
213 int strlen = 0;
215 if (Jim_GetLong(interp, arg, &tmpval) == JIM_OK) {
216 *pval = tmpval;
217 //fprintf(stderr,"int conversion OK\n");
218 return JIM_OK;
219 } else if (lastval == 0) {
220 //fprintf(stderr,"tmpval: %ld lastval %p \n",tmpval, lastval);
221 return JIM_ERR;
222 } else if (strarg = Jim_GetString(arg, &strlen),strlen>0) {
223 // fprintf(stderr,"lastval: %ld %p %s\n",tmpval, strarg,strarg);
224 do {
225 switch (*strarg) {
226 case '-': *pval = *lastval - size; break;
227 case '.': *pval = *lastval; break;
228 case '+': *pval = *lastval + size; break;
229 default:
230 //fprintf(stderr,"extra opt :%d %c %s\n",strlen,*strarg,strarg);
231 return JIM_ERR;
233 } while (strarg++,*strarg);
234 //fprintf(stderr,"pval: %d \n",*pval);
235 } else {
236 //fprintf(stderr,"else \n");
237 return JIM_ERR;
239 return JIM_OK;
242 #define MASK(width) ((1<<width)-1)
243 #define DATAOFFS 0
244 #define DATABITS 27
245 #define ADDROFFS DATABITS
246 #define ADDRBITS 5
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)
251 #define ADDRREG 0x1f
253 static int Jim_HwIoRregCommand(Jim_Interp *interp, int argc,
254 Jim_Obj *const *argv)
256 int idx ;
257 int lbase = base;
258 int addrval;
259 int *plast = NULL;
260 int outvalue;
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) {
267 const char *board;
268 int strlen;
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);
273 continue;
275 Jim_WrongNumArgs(interp, 1, argv, "Format!");
276 return JIM_ERR;
278 outvalue = COMPOSE(ADDRREG,addrval);
279 // fprintf(stderr,"rreg lbase: %x addrval: %x outvalue: %08x\n",lbase,addrval,outvalue);
280 inb(0x80);
281 outl(outvalue,lbase);
282 #ifdef USE_USLEEP
283 usleep(1000);
284 #else
285 inb(0x80);
286 inb(0x80);
287 inb(0x80);
288 inb(0x80);
289 inb(0x80);
290 #endif
291 Jim_ListAppendElement(interp,ret,Jim_NewIntObj(interp, STRIP(inl(lbase))));
292 inb(0x80);
293 plast = &addrval;
295 Jim_SetResult(interp, ret);
296 return JIM_OK;
299 #define RETisUINT 0
300 #define RETisINT 1
301 #define MAXBOARD 4
302 static int Jim_HwIoRregBlkCommand(Jim_Interp *interp, int argc,
303 Jim_Obj *const *argv)
305 long len = -1 ;
306 int bcnt = 0;
307 int lbase[MAXBOARD] = {base, 0, 0, 0 };
308 long addr;
309 long outvalue;
310 const char *board;
311 int strlen;
312 int rettype=RETisUINT;
313 int llength;
314 int i,j,k;
315 int swaplist[] = {0, 3, 2, 1};
316 char swaplen = (sizeof(swaplist)/sizeof(int));
317 long swapbuf[2*swaplen];
319 Jim_Obj *ret = NULL;
321 if ( argc < 3) {
322 Jim_WrongNumArgs(interp, 1, argv, "wrong num args!");
323 return JIM_ERR;
325 // check if the board spec is a list
326 if ((argc>=4) && (Jim_ListLength(interp,argv[1],&llength),llength > 1)) {
327 Jim_Obj* bobj;
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);
337 argv++; argc--;
339 while ((argc > 3) && (board = Jim_GetString(argv[1], &strlen))) {
340 if (strcmp("int",board)==0) {
341 rettype = RETisINT;
342 argv++; argc--;
343 continue;
345 if (strcmp("noswap",board)==0) {
346 swaplist[0] = 0;
347 swaplist[1] = 1;
348 swaplist[2] = 2;
349 swaplist[3] = 3;
350 argv++; argc--;
351 continue;
353 if (sscanf(board,"swap:%i,%i,%i,%i",
354 &swaplist[0],&swaplist[1],&swaplist[2],&swaplist[3]
355 )==4) {
356 argv++; argc--;
357 continue;
359 // fprintf(stderr,"marg Board: %s base %x \n",board,getbasefromID(board));
360 //fprintf(stderr,"cont for ID\n");
361 lbase[bcnt++] = getbasefromID(board);
362 argv++; argc--;
364 if (bcnt > MAXBOARD) {
365 Jim_WrongNumArgs(interp, 1, argv, "too many boards specified!");
366 return JIM_ERR;
368 if (!bcnt) bcnt = 1; // default base
369 // get start
370 if (Jim_GetLong(interp, argv[1], &addr) != JIM_OK) {
371 return JIM_ERR;
373 outvalue = COMPOSE(ADDRREG,addr);
375 // get len
376 if (Jim_GetLong(interp, argv[2], &len) != JIM_OK) {
377 return JIM_ERR;
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);
382 inb(0x80);
383 outl(outvalue,lbase[i]);
385 #ifdef USE_USLEEP
386 usleep(1000);
387 #else
388 inb(0x80);
389 inb(0x80);
390 inb(0x80);
391 inb(0x80);
392 inb(0x80);
393 #endif
394 ret = Jim_NewListObj(interp, 0, 0);
395 switch (rettype) {
396 case RETisUINT:
397 j = 0;
398 while (len--) {
399 for (i=0;(i<bcnt);i++,j++) {
400 inb(0x80);
401 swapbuf[j] = inl(lbase[i]);
403 if (j>=swaplen) {
404 j -= swaplen;
405 for (k=0;(k<swaplen);k++) {
406 Jim_ListAppendElement(interp,ret,Jim_NewIntObj(interp, swapbuf[j+swaplist[k]]));
410 inb(0x80);
411 break;
412 case RETisINT:
413 j = 0;
414 while (len--) {
415 for (i=0;(i<bcnt);i++,j++) {
416 inb(0x80);
417 swapbuf[j] = inl(lbase[i]);
419 if (j>=swaplen) {
420 j -= swaplen;
421 for (k=0;(k<swaplen);k++) {
422 Jim_ListAppendElement(interp,ret,Jim_NewIntObj(interp, (int)swapbuf[j+swaplist[k]]));
426 inb(0x80);
428 Jim_SetResult(interp, ret);
429 return JIM_OK;
432 static int Jim_HwIoWregCommand(Jim_Interp *interp, int argc,
433 Jim_Obj *const *argv)
435 int idx ;
436 int lbase = base;
437 int addr;
438 int *plast = NULL;
439 long val;
440 long outvalue;
441 int cnt = 0;
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) {
447 const char *board;
448 int strlen;
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);
453 continue;
455 Jim_WrongNumArgs(interp, 1, argv, "Format!");
456 return JIM_ERR;
458 plast = &addr;
459 idx++;
460 if (idx == argc)
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);
465 inb(0x80);
466 outl(outvalue,lbase);
467 inb(0x80);
468 // fprintf(stderr,"outb:%ld @ %d\n",outval,addrval);
469 cnt++;
470 } else
471 return JIM_ERR;
472 //fprintf(stderr,"argc %d idx %d\n",argc,idx);
474 Jim_SetResult(interp, Jim_NewIntObj(interp, cnt));
475 return JIM_OK;
479 #undef INOUT_SIZE
480 #undef INOUT_IN_OP
481 #undef INOUT_OUT_OP
482 #undef INOUT_IN_CMDNAME
483 #undef INOUT_OUT_CMDNAME
484 //end
486 #define INOUT_SIZE 1
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"
493 #define INOUT_SIZE 2
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"
500 #define INOUT_SIZE 4
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} ;
515 int option;
516 jim_wide start;
517 jim_wide len;
519 switch (argc) {
520 case 3: // Address Range
521 if (Jim_GetWide(interp, argv[1], &start) != JIM_OK) {
522 Jim_WrongNumArgs(interp, 1, argv, "invalid Start");
523 return JIM_ERR;
525 if (Jim_GetWide(interp, argv[2], &len) != JIM_OK) {
526 Jim_WrongNumArgs(interp, 1, argv, "invalid Len");
527 return JIM_ERR;
529 if (mlock((void*)(long)start,len))
530 goto tell_posix_error;
531 return JIM_OK;
532 case 2:
533 if (Jim_GetEnum(interp, argv[1], options, &option,
534 "mlock type", JIM_ERRMSG) != JIM_OK)
535 return JIM_ERR;
536 switch (option) {
537 case RELEASE:
538 if (munlockall())
539 goto tell_posix_error;
540 return JIM_OK;
541 case CURRENT:
542 if (mlockall(MCL_CURRENT))
543 goto tell_posix_error;
544 return JIM_OK;
545 case FUTURE:
546 if (mlockall(MCL_FUTURE))
547 goto tell_posix_error;
548 return JIM_OK;
550 break;
551 case 1:
552 return JIM_OK;
553 default:
554 Jim_WrongNumArgs(interp, 1, argv, "?template?");
555 return JIM_ERR;
557 tell_posix_error:
558 Jim_PosixSetError(interp);
559 return JIM_ERR;
562 #define SELF 0
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 };
572 int policy = -1;
573 int mypolicy;
574 int min, max;
575 jim_wide new;
576 int newprio = 0;
578 switch (argc) {
579 case 3: if (Jim_GetWide(interp, argv[2], &new) != JIM_OK) {
580 Jim_WrongNumArgs(interp, 1, argv, "invalid Priority");
581 return JIM_ERR;
583 newprio = 1;
584 case 2: if (Jim_GetEnum(interp, argv[1], policies, &policy,
585 "Sched Priority Policy", JIM_ERRMSG) != JIM_OK)
586 return JIM_ERR;
587 switch (policy) {
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;
600 return JIM_OK;
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;
607 return JIM_OK;
609 return JIM_ERR;
610 case 1: {
611 char buff[0x20];
612 mypolicy = sched_getscheduler(SELF);
613 switch (mypolicy) {
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);
622 return JIM_OK;
624 default:
625 Jim_WrongNumArgs(interp, 1, argv, "?template?");
626 return JIM_ERR;
630 sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO) - 10;
631 sched_setscheduler(0, SCHED_FIFO, &sched_param);
633 return JIM_OK;
634 tell_posix_error:
635 //fprintf(stderr,"telling posix error:");
636 Jim_PosixSetError(interp);
637 return JIM_ERR;
640 int Jim_OnLoad(Jim_Interp *interp)
642 Jim_InitExtension(interp);
643 if (Jim_PackageProvide(interp, "hwio", "0.5", JIM_ERRMSG) != JIM_OK)
644 return JIM_ERR;
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
667 ioperm( 0x80, 1, 1);
668 return JIM_OK;