Nut/OS  4.10.3
API Reference
npl.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00056 #include <dev/npl.h>
00057 
00058 #if 0
00059 /* Use for local debugging. */
00060 #define NUTDEBUG
00061 #include <stdio.h>
00062 #endif
00063 
00068 
00069 static int npl_registered;
00070 
00071 /*
00072  * NIC interrupt entry.
00073  */
00074 static void NplInterrupt(void *arg)
00075 {
00076     uint16_t slr;
00077 
00078     /* Read signal latch register and clear all enabled interrupts. */
00079     slr = inw(NPL_SLR) & inw(NPL_IMR);
00080 
00081     /* RS232 CTS activated. */
00082     if (slr & NPL_RSCTS) {
00083         if (sig_RSCTS.ir_handler) {
00084             (sig_RSCTS.ir_handler) (sig_RSCTS.ir_arg);
00085         }
00086     }
00087     /* RS232 DSR activated. */
00088     if (slr & NPL_RSDSR) {
00089         if (sig_RSDSR.ir_handler) {
00090             (sig_RSDSR.ir_handler) (sig_RSDSR.ir_arg);
00091         }
00092     }
00093     /* RS232 DCD activated. */
00094     if (slr & NPL_RSDCD) {
00095         if (sig_RSDCD.ir_handler) {
00096             (sig_RSDCD.ir_handler) (sig_RSDCD.ir_arg);
00097         }
00098     }
00099     /* RS232 RI activated. */
00100     if (slr & NPL_RSRI) {
00101         if (sig_RSRI.ir_handler) {
00102             (sig_RSRI.ir_handler) (sig_RSRI.ir_arg);
00103         }
00104     }
00105     /* RTC Alarm activated. */
00106     if (slr & NPL_RTCALARM) {
00107         if (sig_RTCALARM.ir_handler) {
00108             (sig_RTCALARM.ir_handler) (sig_RTCALARM.ir_arg);
00109         }
00110     }
00111     /* LAN wakeup activated. */
00112     if (slr & NPL_LANWAKEUP) {
00113         if (sig_LANWAKEUP.ir_handler) {
00114             (sig_LANWAKEUP.ir_handler) (sig_LANWAKEUP.ir_arg);
00115         }
00116     }
00117     /* FLASH ready activated. */
00118     if (slr & NPL_FMBUSY) {
00119         if (sig_FMBUSY.ir_handler) {
00120             (sig_FMBUSY.ir_handler) (sig_FMBUSY.ir_arg);
00121         }
00122     }
00123     /* RS232 signal valid. */
00124     if (slr & NPL_RSINVAL) {
00125         if (sig_RSINVAL.ir_handler) {
00126             (sig_RSINVAL.ir_handler) (sig_RSINVAL.ir_arg);
00127         }
00128     }
00129     /* RS232 signal invalid. */
00130     if (slr & NPL_NRSINVAL) {
00131         if (sig_NRSINVAL.ir_handler) {
00132             (sig_NRSINVAL.ir_handler) (sig_NRSINVAL.ir_arg);
00133         }
00134     }
00135     /* Multimedia card inserted. */
00136     if (slr & NPL_MMCD) {
00137         if (sig_MMCD.ir_handler) {
00138             (sig_MMCD.ir_handler) (sig_MMCD.ir_arg);
00139         }
00140     }
00141     /* Multimedia card removed. */
00142     if (slr & NPL_NMMCD) {
00143         if (sig_NMMCD.ir_handler) {
00144             (sig_NMMCD.ir_handler) (sig_NMMCD.ir_arg);
00145         }
00146     }
00147     outw(NPL_SCR, slr);
00148 }
00149 
00150 static int NplIrqCtl(int cmd, void *param, IRQ_HANDLER * irq, unsigned int mask)
00151 {
00152     int rc = 0;
00153     unsigned int *ival = (unsigned int *) param;
00154     uint16_t enabled = inw(NPL_IMR) & mask;
00155 
00156     /* Disable interrupt. */
00157     if (enabled) {
00158         outw(NPL_IMR, enabled & ~mask);
00159     }
00160     switch (cmd) {
00161     case NUT_IRQCTL_INIT:
00162         /* Clear interrupt */
00163         outw(NPL_SCR, mask);
00164         break;
00165     case NUT_IRQCTL_STATUS:
00166         if (enabled) {
00167             *ival |= 1;
00168         } else {
00169             *ival &= ~1;
00170         }
00171         break;
00172     case NUT_IRQCTL_ENABLE:
00173         enabled = 1;
00174         break;
00175     case NUT_IRQCTL_DISABLE:
00176         enabled = 0;
00177         break;
00178 #ifdef NUT_PERFMON
00179     case NUT_IRQCTL_GETCOUNT:
00180         *ival = (unsigned int) irq->ir_count;
00181         irq->ir_count = 0;
00182         break;
00183 #endif
00184     default:
00185         rc = -1;
00186         break;
00187     }
00188 
00189     /* Enable interrupt. */
00190     if (enabled) {
00191         outw(NPL_IMR, inw(NPL_IMR) | mask);
00192     }
00193     return rc;
00194 }
00195 
00196 
00197 static int NplRsCtsCtl(int cmd, void *param)
00198 {
00199     return NplIrqCtl(cmd, param, &sig_RSCTS, NPL_RSCTS);
00200 }
00201 
00202 static int NplRsDsrCtl(int cmd, void *param)
00203 {
00204     return NplIrqCtl(cmd, param, &sig_RSDSR, NPL_RSDSR);
00205 }
00206 
00207 static int NplRsDcdCtl(int cmd, void *param)
00208 {
00209     return NplIrqCtl(cmd, param, &sig_RSDCD, NPL_RSDCD);
00210 }
00211 
00212 static int NplRsRiCtl(int cmd, void *param)
00213 {
00214     return NplIrqCtl(cmd, param, &sig_RSRI, NPL_RSRI);
00215 }
00216 
00217 static int NplRtcAlarmCtl(int cmd, void *param)
00218 {
00219     return NplIrqCtl(cmd, param, &sig_RTCALARM, NPL_RTCALARM);
00220 }
00221 
00222 static int NplLanWakeupCtl(int cmd, void *param)
00223 {
00224     return NplIrqCtl(cmd, param, &sig_LANWAKEUP, NPL_LANWAKEUP);
00225 }
00226 
00227 static int NplFmBusyCtl(int cmd, void *param)
00228 {
00229     return NplIrqCtl(cmd, param, &sig_FMBUSY, NPL_FMBUSY);
00230 }
00231 
00232 static int NplRsInvalCtl(int cmd, void *param)
00233 {
00234     return NplIrqCtl(cmd, param, &sig_RSINVAL, NPL_RSINVAL);
00235 }
00236 
00237 static int NplRsValidCtl(int cmd, void *param)
00238 {
00239     return NplIrqCtl(cmd, param, &sig_NRSINVAL, NPL_NRSINVAL);
00240 }
00241 
00242 static int NplMmcInsertCtl(int cmd, void *param)
00243 {
00244     return NplIrqCtl(cmd, param, &sig_MMCD, NPL_MMCD);
00245 }
00246 
00247 static int NplMmcRemoveCtl(int cmd, void *param)
00248 {
00249     return NplIrqCtl(cmd, param, &sig_NMMCD, NPL_NMMCD);
00250 }
00251 
00252 
00267 int NplRegisterIrqHandler(IRQ_HANDLER * irq, void (*handler) (void *), void *arg)
00268 {
00269     int rc;
00270 
00271     /* Initialize this interrupt. */
00272     rc = (irq->ir_ctl) (NUT_IRQCTL_INIT, NULL);
00273 
00274     if (rc == 0) {
00275         /* Set the interrupt handler. */
00276         irq->ir_arg = arg;
00277         irq->ir_handler = handler;
00278 
00279         if (!npl_registered) {
00280             npl_registered = 1;
00281 #if defined(ETHERNUT3)
00282             outr(PIO_PDR, _BV(9));
00283 #endif
00284             if ((rc = NutRegisterIrqHandler(&sig_INTERRUPT0, NplInterrupt, NULL)) == 0) {
00285                 NutIrqSetMode(&sig_INTERRUPT0, NUT_IRQMODE_LOWLEVEL);
00286                 NutIrqEnable(&sig_INTERRUPT0);
00287             }
00288         }
00289     }
00290     return rc;
00291 }
00292 
00300 int NplIrqEnable(IRQ_HANDLER * irq)
00301 {
00302     return (irq->ir_ctl) (NUT_IRQCTL_ENABLE, NULL);
00303 }
00304 
00312 int NplIrqDisable(IRQ_HANDLER * irq)
00313 {
00314     return (irq->ir_ctl) (NUT_IRQCTL_DISABLE, NULL);
00315 }
00316 
00320 IRQ_HANDLER sig_RSCTS = {
00321 #ifdef NUT_PERFMON
00322     0,                          /* Interrupt counter, ir_count. */
00323 #endif
00324     NULL,                       /* Passed argument, ir_arg. */
00325     NULL,                       /* Handler subroutine, ir_handler. */
00326     NplRsCtsCtl                 /* Interrupt control, ir_ctl. */
00327 };
00328 
00332 IRQ_HANDLER sig_RSDSR = {
00333 #ifdef NUT_PERFMON
00334     0,                          /* Interrupt counter, ir_count. */
00335 #endif
00336     NULL,                       /* Passed argument, ir_arg. */
00337     NULL,                       /* Handler subroutine, ir_handler. */
00338     NplRsDsrCtl                 /* Interrupt control, ir_ctl. */
00339 };
00340 
00344 IRQ_HANDLER sig_RSDCD = {
00345 #ifdef NUT_PERFMON
00346     0,                          /* Interrupt counter, ir_count. */
00347 #endif
00348     NULL,                       /* Passed argument, ir_arg. */
00349     NULL,                       /* Handler subroutine, ir_handler. */
00350     NplRsDcdCtl                 /* Interrupt control, ir_ctl. */
00351 };
00352 
00356 IRQ_HANDLER sig_RSRI = {
00357 #ifdef NUT_PERFMON
00358     0,                          /* Interrupt counter, ir_count. */
00359 #endif
00360     NULL,                       /* Passed argument, ir_arg. */
00361     NULL,                       /* Handler subroutine, ir_handler. */
00362     NplRsRiCtl                  /* Interrupt control, ir_ctl. */
00363 };
00364 
00368 IRQ_HANDLER sig_RTCALARM = {
00369 #ifdef NUT_PERFMON
00370     0,                          /* Interrupt counter, ir_count. */
00371 #endif
00372     NULL,                       /* Passed argument, ir_arg. */
00373     NULL,                       /* Handler subroutine, ir_handler. */
00374     NplRtcAlarmCtl              /* Interrupt control, ir_ctl. */
00375 };
00376 
00380 IRQ_HANDLER sig_LANWAKEUP = {
00381 #ifdef NUT_PERFMON
00382     0,                          /* Interrupt counter, ir_count. */
00383 #endif
00384     NULL,                       /* Passed argument, ir_arg. */
00385     NULL,                       /* Handler subroutine, ir_handler. */
00386     NplLanWakeupCtl             /* Interrupt control, ir_ctl. */
00387 };
00388 
00392 IRQ_HANDLER sig_FMBUSY = {
00393 #ifdef NUT_PERFMON
00394     0,                          /* Interrupt counter, ir_count. */
00395 #endif
00396     NULL,                       /* Passed argument, ir_arg. */
00397     NULL,                       /* Handler subroutine, ir_handler. */
00398     NplFmBusyCtl                /* Interrupt control, ir_ctl. */
00399 };
00400 
00404 IRQ_HANDLER sig_RSINVAL = {
00405 #ifdef NUT_PERFMON
00406     0,                          /* Interrupt counter, ir_count. */
00407 #endif
00408     NULL,                       /* Passed argument, ir_arg. */
00409     NULL,                       /* Handler subroutine, ir_handler. */
00410     NplRsInvalCtl               /* Interrupt control, ir_ctl. */
00411 };
00412 
00416 IRQ_HANDLER sig_NRSINVAL = {
00417 #ifdef NUT_PERFMON
00418     0,                          /* Interrupt counter, ir_count. */
00419 #endif
00420     NULL,                       /* Passed argument, ir_arg. */
00421     NULL,                       /* Handler subroutine, ir_handler. */
00422     NplRsValidCtl               /* Interrupt control, ir_ctl. */
00423 };
00424 
00428 IRQ_HANDLER sig_MMCD = {
00429 #ifdef NUT_PERFMON
00430     0,                          /* Interrupt counter, ir_count. */
00431 #endif
00432     NULL,                       /* Passed argument, ir_arg. */
00433     NULL,                       /* Handler subroutine, ir_handler. */
00434     NplMmcInsertCtl             /* Interrupt control, ir_ctl. */
00435 };
00436 
00440 IRQ_HANDLER sig_NMMCD = {
00441 #ifdef NUT_PERFMON
00442     0,                          /* Interrupt counter, ir_count. */
00443 #endif
00444     NULL,                       /* Passed argument, ir_arg. */
00445     NULL,                       /* Handler subroutine, ir_handler. */
00446     NplMmcRemoveCtl             /* Interrupt control, ir_ctl. */
00447 };
00448