source: multiio/pcmmio/mio_io_rtems.c @ 396c143

Last change on this file since 396c143 was 396c143, checked in by Joel Sherrill <joel.sherrill@…>, on 10/05/11 at 18:03:32

2011-10-05 Cindy Cicalese <cicalese@…>

  • mio_io.c, mio_io.h, mio_io_rtems.c: Updates after testing in lab.
  • Property mode set to 100644
File size: 19.4 KB
Line 
1/* mio_io.c WinSystems support module file for the  PCM-MIO RTEMS driver
2 *
3 *  $Id$
4 *
5 *  This file implements the hardware access routines as implemented for RTEMS.
6 *  This is very likely close to what is required with no OS.
7 */
8
9/* #define DEBUG 1 */
10
11#include "mio_io.h"   
12
13#include <stdio.h>
14#include <fcntl.h>      /* open */
15#include <unistd.h>     /* exit */
16#include <sys/ioctl.h>  /* ioctl */
17#include <stdlib.h>     /* for exit */
18
19#include <rtems.h>
20#include <i386_io.h>
21#include <bsp/irq.h>
22
23/*
24 *  These are configured by the initialization call.
25 */
26
27/* IRQ source or 0 ==> polled */
28static unsigned short irq = 0;
29/* This holds the base addresses of the board */
30static unsigned short base_port = 0;
31
32/* Function prototypes for local functions */
33static int get_buffered_int(
34  unsigned long long *timestamp
35);
36static void init_io(unsigned short io_address);
37static void clr_int(int bit_number);
38static int get_int(void);
39
40/* RTEMS Ids for Wait Queues */
41rtems_id wq_a2d_1;
42rtems_id wq_a2d_2;
43rtems_id wq_dac_1;
44rtems_id wq_dac_2;
45rtems_id wq_dio;
46
47/*
48 *  Limits on number of buffered discrete input interrupts in
49 *  the message queue.
50 */
51#define MAXIMUM_BUFFERED_DISCRETE_INTERRUPTS 1024
52
53///////////////////////////////////////////////////////////////////////////////
54typedef struct {
55  unsigned long long timestamp;
56  int                pin;
57} din_message_t;
58
59unsigned int pcmmio_dio_missed_interrupts;
60
61int interruptible_sleep_on(
62  rtems_id *id,
63  int       milliseconds
64);
65void wake_up_interruptible(
66  rtems_id *id
67);
68
69//
70//    MIO_READ_IRQ_ASSIGNED
71//
72//////////////////////////////////////////////////////////////////////////////
73
74int mio_read_irq_assigned(void)
75{
76  mio_error_code = MIO_SUCCESS;
77
78  if (check_handle())   /* Check for chip available */
79    return -1;
80
81  /* All of our programming of the hardware is handled at this level so that
82     all of the routines that need to shove and IRQ value into hardware will
83     use this call.
84  */
85
86  return (irq & 0xff);
87}
88
89///////////////////////////////////////////////////////////////////////////////
90//
91//    READ_DIO_BYTE
92//
93//////////////////////////////////////////////////////////////////////////////
94
95unsigned char read_dio_byte(int offset)
96{
97  unsigned char byte_val;
98  unsigned char offset_val;
99
100  mio_error_code = MIO_SUCCESS;
101
102  if (check_handle())   /* Check for chip available */
103    return -1;
104
105  /* All bit operations are handled at this level so we need only
106     read and write bytes from the actual hardware.
107  */
108
109  offset_val = offset & 0xff;
110  byte_val = inb(base_port + 0x10 + offset_val);
111  return (byte_val & 0xff);
112}
113
114///////////////////////////////////////////////////////////////////////////////
115//
116//    MIO_READ_REG
117//
118//////////////////////////////////////////////////////////////////////////////
119
120unsigned char mio_read_reg(int offset)
121{
122  unsigned char byte_val;
123  unsigned char offset_val;
124
125  mio_error_code = MIO_SUCCESS;
126
127  if (check_handle())   /* Check for chip available */
128    return -1;
129
130
131  /* This is a catchall register read routine that allows reading of
132     ANY of the registers on the PCM-MIO. It is used primarily for
133     retreiving control and access values in the hardware.
134   */
135
136  offset_val = offset & 0xff;
137  byte_val = inb(base_port + offset_val);
138  return (byte_val & 0xff);
139}
140
141///////////////////////////////////////////////////////////////////////////////
142//
143//    MIO_WRITE_REG
144//
145//////////////////////////////////////////////////////////////////////////////
146
147int mio_write_reg(int offset, unsigned char value)
148{
149  unsigned char byte_val;
150  unsigned char offset_val;
151
152  mio_error_code = MIO_SUCCESS;
153
154  if (check_handle())   /* Check for chip available */
155    return -1;
156
157  /* This function like the previous allow unlimited
158     write access to ALL of the registers on the PCM-MIO
159   */
160
161  offset_val = offset & 0xff;
162  byte_val = value;
163  outb(byte_val, base_port + offset_val);
164 
165  return 0;
166}
167
168
169///////////////////////////////////////////////////////////////////////////////
170//
171//    WRITE_DIO_BYTE
172//
173//////////////////////////////////////////////////////////////////////////////
174
175int write_dio_byte(int offset, unsigned char value)
176{
177  unsigned char byte_val;
178  unsigned char offset_val;
179
180  mio_error_code = MIO_SUCCESS;
181
182  if (check_handle())   /* Check for chip available */
183    return -1;
184
185  /* All bit operations for the DIO are handled at this level
186     and we need the driver to allow access to the actual
187     DIO registers to update the value.
188  */
189
190  offset_val = offset & 0xff;
191  byte_val = value;
192  outb(byte_val, base_port + 0x10 + offset_val);
193
194  return 0;
195}
196
197
198///////////////////////////////////////////////////////////////////////////////
199//
200//    WRITE_DAC_COMMAND
201//
202//////////////////////////////////////////////////////////////////////////////
203
204int write_dac_command(int dac_num,unsigned char value)
205{
206  unsigned char  byte_val;
207  unsigned char  offset_val;
208
209  mio_error_code = MIO_SUCCESS;
210
211  if (check_handle())   /* Check for chip available */
212    return -1;
213
214  byte_val = dac_num & 0xff;            /* This is the DAC number */
215  offset_val = value;                   /* This is the data value */
216  if (byte_val)
217    outb(offset_val,base_port + 0x0e);
218  else
219    outb(offset_val,base_port + 0x0a);
220
221  return 0;
222}
223
224///////////////////////////////////////////////////////////////////////////////
225//
226//    WRITE_ADC_COMMAND
227//
228//////////////////////////////////////////////////////////////////////////////
229
230int write_adc_command(int adc_num,unsigned char value)
231{
232  unsigned char byte_val;
233  unsigned char offset_val;
234
235  mio_error_code = MIO_SUCCESS;
236
237  if (check_handle())   /* Check for chip available */
238    return -1;
239
240  byte_val = adc_num & 0xff;            /* This is the ADC number */
241  offset_val = value;                   /* This is the data value */
242
243  if(byte_val)
244    outb(offset_val,base_port + 0x06);
245  else
246    outb(offset_val,base_port + 0x02);
247  return 0;
248}
249
250///////////////////////////////////////////////////////////////////////////////
251//
252//    WRITE_DAC_DATA
253//
254//////////////////////////////////////////////////////////////////////////////
255
256int write_dac_data(int dac_num, unsigned short value)
257{
258  unsigned short word_val;
259  unsigned char byte_val;
260
261  mio_error_code = MIO_SUCCESS;
262
263  if (check_handle())   /* Check for chip available */
264    return -1;
265
266  byte_val = dac_num;
267  word_val = value;
268
269  if(byte_val)          /* DAC 1 */
270    outw(word_val,base_port+0x0c);
271  else
272    outw(word_val,base_port+8);
273 
274  return 0;
275}
276
277///////////////////////////////////////////////////////////////////////////////
278//
279//    DAC_READ_STATUS
280//
281//////////////////////////////////////////////////////////////////////////////
282
283unsigned char dac_read_status(int dac_num)
284{
285  mio_error_code = MIO_SUCCESS;
286
287  if (check_handle())   /* Check for chip available */
288    return -1;
289
290  if (dac_num)
291    return inb(base_port + 0x0f);
292
293  return inb(base_port + 0x0b);
294}
295
296///////////////////////////////////////////////////////////////////////////////
297//
298//    ADC_READ_STATUS
299//
300//////////////////////////////////////////////////////////////////////////////
301
302unsigned char adc_read_status(int adc_num)
303{
304  mio_error_code = MIO_SUCCESS;
305
306  if (check_handle())   /* Check for chip available */
307    return -1;
308
309  if (adc_num)
310    return inb(base_port + 7);
311  return inb(base_port + 3);
312}
313
314///////////////////////////////////////////////////////////////////////////////
315//
316//    ADC_READ_CONVERSION_DATA
317//
318//////////////////////////////////////////////////////////////////////////////
319
320unsigned short adc_read_conversion_data(int channel)
321{
322  int adc_num;
323
324  mio_error_code = MIO_SUCCESS;
325
326  if (check_handle())   /* Check for chip available */
327    return -1;
328
329  if (channel > 7)
330    adc_num = 1;
331  else
332    adc_num = 0;
333
334  if (adc_num)
335    return inw(base_port + 4);
336
337  return inw(base_port);
338}
339
340
341int dio_get_int_with_timestamp(
342  unsigned long long *timestamp
343)
344{
345  mio_error_code = MIO_SUCCESS;
346
347  if (check_handle())   /* Check for chip available */
348    return -1;
349
350  return get_buffered_int(timestamp) & 0xff;
351}
352
353int dio_get_int(void)
354{
355  mio_error_code = MIO_SUCCESS;
356
357  return dio_get_int_with_timestamp(NULL);
358}
359
360int wait_adc_int_with_timeout(int adc_num, int milliseconds)
361{
362  int sc;
363
364  mio_error_code = MIO_SUCCESS;
365
366  if (check_handle())   /* Check for chip available */
367    return -1;
368
369  if (adc_num) {
370    sc = interruptible_sleep_on(&wq_a2d_1, milliseconds);
371  } else {
372    sc = interruptible_sleep_on(&wq_a2d_2, milliseconds);
373  }
374
375  return sc;
376}
377
378int wait_adc_int(int adc_num)
379{
380  return wait_adc_int_with_timeout(adc_num, 0);
381}
382
383int wait_dac_int_with_timeout(int dac_num, int milliseconds)
384{
385  int sc;
386
387  mio_error_code = MIO_SUCCESS;
388
389  if (check_handle())   /* Check for chip available */
390    return -1;
391
392  if (dac_num) {
393    sc = interruptible_sleep_on(&wq_dac_1, milliseconds);
394  } else {
395    sc = interruptible_sleep_on(&wq_dac_2, milliseconds);
396  }
397
398  return sc;
399}
400
401int wait_dac_int(int dac_num)
402{
403  return wait_dac_int_with_timeout(dac_num, 0);
404}
405
406int wait_dio_int_with_timestamp(
407  int                 milliseconds,
408  unsigned long long *timestamp
409)
410{
411  rtems_status_code  rc;
412  din_message_t      din;
413  size_t             received;
414
415  mio_error_code = MIO_SUCCESS;
416
417  if (check_handle())   /* Check for chip available */
418    return -1;
419
420  rc = rtems_message_queue_receive(
421    wq_dio,
422    &din,
423    &received,
424    RTEMS_DEFAULT_OPTIONS,
425    RTEMS_MILLISECONDS_TO_TICKS(milliseconds)
426  );
427  if ( rc == RTEMS_UNSATISFIED ) {
428    mio_error_code = MIO_TIMEOUT_ERROR;
429    return -1;
430  }
431
432  if ( rc == RTEMS_TIMEOUT ) {
433    mio_error_code = MIO_READ_DATA_FAILURE;
434    return -1;
435  }
436
437  if ( rc != RTEMS_SUCCESSFUL ) {
438    printk( "wait_dio_int_with_timestamp - error %d\n", rc );
439    exit( 0 );
440  }
441
442  if (timestamp)
443    *timestamp = din.timestamp;
444  return din.pin;
445}
446
447int wait_dio_int_with_timeout(int milliseconds)
448{
449  return wait_dio_int_with_timestamp(milliseconds, NULL);
450}
451
452int wait_dio_int(void)
453{
454  return wait_dio_int_with_timestamp(0, NULL);
455}
456
457static int handle = 0; /* XXX move to lower */
458
459int check_handle(void)
460{
461  if (handle > 0)  /* If it's already a valid handle */
462    return 0;
463
464  if (handle == -1)  /* If it's already been tried */
465  {
466    mio_error_code = MIO_OPEN_ERROR;
467    sprintf(mio_error_string,"MIO - Unable to open device PCMMIO");
468    return -1;
469  }
470
471  /*
472   * 0  ==> not initialized
473   * 1+ ==> valid file handle, thus initialized
474   * -1 ==> already attempted to open
475   */
476  handle = 1;
477  return 0;
478
479  /* if an error happens, go here */
480  mio_error_code = MIO_OPEN_ERROR;
481  sprintf(mio_error_string,"MIO - Unable to open device PCMMIO");
482  handle = -1;
483  return -1;
484}
485
486/*
487 *  RTEMS barrier create helper
488 */
489void pcmmio_barrier_create(
490  rtems_name  name,
491  rtems_id   *id
492)
493{
494  rtems_status_code rc;
495
496  rc = rtems_barrier_create( name, RTEMS_BARRIER_MANUAL_RELEASE, 0, id );
497  if ( rc == RTEMS_SUCCESSFUL )
498    return;
499
500 printk( "Unable to create PCMMIO Barrier\n" );
501 exit(1);
502}
503
504/*
505 *  RTEMS barrier create helper
506 */
507void pcmmio_din_queue_create(
508  rtems_name  name,
509  rtems_id   *id
510)
511{
512  rtems_status_code rc;
513
514  rc = rtems_message_queue_create(
515    name,
516    MAXIMUM_BUFFERED_DISCRETE_INTERRUPTS,
517    sizeof(din_message_t),
518    RTEMS_DEFAULT_ATTRIBUTES,
519    id
520  );
521  if ( rc == RTEMS_SUCCESSFUL )
522    return;
523
524  printk( "Unable to create PCMMIO DIN IRQ Message Queue\n" );
525  exit(1);
526}
527
528int interruptible_sleep_on(
529  rtems_id *id,
530  int       milliseconds
531)
532{
533  rtems_status_code rc;
534
535  rc = rtems_barrier_wait(*id, RTEMS_MILLISECONDS_TO_TICKS(milliseconds));
536  if ( rc == RTEMS_SUCCESSFUL )
537    return 0;
538  return -1;
539}
540
541void wake_up_interruptible(
542  rtems_id *id
543)
544{
545  rtems_status_code rc;
546  uint32_t          unblocked;
547
548  rc = rtems_barrier_release(*id, &unblocked);
549}
550
551/*
552 *  RTEMS specific interrupt handler
553 */
554#include <bsp/irq.h>
555
556void common_handler(void);
557
558void pcmmio_irq_handler(
559  rtems_irq_hdl_param param
560)
561{
562  common_handler();
563}
564
565static void pcmmio_irq_disable(const rtems_irq_connect_data *irq)
566{
567  BSP_irq_disable_at_i8259s(irq->name);
568}
569static void pcmmio_irq_enable(const rtems_irq_connect_data *irq)
570{
571  BSP_irq_enable_at_i8259s(irq->name);
572}
573
574static int pcmmio_irq_is_on(const rtems_irq_connect_data *irq)
575{
576  return BSP_irq_enabled_at_i8259s( irq->name );
577}
578
579rtems_irq_connect_data pcmmio_irq = {
580  0,                            // name
581  pcmmio_irq_handler,           // handler
582  NULL,                         // parameter
583  pcmmio_irq_enable,            // enable IRQ
584  pcmmio_irq_disable,           // disable IRQ
585  pcmmio_irq_is_on,             // is IRQ enabled
586};
587
588/* from pcmmio.c - GNU/Linux driver */
589void init_io(unsigned short io_address)
590{
591  int x;
592  unsigned short port;
593
594  /* save the address for later use */
595  port = io_address + 0X10;
596
597  /* Clear all of the I/O ports. This also makes them inputs */
598  for(x=0; x < 7; x++)
599    outb(0,port+x);
600
601  /* Set page 2 access, for interrupt enables */
602  outb(0x80,port+7);
603
604  /* Clear all interrupt enables */
605  outb(0,port+8);
606  outb(0,port+9);
607  outb(0,port+0x0a);
608
609  /* Restore page 0 register access */
610  outb(0,port+7);
611}
612
613/*
614 * RTEMS specific initialization routine
615 */
616void pcmmio_initialize(
617  unsigned short _base_port,
618  unsigned short _irq
619)
620{
621  /* hardware configuration information */
622  base_port                    = _base_port;
623  irq                          = _irq;
624  pcmmio_dio_missed_interrupts = 0;
625
626  /* Create RTEMS Objects */
627  pcmmio_barrier_create( rtems_build_name( 'a', '2', 'd', '1' ), &wq_a2d_1 );
628  pcmmio_barrier_create( rtems_build_name( 'd', 'a', 'c', '1' ), &wq_dac_1 );
629  pcmmio_barrier_create( rtems_build_name( 'd', 'a', 'c', '2' ), &wq_dac_2 );
630  pcmmio_din_queue_create( rtems_build_name( 'd', 'i', 'o', ' ' ), &wq_dio );
631
632  if ( base_port )
633    init_io( base_port );
634
635  /* install IRQ handler */
636  if ( base_port && irq ) {
637    int status = 0;
638    pcmmio_irq.name = irq;
639    #if defined(BSP_SHARED_HANDLER_SUPPORT)
640      printk( "PCMMIO Installing IRQ handler as shared\n" );
641      status = BSP_install_rtems_shared_irq_handler( &pcmmio_irq );
642    #else
643      printk( "PCMMIO Installing IRQ handler as non-shared\n" );
644      status = BSP_install_rtems_irq_handler( &pcmmio_irq );
645    #endif
646    if ( !status ) {
647      printk("Error installing PCMMIO interrupt handler! status=%d\n", status );
648    }
649  }
650}
651
652#include <libcpu/cpuModel.h> /* for rdtsc */
653
654/*
655 *  From this point down, we should be able to share easily with the Linux
656 *  driver but I haven't gone to the trouble to do surgery on it.  I have
657 *  no way to test it.
658 */
659
660/* real copy is in mio_io.c */
661extern unsigned char adc2_port_image;
662
663/* This is the common interrupt handler. It is called by the
664 * actual hardware ISR.
665 */
666
667void common_handler(void)
668{
669  unsigned char status;
670  unsigned char int_num;
671
672  /* Read the interrupt ID register from ADC2 */
673
674  adc2_port_image = adc2_port_image | 0x20;
675  outb(adc2_port_image,base_port + 0x0f);
676
677  status = inb(base_port + 0x0f);
678  if (status & 1) {
679    /* Clear ADC1 interrupt */
680    inb(base_port+1);      /* Clear interrupt */
681
682    /* Wake up any holding processes */
683    wake_up_interruptible(&wq_a2d_1);
684  }
685
686  if (status & 2) {
687    /* Clear ADC1 interrupt */
688    inb(base_port+5);      /* Clear interrupt */
689
690    /* Wake up anybody waiting for ADC1 */
691    wake_up_interruptible(&wq_a2d_2);
692  }
693
694  if (status & 4) {
695    /* Clear DAC1 interrupt */
696    inb(base_port+9);    /* Clear interrupt */
697
698    /* Wake up if you're waiting on DAC1 */
699    wake_up_interruptible(&wq_dac_1);
700  }
701
702  if (status & 8) {
703
704    /* DIO interrupt. Find out which bit */
705    while ((int_num = get_int()) != 0) {
706      rtems_status_code  rc;
707      din_message_t      din;
708
709      din.timestamp = rdtsc();
710      din.pin       = int_num;
711
712      rc = rtems_message_queue_send( wq_dio, &din, sizeof(din_message_t) );
713      if ( rc != RTEMS_SUCCESSFUL ) {
714        pcmmio_dio_missed_interrupts++;
715        #ifdef DEBUG
716          printk("<1>Missed DIO interrupt\n" );
717        #endif
718     }
719     #ifdef DEBUG
720       printk("<1>Buffering DIO interrupt on bit %d\n",int_num);
721     #endif
722
723      /* Clear the interrupt */
724      clr_int(int_num);
725    }
726  }
727
728  if (status & 0x10) {
729    /* Clear DAC2 Interrupt */
730    inb(base_port+0x0d);    /* Clear interrupt */
731
732    /* Wake up DAC2 holding processes */
733    wake_up_interruptible(&wq_dac_2);
734  }
735
736  /* Reset the access to the interrupt ID register */
737  adc2_port_image = adc2_port_image & 0xdf;
738  outb(adc2_port_image,base_port+0x0f);
739}
740
741
742void clr_int(int bit_number)
743{
744  unsigned short port;
745  unsigned short temp;
746  unsigned short mask;
747  unsigned short dio_port;
748
749  dio_port = base_port + 0x10;
750
751  /* Also adjust bit number */
752  --bit_number;
753
754  /* Calculate the I/O address based upon bit number */
755  port = (bit_number / 8) + dio_port + 8;
756
757  /* Calculate a bit mask based upon the specified bit number */
758  mask = (1 << (bit_number % 8));
759
760  /* Turn on page 2 access */
761  outb(0x80,dio_port+7);
762
763  /* Get the current state of the interrupt enable register */
764  temp = inb(port);
765
766  /* Temporarily clear only our enable. This clears the interrupt */
767  temp = temp & ~mask;    /* Clear the enable for this bit */
768
769  /* Now update the interrupt enable register */
770  outb(temp,port);
771
772  /* Re-enable our interrupt bit */
773  temp = temp | mask;
774  outb(temp,port);
775
776  /* Set access back to page 0 */
777  outb(0x00,dio_port+7);
778}
779
780int get_int(void)
781{
782  int temp;
783  int x;
784  unsigned short dio_port;
785
786  dio_port = base_port + 0x10;
787
788  /* Read the master interrupt pending register,
789           mask off undefined bits */
790  temp = inb(dio_port+6) & 0x07;
791
792  /* If there are no pending interrupts, return 0 */
793  if ((temp & 7) == 0)
794    return 0;
795
796  /* There is something pending, now we need to identify it */
797
798  /* Set access to page 3 for interrupt id register */
799  outb(0xc0, dio_port + 7);
800
801  /* Read the interrupt ID register for port 0 */
802  temp = inb(dio_port+8);
803
804  /* See if any bit set, if so return the bit number */
805  if (temp != 0) {
806    for (x=0; x<=7; x++) {
807      if (temp & (1 << x)) {
808        outb(0,dio_port+7);
809        return(x+1);
810       }
811    }
812  }
813
814  /* None in port 0, read port 1 interrupt ID register */
815  temp = inb(dio_port+9);
816
817  /* See if any bit set, if so return the bit number */
818  if (temp != 0) {
819    for (x=0; x<=7; x++) {
820      if (temp & (1 << x)) {
821        outb(0,dio_port+7);
822        return(x+9);
823      }
824    }
825  }
826
827  /* Lastly, read the status of port 2 interrupt ID register */
828  temp = inb(dio_port+0x0a);
829
830  /* If any pending, return the appropriate bit number */
831  if (temp != 0) {
832    for (x=0; x<=7; x++) {
833      if (temp & (1 << x)) {
834         outb(0,dio_port+7);
835         return(x+17);
836      }
837    }
838  }
839
840  /* We should never get here unless the hardware is seriously
841     misbehaving, but just to be sure, we'll turn the page access
842     back to 0 and return a 0 for no interrupt found
843  */
844  outb(0,dio_port+7);
845  return 0;
846}
847
848void flush_buffered_ints(void)
849{
850  rtems_status_code  rc;
851  size_t             flushed;
852
853  rc = rtems_message_queue_flush( wq_dio, &flushed );
854  if ( rc != RTEMS_SUCCESSFUL ) {
855    printk( "flushed_buffered_int - error %d\n", rc );
856    exit( 0 );
857  }
858}
859
860int get_buffered_int(
861  unsigned long long *timestamp
862)
863{
864  rtems_status_code  rc;
865  din_message_t      din;
866  int                line;
867  size_t             received;
868
869  if (irq == 0) {
870    line = get_int();
871    if (line)
872      clr_int(line);
873    return line;
874  }
875
876  rc = rtems_message_queue_receive(
877    wq_dio,
878    &din,
879    &received,
880    RTEMS_NO_WAIT,
881    0
882  );
883  if ( rc == RTEMS_UNSATISFIED )
884    return 0;
885
886  if ( rc != RTEMS_SUCCESSFUL ) {
887    printk( "get_buffered_int - error %d\n", rc );
888    exit( 0 );
889  }
890
891  if (timestamp)
892    *timestamp = din.timestamp;
893  return din.pin;
894}
895
896int dio_get_missed_interrupts(void)
897{
898  int isrs;
899
900  isrs = pcmmio_dio_missed_interrupts;
901
902  pcmmio_dio_missed_interrupts = 0;
903
904  return isrs;
905}
Note: See TracBrowser for help on using the repository browser.