source: lib/dagapi.c @ 59c31da

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 59c31da was 59c31da, checked in by Daniel Lawson <dlawson@…>, 17 years ago

fixes in trace.c for DAG support.
New dagapi / dagopts.c. Still need to find way to build these outside the source

  • Property mode set to 100644
File size: 19.4 KB
Line 
1/*
2 * Copyright (c) 2002 Endace Measurement Systems Ltd, Hamilton, New Zealand.
3 * All rights reserved.
4 *
5 * This source code is proprietary to Endace Measurement Systems and no part
6 * of it may be redistributed, published or disclosed except as outlined in
7 * the written contract supplied with this product.
8 *
9 * $Id$
10 */
11
12# include       <stdio.h>
13# include       <fcntl.h>
14# include       <stdlib.h>
15# include       <unistd.h>
16# include       <errno.h>
17# include       <regex.h>
18# include       <stdarg.h>
19# include       <string.h>
20
21# include       <sys/types.h>
22# include       <sys/wait.h>
23# include       <sys/mman.h>
24# include       <sys/param.h>
25# include       <sys/time.h>
26
27# if 0
28# include       <machine/cpufunc.h>
29# endif
30
31# include       <dagnew.h>
32# include       <dagapi.h>
33# include       <dagtoken.h>
34
35extern void     dagopt_scan_string(const char *);
36extern int      dagoptlex(void);
37extern char     *dagopttext;
38extern int      dagoptlval;
39
40# define        ToHM2           (*(volatile unsigned *)(herd[dagfd].iom+0x08))
41# define        ToHM4           (*(volatile unsigned *)(herd[dagfd].iom+0x10))
42# define        ToAM2           (*(volatile unsigned *)(herd[dagfd].iom+0x48))
43# define        ToAM3           (*(volatile unsigned *)(herd[dagfd].iom+0x4c))
44# define        IOM(OFF)        (*(volatile unsigned *)(herd[dagfd].iom+(OFF)))
45# define        ARMOFFSET(FD)   ({ int _off = ToHM4 - dag_info(FD)->phy_addr; \
46                                        (_off == herd[FD].rx_memsize) ? 0 : _off; })
47
48# define        CUROFFSET(FD)   ({ int _off = pbm->curaddr - dag_info(FD)->phy_addr; \
49                                        (_off == herd[FD].rx_memsize) ? 0 : _off; })
50# define        SEGOFFSET(FD)   ({ int _off = pbm->segaddr - dag_info(FD)->phy_addr; \
51                                        (_off == herd[FD].rx_memsize) ? 0 : _off; })
52# define        PBMOFFSET(FD)   (herd[FD].brokencuraddr ? \
53                                        SEGOFFSET(FD) : CUROFFSET(FD))
54
55/*
56 * Long comment on why this is here and necessary:
57 * There are a number of ambiguities with the wrsafe and curaddr pointers being
58 * the same, in particular, understanding in any given situation whether the
59 * buffer is empty/full from the PBM point of view, or meant to be emptied from
60 * a users point of view. A number of fixes are possible, this one appears to be
61 * the reliable path to address the problem, for the moment.
62 */
63# define        WRSAFE(FD,X)    (((X)<8) ? ((X)+herd[FD].rx_memsize-8) : ((X)-8))
64
65/*
66 * Need to explain the file descriptor associative array.
67 */
68typedef struct sheep {
69        char            dagname[32];    /* be generous */
70        int             dagiom;         /* XXX cannot be 0 */
71        u_char          *buf;           /* large buffer */
72        u_char          *iom;           /* IO memory pointer */
73        daginf_t        daginf;
74        unsigned        brokencuraddr;  /* fix for ECMs and Dag4.1s */
75        unsigned        byteswap;       /* endinness for 3.4/3.51ecm */
76        unsigned        rx_memaddr;     /* cached rx hole base */
77        unsigned        rx_memsize;     /* cached rx hole size */
78} sheep_t;
79
80static sheep_t  *herd;                  /* I was going to call this flock, initially */
81
82static void     panic(char *fmt, ...) __attribute__((noreturn, format (printf, 1, 2)));
83static void     dagpbmcheck(int dagfd);
84
85char *dagpath(char *path, char *temp, int tempsize) {
86       
87        if (!getenv("DAG"))
88                return path;
89        snprintf(temp, tempsize-1, "%s/%s", getenv("DAG"), path);
90        return temp;
91}
92
93int
94dag_open(char *dagname)
95{
96        int     dagfd, i;
97
98        if((dagfd = open(dagname, O_RDWR)) < 0)
99                return dagfd;
100        if(herd == NULL) {
101                int herdsize = sysconf(_SC_OPEN_MAX) * sizeof(sheep_t);
102                herd = malloc(herdsize);
103                if(herd == NULL)
104                        return -1;      /* errno is ENOMEM */
105                memset(herd, 0, herdsize);
106                for( i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++)
107                        herd[i].dagiom = -1;
108        }
109        if(dagfd >= sysconf(_SC_OPEN_MAX))
110                panic("dagapi: internal error in %s line %u\n", __FILE__, __LINE__);
111        /*
112         * Now fill in the herd structure
113         */
114        strcpy(herd[dagfd].dagname, dagname);
115        if(ioctl(dagfd, DAGIOCINFO, &herd[dagfd].daginf) < 0)
116                return -1;              /* errno set appropriately */
117
118        if((herd[dagfd].dagiom = dag_clone(dagfd, DAGMINOR_IOM)) < 0)
119                panic("dag_open dag_clone dagfd for dagiom: %s\n", strerror(errno));
120
121        if((herd[dagfd].iom = mmap(NULL, 16*PAGE_SIZE, PROT_READ | PROT_WRITE,
122                                        MAP_SHARED, herd[dagfd].dagiom, 0)) == MAP_FAILED)
123                return -1;      /* errno set appropriately */
124
125        return dagfd;
126}
127
128int
129dag_close(int dagfd)
130{
131        if (herd[dagfd].buf != NULL) {
132                int             buf_size=0;
133
134                if(dag_info(dagfd)->soft_caps.pbm) {
135                        buf_size = ((dagpbm_t *)(herd[dagfd].iom +
136                                        dag_info(dagfd)->pbm_base))->memsize;
137                } else {
138                        buf_size = dag_info(dagfd)->buf_size;
139                }
140                munmap(herd[dagfd].buf, 2*buf_size);
141                herd[dagfd].buf = NULL;
142        }
143        (void)close(herd[dagfd].dagiom);
144        if (herd[dagfd].iom != NULL) {
145                munmap(herd[dagfd].iom, 16*PAGE_SIZE);
146                herd[dagfd].iom = NULL;
147        }
148        memset(&herd[dagfd], 0, sizeof(herd[dagfd]));
149        herd[dagfd].dagiom = -1;
150        return close(dagfd);
151}
152
153/*
154 * This is tentative, could be made an inline function.
155 * Problem is we don't want to make herd public.
156 */
157daginf_t *
158dag_info(int dagfd)
159{
160        return &herd[dagfd].daginf;
161}
162
163u_char *
164dag_iom(int dagfd)
165{
166        return herd[dagfd].iom;
167}
168
169u_char
170dag_linktype(int dagfd)
171{
172        daggpp_t        *gpp = (daggpp_t *)(herd[dagfd].iom +
173                                        dag_info(dagfd)->gpp_base);
174        unsigned char   type;
175
176        type = (gpp->control >> 16) & 0xff;
177        if (type == 0xff)
178                type = TYPE_ETH;
179
180        return type;
181}
182
183static int      spawn(char *cmd, ...);
184
185#define Int_Enables 0x8c
186#define IW_Enable   0x10000
187#define armcode(X) ( (*(int*)(herd[X].iom + Int_Enables) & IW_Enable) || dag_info(X)->soft_caps.code )
188
189int
190dag_configure(int dagfd, char *params)
191{
192        int     lock, tok, setatm, dagarm, val;
193        char    temp1[80], temp2[80];
194        daggpp_t        *gpp = (daggpp_t *)(herd[dagfd].iom +
195                                        dag_info(dagfd)->gpp_base);
196
197        /*
198         * We better own this before changing configurations
199         * We might aquire the lock again when starting the
200         * card, which is no harm.
201         */
202        lock = 1;
203        if(ioctl(dagfd, DAGIOCLOCK, &lock) < 0)
204                return -1;      /* errno set */
205
206        /*
207         * Parse input options
208         *
209         * Options are parsed before loading arm code since
210         * arm code loading depends on the options provided.
211         * The ncells options may enable armcode loading, and if so sets
212         * ToAM3 afterwards, since it is volatile on mailbox use.
213         *
214         * It is also possible auto-fpga loading may depend on options
215         * parsed here. If so, needs rearranging since reprogramming the
216         * pp fpga will void the gpp configurations set now.
217         */
218        dagopt_scan_string(params);
219
220        setatm=1; /* default to ncells=1 */
221        while((tok = dagoptlex()) != 0)
222                switch(tok) {
223                  case T_ERROR:
224                        fprintf(stderr, "unknown option '%s'\n", dagopttext);
225                        break;
226                  case T_POS:
227                        break;
228                  case T_ATM:
229                        break;
230                  case T_ATM_NCELLS:
231                        if (dagoptlval)
232                                *(int*)(herd[dagfd].iom + Int_Enables) |= IW_Enable;
233                        else
234                                *(int*)(herd[dagfd].iom + Int_Enables) &= ~IW_Enable;
235                        if (dagoptlval > 15)
236                                panic("ncells set too high (%d), max is 15\n",
237                                      dagoptlval);
238                        setatm &= ~0xffff;
239                        setatm |= dagoptlval;
240                        break;
241                  case T_ATM_LCELL:
242                        if(dagoptlval)
243                                setatm |= 0x20000;
244                        break;
245                  case T_GPP_SLEN:
246                        gpp->snaplen = dagoptlval;
247                        break;
248                  case T_GPP_VARLEN:
249                        if(dagoptlval)
250                                gpp->control |= 1;
251                        else
252                                gpp->control &= ~1;
253                        break;
254                  default:
255                        /* silently ignore unhandled tokens */
256                        if (tok < T_MAX)
257                                break;
258                        /* panic on illegal tokens */
259                        panic("unknown token %u in %s line %u\n", tok, __FILE__, __LINE__);
260                }
261
262        switch(dag_info(dagfd)->device_code) {
263          case 0x3200:
264                if(armcode(dagfd)) {
265                        dagarm=dag_clone(dagfd, DAGMINOR_ARM);
266                        if(lseek(dagarm, (off_t)(dag_info(dagfd)->phy_base+(0x5c<<2)), SEEK_SET) < 0)
267                                panic("dagioread lseek register 0x%x: %s\n", 0x5c, strerror(errno));
268                        if(read(dagarm, &val, sizeof(val)) != sizeof(val))
269                                panic("read /dev/dagarmN register 0x%x: %s\n", 0x5c, strerror(errno));
270                        close(dagarm);
271                        if (val & 0x80) {
272                                if(spawn(dagpath("tools/dagrun", temp1, 80), "-d",
273                                         herd[dagfd].dagname,
274                                         dagpath("arm/dag3pos-full.b",
275                                                 temp2, 80), NULL) < 0)
276                                        return -1;                             
277                        } else {
278                                if(spawn(dagpath("tools/dagrun", temp1, 80), "-d",
279                                         herd[dagfd].dagname,
280                                         dagpath("arm/dag3atm-hash.b",
281                                                 temp2, 80), NULL) < 0)
282                                        return -1;                             
283                        }
284                }
285                break;
286          case 0x3500:
287                /*
288                 * XXX might want to load recent images first
289                 * XXX check if DUCK PPS present ?
290                 */
291                /*
292                 * XXX we need to split params and implement an "ignore what
293                 * you don't know" option in dagthree
294                 */
295# if notyet
296                if(execlp(dagpath("tools/dagthree", temp1, 80), "-d", herd[dagfd].dagname, params, NULL) < 0)
297                        return -1;      /* errno set appropriately */
298# endif
299                if(armcode(dagfd)) {
300# ifdef __linux__
301                        if(spawn(dagpath("tools/dagrun", temp1, 80), "-d", herd[dagfd].dagname, dagpath("arm/dag3atm-erf.b", temp2, 80), NULL) < 0)
302                                return -1;                             
303                       
304# else /* FreeBSD */
305                        if(spawn(dagpath("dagld", temp1, 80), "-d", herd[dagfd].dagname, "-r", dagpath("arm/dag3atm-erf.b", temp2, 80), NULL) < 0)
306                                return -1;
307# endif
308                }
309                break;
310                /* normal */
311          case 0x350e:
312          case 0x360d:
313          case 0x360e:
314          case 0x368e:
315                break;
316                /* byteswapped */
317          case 0x351c:
318                herd[dagfd].byteswap = DAGPBM_BYTESWAP;
319                break;
320                /* byteswapped and ipp */
321          case 0x3400:
322          case 0x340e:
323          case 0x341e:
324                herd[dagfd].byteswap = DAGPBM_BYTESWAP;
325                /* ipp */
326          case 0x4100:
327          case 0x4110:
328                herd[dagfd].brokencuraddr++;
329                break;
330                /* normal */
331          case 0x3800:
332          case 0x4220:
333          case 0x422e:
334          case 0x423e:
335          case 0x4230:
336          case 0x4300:
337          case 0x430e:
338          case 0x6000:
339          case 0x6100:
340                /*
341                 * XXX might wish to load recent Xilinx image, then reload
342                 */
343                break;
344          default:
345                errno = ENODEV;         /* need to say something */
346                return -1;
347        }
348
349        /* Now we are finished with loading, it's safe to set ARM parameters */
350        if(armcode(dagfd))
351                ToAM3 = setatm;
352
353        return 0;
354}
355
356static int
357spawn(char *cmd, ...)
358{
359        va_list ap;
360        int     i, pid, status;
361        char    *args[16];      /* arbitrarily small */
362
363        switch(pid = fork()) {
364          case -1:      /* error */
365                return -1;      /* errno set appropriately */
366          case 0:       /* child */
367                va_start(ap, cmd);
368                args[0] = cmd;
369                for( i = 1 ; i < 15 ; i++)
370                        if((args[i] = va_arg(ap, char *)) == NULL)
371                                break;
372                args[i] = NULL;
373                for( i = 0 ; i < 15 ; i++ ) {
374                        if(args[i] == NULL) {
375                                break;
376                        }
377                }
378
379                va_end(ap);
380                execvp(cmd, args);
381                panic("execvp %s failed: %s\n", cmd, strerror(errno));
382          default:      /* parent */
383                if(wait(&status) != pid)
384                        return -1;
385                if(!WIFEXITED(status))
386                        return -1;
387                if(WEXITSTATUS(status) != 0)
388                        return -1;
389                break;
390        }
391        return 0;
392}
393
394extern int      dag32start(int dagfd);
395extern int      dag32stop(int dagfd);
396extern int      dag35start(int dagfd);
397extern int      dag35stop(int dagfd);
398extern int      dag42start(int dagfd);
399extern int      dag42stop(int dagfd);
400
401int
402dag_start(int dagfd)
403{
404        int     lock;
405
406        lock = 1;
407        if(ioctl(dagfd, DAGIOCLOCK, &lock) < 0)
408                return -1;      /* errno set */
409
410        memset(herd[dagfd].buf, 0, herd[dagfd].rx_memsize);
411
412        switch(dag_info(dagfd)->device_code) {
413          case 0x3200:
414                return dag32start(dagfd);
415          case 0x3500:
416          case 0x360d:
417                return dag35start(dagfd);
418          case 0x3400:
419          case 0x340e:
420          case 0x341e:
421          case 0x351c:
422          case 0x350e:
423          case 0x360e:
424          case 0x368e:
425          case 0x3800:
426          case 0x4100:
427          case 0x4110:
428          case 0x4220:
429          case 0x422e:
430          case 0x423e:
431          case 0x4230:
432          case 0x4300:
433          case 0x430e:
434          case 0x6000:
435          case 0x6100:
436                return dag42start(dagfd);
437          default:
438                errno = ENODEV;         /* need to say something */
439                return -1;
440        }
441}
442
443int
444dag_stop(int dagfd)
445{
446        int     lock;
447        int     error = 0;
448
449        switch(dag_info(dagfd)->device_code) {
450          case 0x3200:
451                error = dag32stop(dagfd);
452                break;
453          case 0x3500:
454          case 0x360d:
455                error = dag35stop(dagfd);
456                break;
457          case 0x3400:
458          case 0x340e:
459          case 0x341e:
460          case 0x351c:
461          case 0x350e:
462          case 0x360e:
463          case 0x368e:
464          case 0x3800:
465          case 0x4100:
466          case 0x4110:
467          case 0x4220:
468          case 0x422e:
469          case 0x423e:
470          case 0x4230:
471          case 0x4300:
472          case 0x430e:
473          case 0x6000:
474          case 0x6100:
475                error = dag42stop(dagfd);
476                break;
477          default:
478                errno = ENODEV;         /* need to say something */
479                error = -1;
480        }
481
482        lock = 0; /* unlock */
483        if(ioctl(dagfd, DAGIOCLOCK, &lock) < 0) 
484                error = -1;             /* errno set accordingly */
485        return error;
486}
487
488void *
489dag_mmap(int dagfd)
490{
491        void            *sp, *p, *ep;
492        daginf_t        *dip;
493        int             buf_size=0;
494
495        dagpbm_t        *pbm = (dagpbm_t *)(herd[dagfd].iom +
496                                        dag_info(dagfd)->pbm_base);
497
498        dip = dag_info(dagfd);
499
500        /* check pbm space is configured */
501        dagpbmcheck(dagfd);
502
503        /*
504         * Get the buffer size from the card if possible, since
505         * if rx/tx is configured only part of the memory space
506         * is used for rx.
507         * XXX There is currently no way to tell dag_mmap which
508         * half you want, always supplies first rx region.
509         */
510        if(dag_info(dagfd)->soft_caps.pbm) {
511                buf_size = pbm->memsize;
512        } else {
513                buf_size = dip->buf_size;
514        }
515
516        /*
517         * Start off with a fake mapping to allocate contiguous virtual
518         * address space in one lot for twice the size of the memory buffer,
519         * then map in the two copies via the dag device driver.
520         * This saves us (for the momemt) the costs of rewriting parts of
521         * the device driver, which would be an alternative solution to the
522         * problem.
523         */
524        if((sp = mmap(NULL, 2*buf_size, PROT_READ | PROT_WRITE,
525                        MAP_ANON|MAP_SHARED, -1, 0)) == MAP_FAILED)
526                return MAP_FAILED;
527        /*
528         * Now map the real buffer, 1st round.
529         */
530        if((p = mmap(sp, buf_size, PROT_READ | PROT_WRITE,
531                        MAP_FIXED|MAP_SHARED, dagfd, 0)) == MAP_FAILED)
532                return MAP_FAILED;
533        /*
534         * Map the buffer for a second time, this will turn out to be a neat
535         * feature for handling data records crossing the wrap around the
536         * top of the memory buffer.
537         */
538        if((ep = mmap(sp+buf_size, buf_size, PROT_READ|PROT_WRITE,
539                        MAP_FIXED|MAP_SHARED, dagfd, 0)) == MAP_FAILED)
540                return MAP_FAILED;
541        herd[dagfd].buf = p;
542        return p;
543}
544
545/*
546 * XXX should probably made card or feature specific.
547 * XXX should the next two be merged ? Blocking/non-blocking ?
548 */
549int
550dag_offset(int dagfd, int *oldoffset, int flags)
551{
552        dagpbm_t        *pbm = (dagpbm_t *)(herd[dagfd].iom +
553                                        dag_info(dagfd)->pbm_base);
554        int             offset;
555
556        /*
557         * The implementation implies that offsets within
558         * the buffer are now starting zero to top of the
559         * hole, exclusive the top address, which is considered
560         * zero.
561         */
562        if(*oldoffset >= herd[dagfd].rx_memsize)
563                *oldoffset -= herd[dagfd].rx_memsize;
564
565        if(dag_info(dagfd)->soft_caps.pbm) {
566                /*
567                 * Advance acknowledgement pointer, this should be done in
568                 * all cases, blocking or non-blocking.
569                 * Reinit the burst manager, in case safety net was reached
570                 * XXX we might consider reporting safety net status ?
571                 */
572                pbm->wrsafe = dag_info(dagfd)->phy_addr + WRSAFE(dagfd, *oldoffset);
573                pbm->cs = (DAGPBM_AUTOWRAP|herd[dagfd].byteswap);
574                /*
575                 * With the WRSAFE() macro in place, if offset equals oldoffset,
576                 * the buffer is guaranteed to be empty.
577                 */
578                offset = PBMOFFSET(dagfd);
579                while(offset == *oldoffset) {
580                        if (flags & DAGF_NONBLOCK)
581                                return offset;
582                        usleep(1);
583                        offset = PBMOFFSET(dagfd);
584                }
585        } else {
586                offset = ARMOFFSET(dagfd);
587                while(offset == *oldoffset) {
588                        if (flags & DAGF_NONBLOCK)
589                                return offset;
590                        usleep(1);
591                        offset = ARMOFFSET(dagfd);
592                }
593        }
594
595        if(offset > herd[dagfd].rx_memsize)
596                panic("dagapi: dag_offset internal error offset=0x%x\n", offset);
597
598        if(offset < *oldoffset)
599                offset += herd[dagfd].rx_memsize;
600
601        return offset;
602}
603
604void *
605dag_nextpkt(void *curpkt, void *buf, int bufsize)
606{
607
608        return 0;
609}
610
611/*
612 * XXX this shall be moved to a different file later
613 */
614int
615dag32start(int dagfd)
616{
617        if(armcode(dagfd)) {
618                ToAM2 = 0;                      /* clear command register */
619
620                while(ToHM2 != 1) {
621                        usleep(1);
622                        if(ToHM2 == 2)
623                                break;          /* protocol bug */
624                }
625
626                ToAM2 = 1;                      /* command: run */
627
628                while(ToHM2 != 2)
629                        usleep(1);
630        }
631
632        return 0;
633}
634
635int
636dag32stop(int dagfd)
637{
638        int     loop = 100, retval=0;
639
640        if(armcode(dagfd)) {
641                ToAM2 = 2;                      /* stop command */
642
643                while(--loop > 0) {
644                        usleep(10*1000); /* give ARM a chance to settle */
645                        if(ToHM2 == 3)
646                                break;
647                }
648                retval = (ToHM2 == 3) ? 0 : -1; /* XXX need to set errno */
649        }
650        return retval;
651}
652
653int
654dag35start(int dagfd)
655{
656        dagpbm_t        *pbm = (dagpbm_t *)(herd[dagfd].iom +
657                                        dag_info(dagfd)->pbm_base);
658
659        /*
660         * XXX make sure the DUCK is in sync, if needed
661         */
662        if(dag_info(dagfd)->soft_caps.pbm) {
663                pbm->cs = (DAGPBM_PAUSED | DAGPBM_SAFETY);
664                while (pbm->cs & DAGPBM_REQPEND)
665                        usleep(1);
666
667                IOM(0x88)  |= (1<<31);          /* L2RESET, will auto deassert */
668
669                pbm->bursttmo = 0xffff;
670                pbm->segsize = (1024*1024);     /* paranoia, not that it matters */
671                pbm->wrsafe = dag_info(dagfd)->phy_addr + WRSAFE(dagfd, herd[dagfd].rx_memsize);
672                pbm->cs = (DAGPBM_SYNCL2R|DAGPBM_AUTOWRAP|herd[dagfd].byteswap);
673
674                IOM(0x88)  |= (1<<31);          /* L2RESET, will auto deassert */
675
676        }
677
678        if(armcode(dagfd)) {
679                IOM(0x88)  |= (1<<31);          /* L2RESET, will auto deassert */
680
681                ToAM2 = 0;                      /* clear command register */
682
683                while(ToHM2 != 1) {
684                        usleep(1);
685                        if(ToHM2 == 2)
686                                break;          /* protocol bug */
687                }
688
689                ToAM2 = 1;                      /* command: run */
690
691                while(ToHM2 != 2)
692                        usleep(1);
693        }
694
695        return 0;
696}
697
698int
699dag35stop(int dagfd)
700{
701        dagpbm_t        *pbm = (dagpbm_t *)(herd[dagfd].iom +
702                                        dag_info(dagfd)->pbm_base);
703        int     loop = 100, retval=0;
704
705        if(armcode(dagfd)) {
706                ToAM2 = 2;                      /* stop command */
707
708                while(--loop > 0) {
709                        usleep(10*1000); /* give ARM a chance to settle */
710                        if(ToHM2 == 3)
711                                break;
712                }
713                retval = (ToHM2 == 3) ? 0 : -1; /* XXX need to set errno */
714        }
715        if(dag_info(dagfd)->soft_caps.pbm) {
716                pbm->cs = (DAGPBM_PAUSED);
717
718                while(--loop > 0) {
719                        if(!(pbm->cs & DAGPBM_REQPEND))
720                                break;
721                        usleep(10*1000);
722                }
723                retval += (pbm->cs & DAGPBM_REQPEND) ? -1 : 0;
724        }
725        return retval;
726}
727
728int
729dag42start(int dagfd)
730{
731        dagpbm_t        *pbm = (dagpbm_t *)(herd[dagfd].iom +
732                                        dag_info(dagfd)->pbm_base);
733
734        pbm->cs = (DAGPBM_PAUSED | DAGPBM_SAFETY);
735        while (pbm->cs & DAGPBM_REQPEND)
736                usleep(1);
737
738        IOM(0x88)  |= (1<<31);          /* L2RESET, will auto deassert */
739
740        pbm->bursttmo = 0xffff;
741        pbm->segsize = (1024*1024);     /* paranoia, not that it matters */
742        pbm->wrsafe = dag_info(dagfd)->phy_addr + WRSAFE(dagfd, herd[dagfd].rx_memsize);
743        pbm->cs = (DAGPBM_SYNCL2R|DAGPBM_AUTOWRAP|herd[dagfd].byteswap);
744
745        IOM(0x88)  |= (1<<31);          /* L2RESET, will auto deassert */
746
747        return 0;
748}
749
750int
751dag42stop(int dagfd)
752{
753        dagpbm_t        *pbm = (dagpbm_t *)(herd[dagfd].iom +
754                                        dag_info(dagfd)->pbm_base);
755        int             loop = 100;
756
757        pbm->cs = (DAGPBM_PAUSED);
758
759        while(--loop > 0) {
760                if(!(pbm->cs & DAGPBM_REQPEND))
761                        break;
762                usleep(10*1000);
763        }
764
765        return 0;
766}
767
768static void
769dagpbmcheck(int dagfd)
770{
771        dagpbm_t        *pbm = (dagpbm_t *)(herd[dagfd].iom +
772                                        dag_info(dagfd)->pbm_base);
773       
774        if(dag_info(dagfd)->soft_caps.pbm) {
775                if((pbm->memaddr & 0xfffffff8) == 0xfffffff8) {
776                        /* pbm unconfigured*/
777                        pbm->memaddr = dag_info(dagfd)->phy_addr; /* XXX curaddr bugfix */
778                        pbm->memsize = dag_info(dagfd)->buf_size;
779                }
780                /* XXX cache actual hole location for dag_offset etc*/
781                herd[dagfd].rx_memaddr = pbm->memaddr;
782                herd[dagfd].rx_memsize = pbm->memsize;
783        } else {
784                /* XXX cache actual hole location for dag_offset etc*/
785                herd[dagfd].rx_memaddr = dag_info(dagfd)->phy_addr;
786                herd[dagfd].rx_memsize = dag_info(dagfd)->buf_size;
787        }
788}
789
790/*
791 * I wish there was a better way, by means of a clone ioctl() in the
792 * kernel, but it appears to be more difficult and also OS specific,
793 * so here is the second best and also portable version.
794 */
795int
796dag_clone(int dagfd, int minor)
797{
798        regex_t         reg;
799        regmatch_t      match;
800        char            buf[16];
801        char            *fmt[DAGMINOR_MAX] = {
802                                "/dev/dag%c",           /* DAGMINOR_DAG */
803                                "/dev/dagmem%c",        /* DAGMINOR_MEM */
804                                "/dev/dagiom%c",        /* DAGMINOR_IOM */
805                                "/dev/dagarm%c",        /* DAGMINOR_ARM */
806                                "/dev/dagram%c",        /* DAGMINOR_RAM */
807                        };
808        int             r;
809
810        if(minor >= DAGMINOR_MAX) {
811                errno = EDOM;
812                return -1;
813        }
814        if(regcomp(&reg, "/dev/dag(iom|mem|arm|ram)*[0-9]", REG_EXTENDED) != 0) {
815                errno = EDOM;   /* grrrk */
816                return -1;
817        }
818        if((r = regexec(&reg, herd[dagfd].dagname, 1, &match, 0)) !=0) {
819                errno = EDOM;  /* grrrk */
820                return -1;
821        }
822        (void)sprintf(buf, fmt[minor], herd[dagfd].dagname[match.rm_eo-1]);
823        regfree(&reg);
824
825        return open(buf, O_RDWR);
826}
827
828static void
829panic(char *fmt, ...)
830{
831        va_list ap;
832
833        (void)fprintf(stderr, "daglib: panic: ");
834        va_start(ap, fmt);
835        (void)vfprintf(stderr, fmt, ap);
836        va_end(ap);
837        exit(1);
838}
839
Note: See TracBrowser for help on using the repository browser.