The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ppc/devirq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "m8260.h"
    7 #include        "../port/error.h"
    8 
    9 enum{
   10         IRQ0 = 18,
   11         Level = 0,
   12         Edge = 1,
   13 };
   14 
   15 enum{
   16         Qdir,
   17         Qirq1,
   18         Qirq2,
   19         Qirq3,
   20         Qirq4,
   21         Qirq5,
   22         Qirq6,
   23         Qirq7,
   24         Qmstimer,
   25         Qfpgareset,
   26         NIRQ,
   27 };
   28 
   29 static Dirtab irqdir[]={
   30         ".",            {Qdir, 0, QTDIR},       0,      DMDIR|0555,
   31         "irq1",         {Qirq1},                0,      0666,
   32         "irq2",         {Qirq2},                0,      0666,
   33         "irq3",         {Qirq1},                0,      0666,
   34         "irq4",         {Qirq1},                0,      0666,
   35         "irq5",         {Qirq1},                0,      0666,
   36         "irq6",         {Qirq1},                0,      0666,
   37         "irq7",         {Qirq1},                0,      0666,
   38         "mstimer",      {Qmstimer},             0,      0666,
   39         "fpgareset",    {Qfpgareset},           0,      0222,
   40 };
   41 
   42 enum
   43 {
   44         CMinterrupt,
   45         CMmode,
   46         CMreset,
   47         CMwait,
   48         CMdebug,
   49 };
   50 
   51 Cmdtab irqmsg[] =
   52 {
   53         CMinterrupt,    "interrupt",    2,
   54         CMmode,         "mode",         2,
   55         CMreset,        "reset",        1,
   56         CMwait,         "wait",         1,
   57         CMdebug,        "debug",        1,
   58 };
   59 
   60 typedef struct Irqconfig Irqconfig;
   61 struct Irqconfig {
   62         int             intenable;      /* Interrupts are enabled */
   63         int             mode;           /* level == 0; edge == 1 */
   64         ulong           interrupts;     /* Count interrupts */
   65         ulong           sleepints;      /* interrupt count when waiting */
   66         Rendez          r;              /* Rendez-vous point for interrupt waiting */
   67         Irqconfig       *next;
   68         Timer;
   69 };
   70 
   71 Irqconfig *irqconfig[NIRQ];     /* irqconfig[0] is not used */
   72 Lock irqlock;
   73 
   74 static void interrupt(Ureg*, void*);
   75 void dumpvno(void);
   76 
   77 static void
   78 ticmstimer(Ureg*, Timer *t)
   79 {
   80         Irqconfig *ic;
   81 
   82         ic = t->ta;
   83         ic->interrupts++;
   84         wakeup(&ic->r);
   85 }
   86 
   87 void
   88 irqenable(Irqconfig *ic, int irq)
   89 {
   90         /* call with ilock(&irqlock) held */
   91 
   92         if (ic->intenable)
   93                 return;
   94         if (irq == Qmstimer){
   95                 if (ic->tnext == nil)
   96                         ic->tns = MS2NS(ic->mode);
   97                 ic->tmode = Tperiodic;
   98                 timeradd(&ic->Timer);
   99         }else{
  100                 if (irqconfig[irq]){
  101                         ic->next = irqconfig[irq];
  102                         irqconfig[irq] = ic;
  103                 }else{
  104                         ic->next = nil;
  105                         irqconfig[irq] = ic;
  106                         intrenable(IRQ0 + irq, interrupt, &irqconfig[irq], irqdir[irq].name);
  107                 }
  108         }
  109         ic->intenable = 1;
  110 }
  111 
  112 void
  113 irqdisable(Irqconfig *ic, int irq)
  114 {
  115         Irqconfig **pic;
  116 
  117         /* call with ilock(&irqlock) held */
  118 
  119         if (ic->intenable == 0)
  120                 return;
  121         if (irq == Qmstimer){
  122                 timerdel(&ic->Timer);
  123         }else{
  124                 for(pic = &irqconfig[irq]; *pic != ic; pic = &(*pic)->next)
  125                         assert(*pic);
  126                 *pic = (*pic)->next;
  127                 if (irqconfig[irq] == nil)
  128                         intrdisable(IRQ0 + irq, interrupt, &irqconfig[irq], irqdir[irq].name);
  129         }
  130         ic->intenable = 0;
  131 }
  132 
  133 static Chan*
  134 irqattach(char *spec)
  135 {
  136         return devattach('b', spec);
  137 }
  138 
  139 static Walkqid*
  140 irqwalk(Chan *c, Chan *nc, char **name, int nname)
  141 {
  142         return devwalk(c, nc, name,nname, irqdir, nelem(irqdir), devgen);
  143 }
  144 
  145 static int
  146 irqstat(Chan *c, uchar *dp, int n)
  147 {
  148         return devstat(c, dp, n, irqdir, nelem(irqdir), devgen);
  149 }
  150 
  151 static Chan*
  152 irqopen(Chan *c, int omode)
  153 {
  154         Irqconfig *ic;
  155         int irq;
  156 
  157         irq = (ulong)c->qid.path;
  158         if(irq != Qdir){
  159                 ic = mallocz(sizeof(Irqconfig), 1);
  160                 ic->tf = ticmstimer;
  161                 ic->ta = ic;
  162                 if (irq == Qmstimer)
  163                         ic->mode = 1000;
  164                 c->aux = ic;
  165         }
  166         return devopen(c, omode, irqdir, nelem(irqdir), devgen);
  167 }
  168 
  169 static void
  170 irqclose(Chan *c)
  171 {
  172         int irq;
  173         Irqconfig *ic;
  174 
  175         irq = (ulong)c->qid.path;
  176         if(irq == Qdir)
  177                 return;
  178         ic = c->aux;
  179         if (irq > Qmstimer)
  180                 return;
  181         ilock(&irqlock);
  182         irqdisable(ic, irq);
  183         iunlock(&irqlock);
  184         free(ic);
  185 }
  186 
  187 static int
  188 irqtfn(void *arg)
  189 {
  190         Irqconfig *ic;
  191 
  192         ic = arg;
  193         return ic->sleepints != ic->interrupts;
  194 }
  195 
  196 static long
  197 irqread(Chan *c, void *buf, long n, vlong)
  198 {
  199         int irq;
  200         Irqconfig *ic;
  201         char tmp[24];
  202 
  203         if(n <= 0)
  204                 return n;
  205         irq = (ulong)c->qid.path;
  206         if(irq == Qdir)
  207                 return devdirread(c, buf, n, irqdir, nelem(irqdir), devgen);
  208         if(irq > Qmstimer){
  209                 print("irqread 0x%llux\n", c->qid.path);
  210                 error(Egreg);
  211         }
  212         ic = c->aux;
  213         if (ic->intenable == 0)
  214                 error("disabled");
  215         ic->sleepints = ic->interrupts;
  216         sleep(&ic->r, irqtfn, ic);
  217         if (irq == Qmstimer)
  218                 snprint(tmp, sizeof tmp, "%11lud %d", ic->interrupts, ic->mode);
  219         else
  220                 snprint(tmp, sizeof tmp, "%11lud %s", ic->interrupts, ic->mode ?"edge":"level");
  221         n = readstr(0, buf, n, tmp);
  222         return n;
  223 }
  224 
  225 static long
  226 irqwrite(Chan *c, void *a, long n, vlong)
  227 {
  228         int irq;
  229         Irqconfig *ic;
  230         Cmdbuf *cb;
  231         Cmdtab *ct;
  232 
  233         if(n <= 0)
  234                 return n;
  235 
  236         irq = (ulong)c->qid.path;
  237         if(irq <= 0 || irq >= nelem(irqdir)){
  238                 print("irqwrite 0x%llux\n", c->qid.path);
  239                 error(Egreg);
  240         }
  241         if (irq == Qfpgareset){
  242                 if (strncmp(a, "reset", 5) == 0)
  243                         fpgareset();
  244                 else
  245                         error(Egreg);
  246                 return n;
  247         }
  248         ic = c->aux;
  249 
  250         cb = parsecmd(a, n);
  251 
  252         if(waserror()) {
  253                 free(cb);
  254                 nexterror();
  255         }
  256         ct = lookupcmd(cb, irqmsg, nelem(irqmsg));
  257         switch(ct->index) {
  258         case    CMinterrupt:
  259                 /* Turn interrupts on or off */
  260                 if (strcmp(cb->f[1], "on") == 0){
  261                         ilock(&irqlock);
  262                         irqenable(ic, irq);
  263                         iomem->siprr = 0x65009770;
  264                         iunlock(&irqlock);
  265                 }else if (strcmp(cb->f[1], "off") == 0){
  266                         ilock(&irqlock);
  267                         irqdisable(ic, irq);
  268                         iunlock(&irqlock);
  269                 }else
  270                         error(Ebadarg);
  271                 break;
  272         case CMmode:
  273                 /* Set mode */
  274                 if (irq == Qmstimer){
  275                         ic->mode = strtol(cb->f[1], nil, 0);
  276                         if (ic->mode <= 0){
  277                                 ic->tns = MS2NS(1000);
  278                                 ic->mode = 1000;
  279                                 error(Ebadarg);
  280                         }
  281                         ic->tns = MS2NS(ic->mode);
  282                 }else if (strcmp(cb->f[1], "level") == 0){
  283                         ic->mode = Level;
  284                         iomem->siexr &= ~(0x8000 >> irq);
  285                 }else if (strcmp(cb->f[1], "edge") == 0){
  286                         ic->mode = Edge;
  287                         iomem->siexr |= 0x8000 >> irq;
  288                 }else
  289                         error(Ebadarg);
  290                 break;
  291         case CMreset:
  292                 ic->interrupts = 0;
  293                 break;
  294         case CMwait:
  295                 if (ic->intenable == 0)
  296                         error("interrupts are off");
  297                 ic->sleepints = ic->interrupts;
  298                 sleep(&ic->r, irqtfn, ic);
  299                 break;
  300         case CMdebug:
  301                 print("simr h/l 0x%lux/0x%lux, sipnr h/l 0x%lux/0x%lux, siexr 0x%lux, siprr 0x%lux\n",
  302                         iomem->simr_h, iomem->simr_l,
  303                         iomem->sipnr_h, iomem->sipnr_l,
  304                         iomem->siexr, iomem->siprr);
  305                 dumpvno();
  306         }
  307         poperror();
  308         free(cb);
  309 
  310         /* Irqi */
  311         return n;
  312 }
  313 
  314 static void
  315 interrupt(Ureg*, void *arg)
  316 {
  317         Irqconfig **pic, *ic;
  318         int irq;
  319 
  320         pic = arg;
  321         irq = pic - irqconfig;
  322         if (irq <= 0 || irq > nelem(irqdir)){
  323                 print("Unexpected interrupt: %d\n", irq);
  324                 return;
  325         }
  326         ilock(&irqlock);
  327         if (irq <= Qirq7)
  328                 iomem->sipnr_h |= 0x8000 >> irq;        /* Clear the interrupt */
  329         for(ic = *pic; ic; ic = ic->next){
  330                 ic->interrupts++;
  331                 wakeup(&ic->r);
  332         }
  333         iunlock(&irqlock);
  334 }
  335 
  336 Dev irqdevtab = {
  337         'b',
  338         "irq",
  339 
  340         devreset,
  341         devinit,
  342         devshutdown,
  343         irqattach,
  344         irqwalk,
  345         irqstat,
  346         irqopen,
  347         devcreate,
  348         irqclose,
  349         irqread,
  350         devbread,
  351         irqwrite,
  352         devbwrite,
  353         devremove,
  354         devwstat,
  355 };

Cache object: 3440b257d1b5f86414c41cef139aacda


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.