Ignore:
Timestamp:
Sep 19, 2012, 10:52:43 AM (12 years ago)
Author:
alain
Message:

Introducing support for Network controller

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/sys/drivers.c

    r216 r218  
    2424// - NB_TTYS   
    2525//
    26 // The following virtual base addresses must be defined in the giet.ld file:
     26// The following virtual base addresses must be defined in the giet_vsegs.ld file:
    2727// - seg_icu_base
    2828// - seg_tim_base
     
    3232// - seg_fbf_base
    3333// - seg_ioc_base
     34// - seg_nic_base
    3435// As some peripherals can be replicated in the clusters (ICU, TIMER, DMA)
    3536// These addresses must be completed by an offset depending on the cluster index
     
    713714//////////////////////////////////////////////////////////////////////////////////
    714715
    715 //+1: for the case where the NB_DMAS_MAX == 0
    716716#if NB_DMAS_MAX > 0
    717717in_unckdata unsigned int                        _dma_lock[NB_DMAS_MAX * NB_CLUSTERS]
    718                                        = { [0 ... ((NB_DMAS_MAX) * NB_CLUSTERS)-1] = 0 };
     718                                       = { [0 ... (NB_DMAS_MAX * NB_CLUSTERS)-1] = 0 };
    719719
    720720in_unckdata volatile unsigned int       _dma_done[NB_DMAS_MAX * NB_CLUSTERS]
     
    749749#endif
    750750}
     751
    751752//////////////////////////////////////////////////////////////////////////////////
    752753// _dma_get_status()
     
    773774
    774775//////////////////////////////////////////////////////////////////////////////////
    775 //      VciFrameBuffer driver
    776 //////////////////////////////////////////////////////////////////////////////////
    777 // The vci_frame_buffer device can be accessed directly by software with memcpy(),
    778 // or it can be accessed through a multi-channels DMA component:
    779 // 
    780 // The '_fb_sync_write' and '_fb_sync_read' functions use a memcpy strategy to
    781 // implement the transfer between a data buffer (user space) and the frame
    782 // buffer (kernel space). They are blocking until completion of the transfer.
    783 //
    784 // The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the DMA
    785 // controlers (distributed in the clusters) to transfer data
    786 // between the user buffer and the frame buffer. A  DMA channel is
    787 // allocated to each task requesting it in the mapping_info data structure.
    788 //////////////////////////////////////////////////////////////////////////////////
    789 
    790 //////////////////////////////////////////////////////////////////////////////////
    791 // _fb_sync_write()
    792 // Transfer data from an memory buffer to the frame_buffer device using
    793 // a memcpy. The source memory buffer must be in user address space.
    794 // - offset : offset (in bytes) in the frame buffer.
    795 // - buffer : base address of the memory buffer.
    796 // - length : number of bytes to be transfered.
    797 // Returns 0 if success, > 0 if error.
    798 //////////////////////////////////////////////////////////////////////////////////
    799 unsigned int _fb_sync_write( unsigned int       offset,
    800                              const void*        buffer,
    801                              unsigned int       length )
    802 {
    803 
    804     // buffer must be mapped in user space
    805     if ( ((unsigned int)buffer + length ) >= 0x80000000 )
    806     {
    807         return 1;
    808     }
    809     else
    810     {
    811         unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
    812         memcpy((void*)fb_address, (void*)buffer, length);
    813         return 0;
    814     }
    815 }
    816 
    817 //////////////////////////////////////////////////////////////////////////////////
    818 // _fb_sync_read()
    819 // Transfer data from the frame_buffer device to a memory buffer using
    820 // a memcpy. The destination memory buffer must be in user address space.
    821 // - offset : offset (in bytes) in the frame buffer.
    822 // - buffer : base address of the memory buffer.
    823 // - length : number of bytes to be transfered.
    824 // Returns 0 if success, > 0 if error.
    825 //////////////////////////////////////////////////////////////////////////////////
    826 unsigned int _fb_sync_read( unsigned int        offset,
    827                             const void*         buffer,
    828                             unsigned int        length )
    829 {
    830     // buffer must be mapped in user space
    831     if ( ((unsigned int)buffer + length ) >= 0x80000000 )
    832     {
    833         return 1;
    834     }
    835     else
    836     {
    837         unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
    838         memcpy((void*)buffer, (void*)fb_address, length);
    839         return 0;
    840     }
    841 }
    842 
    843 //////////////////////////////////////////////////////////////////////////////////
    844 // _fb_dma_access()
    845 // Transfer data between a user buffer and the frame_buffer using DMA.
    846 // - to_user    : from frame buffer to user buffer when true.
    847 // - offset     : offset (in bytes) in the frame buffer.
    848 // - user_vaddr : virtual base address of the memory buffer.
    849 // - length     : number of bytes to be transfered.
     776// _dma_transfer()
     777// Transfer data between a user buffer and a device buffer using DMA.
     778// Two devices types are supported: Frame Buffer if dev_type == 0
     779//                                  Multi-Nic if dev_type != 0
     780// Arguments are:
     781// - dev_type     : device type.
     782// - to_user      : from  device buffer to user buffer when true.
     783// - offset       : offset (in bytes) in the device buffer.
     784// - user_vaddr   : virtual base address of the user buffer.
     785// - length       : number of bytes to be transfered.
     786//
     787// The DMA channel is obtained from task context (CTX_FBDMA_ID / CTX_NIDMA_ID.
    850788// The user buffer must be mapped in user address space and word-aligned.
    851789// The user buffer length must be multiple of 4 bytes.
    852 // Me must compute the physical base addresses for both the frame buffer
     790// Me must compute the physical base addresses for both the device buffer
    853791// and the user buffer before programming the DMA transfer.
    854792// The GIET being fully static, we don't need to split the transfer in 4 Kbytes
     
    856794// Returns 0 if success, > 0 if error.
    857795//////////////////////////////////////////////////////////////////////////////////
    858 unsigned int _fb_dma_access( unsigned int       to_user,
     796unsigned int _dma_transfer(  unsigned int   dev_type,
     797                             unsigned int   to_user,
    859798                             unsigned int   offset,
    860799                             unsigned int   user_vaddr,
     
    862801{
    863802#if NB_DMAS_MAX > 0
    864     unsigned int        ko;                             // unsuccessfull V2P translation
    865     unsigned int        flags;                  // protection flags
    866     unsigned int        ppn;                    // physical page number
    867     unsigned int    user_pbase;         // user buffer pbase address
    868     unsigned int    fb_pbase;           // frame buffer pbase address
     803    unsigned int        ko;                                     // unsuccessfull V2P translation
     804    unsigned int        flags;                          // protection flags
     805    unsigned int        ppn;                            // physical page number
     806    unsigned int    user_pbase;                 // user buffer pbase address
     807    unsigned int    device_pbase;                       // frame buffer pbase address
     808    unsigned int        device_vaddr;                   // device buffer vbase address
     809
     810    // check user buffer address and length alignment
     811    if ( (user_vaddr & 0x3) || (length & 0x3) )
     812    {
     813        _get_lock(&_tty_put_lock);
     814        _puts("\n[GIET ERROR] in _dma_transfer : user buffer not word aligned\n");
     815        _release_lock(&_tty_put_lock);
     816        return 1;
     817    }
    869818
    870819    // get DMA channel and compute DMA vbase address
    871820    unsigned int        task_id    = _get_current_task_id();
    872     unsigned int        dma_id     = _get_context_slot( task_id, CTX_FBDMA_ID );
     821    unsigned int    dma_id     = _get_context_slot( task_id, CTX_DMA_ID );
    873822    unsigned int    cluster_id = dma_id / NB_DMAS_MAX;
    874823    unsigned int    loc_id     = dma_id % NB_DMAS_MAX;
    875 
    876     unsigned int*       dma_base   = (unsigned int*)( (char*)&seg_dma_base +
    877                                  (cluster_id * (unsigned)CLUSTER_SIZE) );
    878  
    879     // check user buffer address and length alignment
    880     if ( (user_vaddr & 0x3) || (length & 0x3) )
    881     {
    882         _get_lock(&_tty_put_lock);
    883         _puts("\n[GIET ERROR] in _fbdma_access() : user buffer not word aligned\n");
    884         _release_lock(&_tty_put_lock);
    885         return 1;
    886     }
    887 
    888     // get user space page table virtual address
     824    unsigned int*       dma_base   = (unsigned int*)( (char*)&seg_dma_base +
     825                                    (cluster_id * (unsigned)CLUSTER_SIZE) );
     826
     827    // get page table address
    889828    unsigned int        user_ptab = _get_context_slot( task_id, CTX_PTAB_ID );
    890829
    891     // compute frame buffer pbase address
    892     unsigned int fb_vaddr = (unsigned int)&seg_fbf_base + offset;
    893 
     830    // get peripheral buffer virtual address
     831    if ( dev_type)  device_vaddr = (unsigned int)&seg_nic_base + offset;
     832    else            device_vaddr = (unsigned int)&seg_fbf_base + offset;
     833
     834    // get device buffer physical address
    894835    ko = _v2p_translate( (page_table_t*)user_ptab,
    895                          (fb_vaddr >> 12),
     836                         (device_vaddr >> 12),
    896837                         &ppn,
    897838                         &flags );
    898     fb_pbase = (ppn << 12) | (fb_vaddr & 0x00000FFF);
    899 
    900839    if ( ko )
    901840    {
    902841        _get_lock(&_tty_put_lock);
    903         _puts("\n[GIET ERROR] in _fbdma_access() : frame buffer unmapped\n");
     842        _puts("\n[GIET ERROR] in _dma_transfer : device buffer unmapped\n");
    904843        _release_lock(&_tty_put_lock);
    905844        return 2;
    906845    }
    907 
    908     // Compute user buffer pbase address
     846    device_pbase = (ppn << 12) | (device_vaddr & 0x00000FFF);
     847
     848    // Compute user buffer physical address
    909849    ko = _v2p_translate( (page_table_t*)user_ptab,
    910850                         (user_vaddr >> 12),
    911851                         &ppn,
    912852                         &flags );
    913     user_pbase = (ppn << 12) | (user_vaddr & 0x00000FFF);
    914 
    915853    if ( ko )
    916854    {
    917855        _get_lock(&_tty_put_lock);
    918         _puts("\n[GIET ERROR] in _fbdma_access() : user buffer unmapped\n");
     856        _puts("\n[GIET ERROR] in _dma_transfer() : user buffer unmapped\n");
    919857        _release_lock(&_tty_put_lock);
    920858        return 3;
     
    923861    {
    924862        _get_lock(&_tty_put_lock);
    925         _puts("[GIET ERROR] in _fbdma_access() : user buffer not in user space\n");
     863        _puts("[GIET ERROR] in _dma_transfer() : user buffer not in user space\n");
    926864        _release_lock(&_tty_put_lock);
    927865        return 4;
     
    930868    {
    931869        _get_lock(&_tty_put_lock);
    932         _puts("\n[GIET ERROR] in _fbdma_access() : user buffer not writable\n");
     870        _puts("\n[GIET ERROR] in _dma_transfer() : user buffer not writable\n");
    933871        _release_lock(&_tty_put_lock);
    934872        return 5;
    935873    }
    936 
    937 
    938 
    939 /*
     874    user_pbase = (ppn << 12) | (user_vaddr & 0x00000FFF);
     875
     876/*  This is a draft for IOMMU support
     877   
    940878    // loop on all virtual pages covering the user buffer
    941879    unsigned int user_vpn_min = user_vaddr >> 12;
     
    987925    // invalidate data cache in case of memory write
    988926    if ( to_user ) _dcache_buf_invalidate( (void*)user_vaddr, length );
    989 
     927   
    990928    // get the lock
    991929    _get_lock( &_dma_lock[dma_id] );
     
    994932    if ( to_user )
    995933    {
    996         dma_base[loc_id*DMA_SPAN + DMA_SRC] = (unsigned int)fb_pbase;
     934        dma_base[loc_id*DMA_SPAN + DMA_SRC] = (unsigned int)device_pbase;
    997935        dma_base[loc_id*DMA_SPAN + DMA_DST] = (unsigned int)user_pbase;
    998936    }
     
    1000938    {
    1001939        dma_base[loc_id*DMA_SPAN + DMA_SRC] = (unsigned int)user_pbase;
    1002         dma_base[loc_id*DMA_SPAN + DMA_DST] = (unsigned int)fb_pbase;
     940        dma_base[loc_id*DMA_SPAN + DMA_DST] = (unsigned int)device_pbase;
    1003941    }
    1004942    dma_base[loc_id*DMA_SPAN + DMA_LEN] = (unsigned int)length;
     
    1007945
    1008946#else //NB_DMAS_MAX == 0
     947
    1009948    return -1;
    1010 #endif
    1011 
     949
     950#endif
     951}  // end _dma_transfer() 
     952
     953//////////////////////////////////////////////////////////////////////////////////
     954// _dma_completed()
     955// This function checks completion of a DMA transfer to or from a peripheral
     956// device (Frame Buffer or Multi-Nic).
     957// As it is a blocking call, the processor is busy waiting.
     958// Returns 0 if success, > 0 if error
     959// (1 == read error / 2 == DMA idle error / 3 == write error)
     960//////////////////////////////////////////////////////////////////////////////////
     961unsigned int _dma_completed()
     962{
     963#if NB_DMAS_MAX > 0
     964    unsigned int    task_id = _get_current_task_id();
     965    unsigned int    dma_id  = _get_context_slot( task_id, CTX_DMA_ID );
     966
     967    // busy waiting with a pseudo random delay between bus access
     968    while (_dma_done[dma_id] == 0)
     969    {
     970        unsigned int delay = (( _proctime() ^ _procid()<<4 ) & 0x3F) + 1;
     971        asm volatile("move  $3,   %0                    \n"
     972                     "loop_nic_completed:               \n"
     973                     "addi  $3, $3, -1              \n"
     974                     "bnez  $3, loop_nic_completed      \n"
     975                     "nop                                       \n"
     976                     :
     977                     : "r"(delay)
     978                     : "$3" );
     979    }
     980   
     981/* draft support for IOMMU
     982    // unmap the buffer from IOMMU page table if IOMMU is activated
     983    if ( GIET_IOMMU_ACTIVE )
     984    {
     985        unsigned int* iob_address = (unsigned int*)&seg_iob_base;
     986
     987        unsigned int  ix1         = _dma_iommu_ix1 + dma_id;
     988        unsigned int  ix2;
     989
     990        for ( ix2 = 0 ; ix2 < _dma_iommu_npages[dma_id] ; ix2++ )
     991        {
     992            // unmap the page in IOMMU page table
     993            _iommu_inval_pte2( ix1,             // PT1 index
     994                               ix2 );   // PT2 index
     995
     996            // clear IOMMU TLB
     997            iob_address[IOB_INVAL_PTE] = (ix1 << 21) | (ix2 << 12);
     998        }
     999    }
     1000*/
     1001
     1002    // reset synchronization variables
     1003    _dma_lock[dma_id] = 0;
     1004    _dma_done[dma_id] = 0;
     1005
     1006    return _dma_status[dma_id];
     1007
     1008#else //NB_DMAS_MAX == 0
     1009    return -1;
     1010#endif
     1011}  // end _dma_completed
     1012
     1013//////////////////////////////////////////////////////////////////////////////////
     1014//      VciFrameBuffer driver
     1015//////////////////////////////////////////////////////////////////////////////////
     1016// The vci_frame_buffer device can be accessed directly by software with memcpy(),
     1017// or it can be accessed through a multi-channels DMA component:
     1018// 
     1019// The '_fb_sync_write' and '_fb_sync_read' functions use a memcpy strategy to
     1020// implement the transfer between a data buffer (user space) and the frame
     1021// buffer (kernel space). They are blocking until completion of the transfer.
     1022//
     1023// The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the
     1024// VciMultiDma components (distributed in the clusters) to transfer data
     1025// between the user buffer and the frame buffer. A  FBDMA channel is
     1026// allocated to each task requesting it in the mapping_info data structure.
     1027//////////////////////////////////////////////////////////////////////////////////
     1028
     1029//////////////////////////////////////////////////////////////////////////////////
     1030// _fb_sync_write()
     1031// Transfer data from an memory buffer to the frame_buffer device using a memcpy.
     1032// - offset : offset (in bytes) in the frame buffer.
     1033// - buffer : base address of the memory buffer.
     1034// - length : number of bytes to be transfered.
     1035//////////////////////////////////////////////////////////////////////////////////
     1036unsigned int _fb_sync_write( unsigned int       offset,
     1037                             const void*        buffer,
     1038                             unsigned int       length )
     1039{
     1040    unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
     1041    memcpy((void*)fb_address, (void*)buffer, length);
     1042    return 0;
     1043}
     1044
     1045//////////////////////////////////////////////////////////////////////////////////
     1046// _fb_sync_read()
     1047// Transfer data from the frame_buffer device to a memory buffer using a memcpy.
     1048// - offset : offset (in bytes) in the frame buffer.
     1049// - buffer : base address of the memory buffer.
     1050// - length : number of bytes to be transfered.
     1051//////////////////////////////////////////////////////////////////////////////////
     1052unsigned int _fb_sync_read( unsigned int        offset,
     1053                            const void*         buffer,
     1054                            unsigned int        length )
     1055{
     1056    unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
     1057    memcpy((void*)buffer, (void*)fb_address, length);
     1058    return 0;
     1059}
     1060
    10121061//////////////////////////////////////////////////////////////////////////////////
    10131062// _fb_write()
     
    10191068//////////////////////////////////////////////////////////////////////////////////
    10201069unsigned int _fb_write( unsigned int    offset,
    1021                         const void*             buffer,
     1070                        const    void*  buffer,
    10221071                        unsigned int    length )
    10231072{
    1024     return _fb_dma_access( 0,                                           // write to frame buffer
    1025                            offset,
    1026                            (unsigned int)buffer,
    1027                            length );   
     1073    return _dma_transfer( 0,                                            // frame buffer
     1074                          0,                                            // write
     1075                                  offset,
     1076                                  (unsigned int)buffer,
     1077                                  length );     
    10281078}
    10291079
     
    10401090                       unsigned int     length )
    10411091{
    1042     return _fb_dma_access( 1,                                           // read from frame buffer
    1043                            offset,
    1044                            (unsigned int)buffer,
    1045                            length );   
     1092    return _dma_transfer( 0,                                            // frame buffer
     1093                          1,                                            // read
     1094                                  offset,
     1095                                  (unsigned int)buffer,
     1096                                  length );     
    10461097}
    10471098
     
    10551106unsigned int _fb_completed()
    10561107{
    1057 #if NB_DMAS_MAX > 0
    1058     unsigned int task_id = _get_current_task_id();
    1059     unsigned int dma_id  = _get_context_slot( task_id, CTX_FBDMA_ID );
    1060 
    1061     // busy waiting with a pseudo random delay between bus access
    1062     while (_dma_done[dma_id] == 0)
    1063     {
    1064             unsigned int i;
    1065         unsigned int delay = ( _proctime() ^ _procid()<<4 ) & 0xFF;
    1066         for (i = 0; i < delay; i++)
    1067             asm volatile("nop");
    1068     }
    1069    
    1070     // unmap the buffer from IOMMU page table if IOMMU is activated
    1071     if ( IOMMU_ACTIVE )
    1072     {
    1073         unsigned int* iob_address = (unsigned int*) &seg_iob_base;
    1074 
    1075         unsigned int  ix1         = _dma_iommu_ix1 + dma_id;
    1076         unsigned int  ix2;
    1077 
    1078         for ( ix2 = 0 ; ix2 < _dma_iommu_npages[dma_id] ; ix2++ )
    1079         {
    1080             // unmap the page in IOMMU page table
    1081             _iommu_inval_pte2( ix1,             // PT1 index
    1082                                ix2 );   // PT2 index
    1083 
    1084             // clear IOMMU TLB
    1085             iob_address[IOB_INVAL_PTE] = (ix1 << 21) | (ix2 << 12);
    1086         }
    1087     }
    1088 
    1089     // reset synchronization variables
    1090     _dma_lock[dma_id] = 0;
    1091     _dma_done[dma_id] = 0;
    1092 
    1093     return _dma_status[dma_id];
    1094 
    1095 #else //NB_DMAS_MAX == 0
    1096 
    1097     return -1;
    1098 
    1099 #endif
    1100 }
    1101 
     1108    return _dma_completed();
     1109}
     1110
     1111//////////////////////////////////////////////////////////////////////////////////
     1112//      VciMultiNic driver
     1113//////////////////////////////////////////////////////////////////////////////////
     1114// The VciMultiNic device can be accessed directly by software with memcpy(),
     1115// or it can be accessed through a multi-channels DMA component:
     1116// 
     1117// The '_nic_sync_write' and '_nic_sync_read' functions use a memcpy strategy to
     1118// implement the transfer between a data buffer (user space) and the NIC
     1119// buffer (kernel space). They are blocking until completion of the transfer.
     1120//
     1121// The '_nic_write()', '_nic_read()' and '_nic_completed()' functions use the
     1122// VciMultiDma components (distributed in the clusters) to transfer data
     1123// between the user buffer and the NIC. A  NIDMA channel is allocated to each
     1124// task requesting it in the mapping_info data structure.
     1125//////////////////////////////////////////////////////////////////////////////////
     1126
     1127//////////////////////////////////////////////////////////////////////////////////
     1128// _nic_sync_write()
     1129// Transfer data from an memory buffer to the NIC device using a memcpy.
     1130// - offset : offset (in bytes) in the frame buffer.
     1131// - buffer : base address of the memory buffer.
     1132// - length : number of bytes to be transfered.
     1133//////////////////////////////////////////////////////////////////////////////////
     1134unsigned int _nic_sync_write( unsigned int      offset,
     1135                              const void*       buffer,
     1136                              unsigned int      length )
     1137{
     1138    unsigned char *nic_address = (unsigned char*)&seg_nic_base + offset;
     1139    memcpy((void*)nic_address, (void*)buffer, length);
     1140    return 0;
     1141}
     1142
     1143//////////////////////////////////////////////////////////////////////////////////
     1144// _nic_sync_read()
     1145// Transfer data from the NIC device to a memory buffer using a memcpy.
     1146// - offset : offset (in bytes) in the frame buffer.
     1147// - buffer : base address of the memory buffer.
     1148// - length : number of bytes to be transfered.
     1149//////////////////////////////////////////////////////////////////////////////////
     1150unsigned int _nic_sync_read( unsigned int       offset,
     1151                             const void*        buffer,
     1152                             unsigned int       length )
     1153{
     1154    unsigned char *nic_address = (unsigned char*)&seg_nic_base + offset;
     1155    memcpy((void*)buffer, (void*)nic_address, length);
     1156    return 0;
     1157}
     1158
     1159//////////////////////////////////////////////////////////////////////////////////
     1160// _nic_write()
     1161// Transfer data from a memory buffer to the NIC device using  DMA.
     1162// - offset : offset (in bytes) in the frame buffer.
     1163// - buffer : base address of the memory buffer.
     1164// - length : number of bytes to be transfered.
     1165// Returns 0 if success, > 0 if error.
     1166//////////////////////////////////////////////////////////////////////////////////
     1167unsigned int _nic_write( unsigned int   offset,
     1168                         const void*    buffer,
     1169                         unsigned int   length )
     1170{
     1171    return _dma_transfer( 1,            // NIC
     1172                          0,                    // write
     1173                                      offset,
     1174                                      (unsigned int)buffer,
     1175                                      length );
     1176}
     1177
     1178//////////////////////////////////////////////////////////////////////////////////
     1179// _nic_read()
     1180// Transfer data from the NIC device to a memory buffer using  DMA.
     1181// - offset : offset (in bytes) in the frame buffer.
     1182// - buffer : base address of the memory buffer.
     1183// - length : number of bytes to be transfered.
     1184// Returns 0 if success, > 0 if error.
     1185//////////////////////////////////////////////////////////////////////////////////
     1186unsigned int _nic_read( unsigned int    offset,
     1187                        const void*             buffer,
     1188                        unsigned int    length )
     1189{
     1190    return _dma_transfer( 1,            // NIC
     1191                          1,                    // read
     1192                          offset,
     1193                                      (unsigned int)buffer,
     1194                                      length );
     1195}
     1196
     1197//////////////////////////////////////////////////////////////////////////////////
     1198// _nic_completed()
     1199// This function checks completion of a DMA transfer to or fom a NIC channel.
     1200// As it is a blocking call, the processor is busy waiting.
     1201// Returns 0 if success, > 0 if error
     1202// (1 == read error / 2 == DMA idle error / 3 == write error)
     1203//////////////////////////////////////////////////////////////////////////////////
     1204unsigned int _nic_completed()
     1205{
     1206    return _dma_completed();
     1207}
     1208
Note: See TracChangeset for help on using the changeset viewer.