Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

dma.c

Go to the documentation of this file.
00001 /*
00002  Filename: dma.c
00003 
00004  This file provides functions needed to access a DMA controller for
00005  local to/from VME bus transfers. The interface
00006  is based on the documentation for the VMEchip2 in the MVME162LX Embedded
00007  Controller Programmer's Reference Guide (MVME162LXPG/D1), with the April 1996 updates. (MVME162LXPG/DIA2) These functions are used within globmem.cc.
00008 
00009  MODIFICATIONS:
00010  18-Jun-1998 WPS created.
00011 
00012  */
00013 
00014 
00015 #include <stdlib.h>             /* malloc(), free() */
00016 #ifdef VXWORKS
00017 #include <vxWorks.h>
00018 #include <logLib.h>             /* logMsg() */
00019 #include <taskLib.h>            /* taskDelay() */
00020 #include <tickLib.h>            /* tickGet() */
00021 #include <usrLib.h>             /* d() */
00022 #endif
00023 
00024 #include "dma.h"
00025 #include "dbg_mem.h"            /* DEBUG_FREE,DEBUG_MALLOC,DEBUG_CALLOC */
00026 
00027 unsigned long DMA_VMEBUS_REQUEST_LEVEL = 0;
00028 
00029 /* DMAC Control Register 1, 2-51 MVME162LX Programmer's Guide */
00030 /* DFAIR=4 (Wait for VME Bus Inactive),  */
00031 /* DRELM=(3-2) (VME Bus Release Mode) { 0=BRx&timer,1=timer,2=BRx,3=BRx|timer} */
00032 /* This variable is OR'd with the DMAC Control Register */
00033 unsigned long MVME162_DMA_CONTROL_OPTIONS = 0;
00034 
00035 /* DMAC Ton/Toff and VMEbus Global Timeout Control Register, 2-59 MVME162LX Programmer's Guide */
00036 /* TIME OFF = (23-21) */
00037 /* TIME_ON = (20-18) */
00038 /* VGTO = (17-16) */
00039 unsigned long MVME162_DMA_TIMEOUT_OPTIONS = 0;
00040 
00041 
00042 
00043 /* DMAC Command Table Format, 2-48 MVME162LX Programmer's Guide */
00044 struct MVME162_DMAC_COMMAND
00045 {
00046   unsigned long control_word;
00047   void *local_bus_address;
00048   void *vme_bus_address;
00049   unsigned long byte_count;
00050   void *next_command;
00051 };
00052 
00053 
00054 struct DMA_ADDR_INFO
00055 {
00056   int board_type;
00057   unsigned long addr;
00058   unsigned long am;
00059   int address_decoder;
00060   int ignore_dma_errors;
00061 };
00062 
00063 void *dma_command_list = 0;
00064 int dma_command_started = 0;
00065 int dma_print_errors = 1;
00066 
00067 void *testDMAVMEAddress = ((void *) 0x4e00000);
00068 long testDMABufSize = 0x4000;
00069 int testDMABoardType = VX_MVME162_BOARD_TYPE;
00070 static char c = 'a';
00071 void *local_data = 0;
00072 struct DMA_ADDR_INFO *testDMAinfo = 0;
00073 int MVME162_DMA_DELAY_COUNT = 1000;
00074 
00075 #define MAX_MVME162_DMAC_COMMANDS (4)
00076 struct MVME162_DMAC_COMMAND
00077   mvme162_dmac_commands_list1[MAX_MVME162_DMAC_COMMANDS];
00078 struct MVME162_DMAC_COMMAND
00079   mvme162_dmac_commands_list2[MAX_MVME162_DMAC_COMMANDS];
00080 struct MVME162_DMAC_COMMAND *mvme162_dmac_commands_list =
00081   mvme162_dmac_commands_list1;
00082 int num_mvme162_dmac_commands = 0;
00083 int startCommandTicks = 0;
00084 
00085 /*  Same arguments as d(), unfortunately d seems to be a shell function we can't call under vxworks5.3.*/
00086 int
00087 displayMemory (void *addr, int nunits, int nwidth)
00088 {
00089   int i;
00090   for (i = 0; i < nunits * nwidth / 16; i++)
00091     {
00092       switch (nwidth)
00093         {
00094         case 4:
00095 #ifdef VXWORKS
00096           logMsg (" %8.8X: %8.8X %8.8X %8.8X %8.8X\n",
00097                   (((unsigned long) addr) + (i * 16)),
00098                   (*(unsigned long *) (((unsigned long) addr) + (i * 16))),
00099                   (*(unsigned long *)
00100                    (((unsigned long) addr) + (i * 16 + 4))),
00101                   (*(unsigned long *)
00102                    (((unsigned long) addr) + (i * 16) + 8)),
00103                   (*(unsigned long *)
00104                    (((unsigned long) addr) + (i * 16) + 12)), 0);
00105 #else
00106           return -1;
00107 #endif
00108           break;
00109 
00110         default:
00111           return -1;
00112         }
00113     }
00114   return 0;
00115 }
00116 
00117 int
00118 setTestDMAData (char c)
00119 {
00120   if (0 == local_data)
00121     {
00122       local_data = (void *) DEBUG_MALLOC (testDMABufSize);
00123     }
00124   memset (local_data, c, testDMABufSize);
00125 }
00126 
00127 int dma_switch = 0;
00128 
00129 int
00130 testDMA ()
00131 {
00132   unsigned long ticks = 0;
00133 #ifdef VXWORKS
00134   ULONG startTicks = tickGet ();
00135 #endif
00136   if (dma_switch)
00137     {
00138       if (mvme162_dmac_commands_list == mvme162_dmac_commands_list1)
00139         {
00140           mvme162_dmac_commands_list = mvme162_dmac_commands_list2;
00141         }
00142       else
00143         {
00144           mvme162_dmac_commands_list = mvme162_dmac_commands_list1;
00145         }
00146     }
00147   printf ("c=%c\n", c);
00148   setTestDMAData (c);
00149   c++;
00150   if (c > 'z')
00151     {
00152       c = 'a';
00153     }
00154 
00155   dma_command_started = 0;
00156 
00157 #ifdef VERBOSE
00158   displayMemory ((void *) 0xfff40030, 8, 4);
00159   displayMemory (mvme162_dmac_commands_list, 8, 4);
00160 #ifdef VXWORKS
00161   logMsg (" getDMAInfo %X %d\n", (int) dma_command_list, dma_command_started,
00162           0, 0, 0, 0);
00163 #endif
00164 #endif
00165   if (0 == testDMAinfo)
00166     {
00167       testDMAinfo =
00168         getDMAInfo (testDMABoardType, ((unsigned long) testDMAVMEAddress));
00169     }
00170   if (0 == testDMAinfo)
00171     {
00172       return -1;
00173     }
00174 #ifdef VERBOSE
00175   displayMemory ((void *) 0xfff40030, 8, 4);
00176   displayMemory (mvme162_dmac_commands_list, 8, 4);
00177 #ifdef VXWORKS
00178   logMsg (" checkForDMADone %X %d\n", (int) dma_command_list,
00179           dma_command_started, 0, 0, 0, 0);
00180 #endif
00181 #endif
00182   taskDelay (1);
00183   taskLock ();
00184   if (!checkForDMADone (testDMAinfo))
00185     {
00186 #ifdef VXWORKS
00187       logMsg (" DMA not Done. %X %d\n", (int) dma_command_list,
00188               dma_command_started, 0, 0, 0, 0);
00189 #endif
00190       displayMemory ((void *) 0xfff40030, 8, 4);
00191       taskUnlock ();
00192       return -1;
00193     }
00194 #ifdef VERBOSE
00195   displayMemory ((void *) 0xfff40030, 8, 4);
00196   displayMemory (mvme162_dmac_commands_list, 8, 4);
00197 #ifdef VXWORKS
00198   logMsg (" DMACLearScheduledTransfersList %X %d\n", (int) dma_command_list,
00199           dma_command_started, 0, 0, 0, 0);
00200 #endif
00201 #endif
00202   if (DMAClearScheduledTransfersList (testDMAinfo) < 0)
00203     {
00204 #ifdef VXWORKS
00205       logMsg (" Can't clear scheduled DMA transfer list. %X %d\n",
00206               (int) dma_command_list, dma_command_started, 0, 0, 0, 0);
00207 #endif
00208       freeDMAInfo (testDMAinfo);
00209       testDMAinfo = 0;
00210       taskUnlock ();
00211       return -1;
00212     }
00213 #ifdef VERBOSE
00214   displayMemory ((void *) 0xfff40030, 8, 4);
00215   displayMemory (mvme162_dmac_commands_list, 8, 4);
00216 #ifdef VXWORKS
00217   logMsg (" DMASheduleLocalToVMETransfer %X %d\n", (int) dma_command_list,
00218           dma_command_started, 0, 0, 0, 0);
00219 #endif
00220 #endif
00221   if (DMAScheduleLocalToVMETransfer
00222       (testDMAinfo, testDMAVMEAddress, local_data, testDMABufSize) < 0)
00223     {
00224 #ifdef VXWORKS
00225       logMsg (" Can't schedule DMA transfer. %X %d\n", (int) dma_command_list,
00226               dma_command_started, 0, 0, 0, 0);
00227 #endif
00228       freeDMAInfo (testDMAinfo);
00229       testDMAinfo = 0;
00230       taskUnlock ();
00231       return -1;
00232     }
00233 #ifdef VERBOSE
00234   displayMemory ((void *) 0xfff40030, 8, 4);
00235   displayMemory (mvme162_dmac_commands_list, 8, 4);
00236 #ifdef VXWORKS
00237   logMsg (" DMAStartTransfers %X %d\n", (int) dma_command_list,
00238           dma_command_started, 0, 0, 0, 0);
00239 #endif
00240 #endif
00241   if (DMAStartTransfers (testDMAinfo) < 0)
00242     {
00243 #ifdef VXWORKS
00244       logMsg (" Can't start DMA transfer. %X %d\n", (int) dma_command_list,
00245               dma_command_started, 0, 0, 0, 0);
00246 #endif
00247       freeDMAInfo (testDMAinfo);
00248       testDMAinfo = 0;
00249       taskUnlock ();
00250       return -1;
00251     }
00252 #ifdef VERBOSE
00253   displayMemory ((void *) 0xfff40030, 8, 4);
00254   displayMemory (mvme162_dmac_commands_list, 8, 4);
00255 #ifdef VXWORKS
00256   logMsg (" checkForDMADone  %X %d\n", (int) dma_command_list,
00257           dma_command_started, 0, 0, 0, 0);
00258 #endif
00259 #endif
00260   while (ticks < 100)
00261     {
00262       switch (checkForDMADone (testDMAinfo))
00263         {
00264         case 0:
00265 #ifdef VERBOSE
00266           displayMemory ((void *) 0xfff40030, 8, 4);
00267           displayMemory (mvme162_dmac_commands_list, 8, 4);
00268 #endif
00269           break;
00270 
00271         case 1:
00272 #ifdef VERBOSE
00273           displayMemory ((void *) 0xfff40030, 8, 4);
00274           displayMemory (mvme162_dmac_commands_list, 8, 4);
00275 #endif
00276           printf ("*((char *)0x%X)=%c\n", testDMAVMEAddress,
00277                   *((char *) testDMAVMEAddress));
00278           taskUnlock ();
00279           return ticks;
00280 
00281         default:
00282           displayMemory ((void *) 0xfff40000, 64, 4);
00283           displayMemory (mvme162_dmac_commands_list, 8, 4);
00284           taskUnlock ();
00285           return -1;
00286         }
00287 #ifdef VXWORKS
00288       ticks = tickGet () - startTicks;
00289 #else
00290       ticks++;
00291 #endif
00292     }
00293 #ifdef VERBOSE
00294   displayMemory ((void *) 0xfff40030, 8, 4);
00295   displayMemory (mvme162_dmac_commands_list, 8, 4);
00296   taskUnlock ();
00297 #ifdef VXWORKS
00298   logMsg ("\ntestDMA finish\n", 0, 0, 0, 0, 0, 0);
00299 #endif
00300 #endif
00301   printf ("*((char *)0x%X)=%c\n", testDMAVMEAddress,
00302           *((char *) testDMAVMEAddress));
00303   return ticks;
00304 }
00305 
00306 unsigned long orig_data = 0;
00307 char orig_data_char;
00308 
00309 int mvme162_dma_init (struct DMA_ADDR_INFO *info);
00310 
00311 struct DMA_ADDR_INFO *
00312 getDMAInfo (int board_type, unsigned long addr)
00313 {
00314   struct DMA_ADDR_INFO *info = 0;
00315   unsigned long vme_bus_enable_control_reg;
00316   unsigned long io_control_reg;
00317   unsigned long a1;
00318   unsigned long enda1;
00319   unsigned long starta1;
00320   int tries = 0;
00321   int addr_found = 0;
00322   unsigned long ticks = 0;
00323 #ifdef VXWORKS
00324   ULONG startTicks = tickGet ();
00325 #endif
00326   info =
00327     (struct DMA_ADDR_INFO *) DEBUG_MALLOC (sizeof (struct DMA_ADDR_INFO));
00328   if (0 == info)
00329     {
00330       return ((struct DMA_ADDR_INFO *) 0);
00331     }
00332   info->board_type = board_type;
00333   info->addr = addr;
00334   switch (board_type)
00335     {
00336     case VX_MVME162_BOARD_TYPE:
00337       if (0 == info)
00338         {
00339           return 0;
00340         }
00341       if (addr & 3)
00342         {
00343           return 0;
00344         }
00345       info->address_decoder = 0;
00346       info->am = 0;
00347       info->ignore_dma_errors = 1;
00348       if (num_mvme162_dmac_commands < 1)
00349         {
00350           memset (mvme162_dmac_commands_list, 0,
00351                   sizeof (struct MVME162_DMAC_COMMAND) *
00352                   MAX_MVME162_DMAC_COMMANDS);
00353           num_mvme162_dmac_commands = 0;
00354         }
00355       /* Local Bus to VMEbus Enable Control Register, 2-44 MVME162LX Programmer's Guide */
00356       vme_bus_enable_control_reg =
00357         (0x0f0000 & *((unsigned long *) 0xFFF4002C));
00358       if (vme_bus_enable_control_reg & 0x10000) /* Address decoder 1 enabled. */
00359         {
00360           /* Local Bus Slave (VMEbus Master) Starting Address/Ending Address Register 1, 2-36 MVME162LX Programmer's Guide */
00361           a1 = *((unsigned long *) 0xFFF40014);
00362           enda1 = (0xFFFF0000 & a1);
00363           starta1 = ((0x0000FFFF & a1) << 16);
00364           if (addr > starta1 && addr < enda1)
00365             {
00366               info->address_decoder = 1;
00367               /* Local Bus Slave (VMEbus Master) Attribute Register 1, 2-42 MVME162LX Programmer's Guide */
00368               info->am = 0x3f & *((unsigned long *) 0xfff40028);
00369 #ifdef VXWORKS
00370               taskDelay (1);
00371 #endif
00372               addr_found = 1;
00373             }
00374         }
00375       if (vme_bus_enable_control_reg & 0x20000 && !addr_found)  /* Address decoder 2 enabled. */
00376         {
00377           /* Local Bus Slave (VMEbus Master) Starting Address/Ending Address Register 2, 2-36 MVME162LX Programmer's Guide */
00378           a1 = *((unsigned long *) 0xFFF40018);
00379           enda1 = (0xFFFF0000 & a1);
00380           starta1 = ((0x0000FFFF & a1) << 16);
00381           if (addr > starta1 && addr < enda1)
00382             {
00383               info->address_decoder = 2;
00384               /* Local Bus Slave (VMEbus Master) Attribute Register 2, 2-41 MVME162LX Programmer's Guide */
00385               info->am = 0x3f & (*((unsigned long *) 0xfff40028) >> 8);
00386 #ifdef VXWORKS
00387               taskDelay (1);
00388 #endif
00389               addr_found = 1;
00390             }
00391         }
00392       if (vme_bus_enable_control_reg & 0x40000 && !addr_found)  /* Address decoder 3 enabled. */
00393         {
00394           /* Local Bus Slave (VMEbus Master) Starting Address/Ending Address Register 3, 2-37 MVME162LX Programmer's Guide */
00395           a1 = *((unsigned long *) 0xFFF4001C);
00396           enda1 = (0xFFFF0000 & a1);
00397           starta1 = ((0x0000FFFF & a1) << 16);
00398           if (addr > starta1 && addr < enda1)
00399             {
00400               info->address_decoder = 1;
00401               /* Local Bus Slave (VMEbus Master) Attribute Register 3, 2-40 MVME162LX Programmer's Guide */
00402               info->am = 0x3f & (*((unsigned long *) 0xfff40028) >> 16);
00403 #ifdef VXWORKS
00404               taskDelay (1);
00405 #endif
00406               addr_found = 1;
00407             }
00408         }
00409       if (vme_bus_enable_control_reg & 0x80000 && !addr_found)  /* Address decoder 4 enabled. */
00410         {
00411           /* Local Bus Slave (VMEbus Master) Starting Address/Ending Address Register 4, 2-38 MVME162LX Programmer's Guide */
00412           a1 = *((unsigned long *) 0xFFF40020);
00413           enda1 = (0xFFFF0000 & a1);
00414           starta1 = ((0x0000FFFF & a1) << 16);
00415           if (addr > starta1 && addr < enda1)
00416             {
00417               info->address_decoder = 1;
00418               /* Local Bus Slave (VMEbus Master) Attribute Register 4, 2-39 MVME162LX Programmer's Guide */
00419               info->am = 0x3f & (*((unsigned long *) 0xfff40028) >> 24);
00420 #ifdef VXWORKS
00421               taskDelay (1);
00422 #endif
00423               addr_found = 1;
00424             }
00425         }
00426       /* Local Bus to VMEbus I/O Control Register */
00427       if ((addr & (0xff << 24)) == (0xf0 << 24))        /* A24 space. */
00428         {
00429           io_control_reg = *((unsigned long *) 0xfff4002c);
00430           if (io_control_reg & (1 << 15))
00431             {
00432               addr_found = 1;
00433               info->address_decoder = 6;
00434               info->am = 0x0c;
00435             }
00436         }
00437       if (addr_found)
00438         {
00439           while (!mvme162_dma_init (info) && tries > 10)
00440             {
00441 #ifdef VXWORKS
00442               taskDelay (1);
00443 #endif
00444               tries++;
00445             }
00446           return info;
00447         }
00448 
00449 
00450       DEBUG_FREE (info);
00451       return 0;
00452 
00453     default:
00454       break;
00455     }
00456   return info;
00457 }
00458 
00459 int
00460 mvme162_dma_init (struct DMA_ADDR_INFO *info)
00461 {
00462   int retval = 0;
00463   unsigned long dmac_status;
00464   unsigned long addr = info->addr;
00465   unsigned long ticks = 0;
00466 #ifdef VXWORKS
00467   ULONG startTicks = tickGet ();
00468 #endif
00469 #ifdef VXWORKS
00470   taskLock ();
00471 #endif
00472   orig_data = *((unsigned long *) addr);
00473   *((unsigned long *) addr) = ~orig_data;
00474   dma_print_errors = 0;
00475   while (!checkForDMADone (info) && ticks < 10)
00476     {
00477 #ifdef VXWORKS
00478       ticks = tickGet () - startTicks;
00479 #else
00480       ticks++;
00481 #endif
00482     }
00483   DMAClearScheduledTransfersList (info);
00484   DMAScheduleLocalToVMETransfer (info, (void *) addr, &orig_data, 4);
00485   DMAStartTransfers (info);
00486   while (!checkForDMADone (info) && ticks < 10)
00487     {
00488 #ifdef VXWORKS
00489       ticks = tickGet () - startTicks;
00490 #else
00491       ticks++;
00492 #endif
00493     }
00494   dma_print_errors = 1;
00495   /* DMAC Status Register, 2-58 MVME162LX Programmer's Guide */
00496   dmac_status = *((unsigned long *) 0xFFF40048);
00497 #ifdef VXWORKS
00498   taskUnlock ();
00499 #endif
00500   retval = ((dmac_status & 0x7f) == 1)
00501     && (orig_data == *((unsigned long *) addr));
00502   if (!retval)
00503     {
00504       *((unsigned long *) addr) == orig_data;
00505     }
00506   return retval;
00507 }
00508 
00509 void
00510 freeDMAInfo (struct DMA_ADDR_INFO *info)
00511 {
00512   if (0 != info)
00513     {
00514       DMAClearScheduledTransfersList (info);
00515       DEBUG_FREE (info);
00516     }
00517 }
00518 
00519 int
00520 checkForDMADone (struct DMA_ADDR_INFO *info)
00521 {
00522   unsigned long dmac_status;
00523   unsigned long dmac_control_word;
00524   unsigned long dmac_byte_counter;
00525   unsigned long dmac_table_address_counter;
00526   int done = 0;
00527   int error = 0;
00528   if (info == 0)
00529     {
00530       return 0;
00531     }
00532   switch (info->board_type)
00533     {
00534     case VX_MVME162_BOARD_TYPE:
00535       /* DMAC Status Register, 2-58 MVME162LX Programmer's Guide */
00536       dmac_status = *((unsigned long *) 0xFFF40048);
00537       done = dmac_status & 1;
00538       error = dmac_status & 0x7e;
00539       if (!done && !error && !dma_command_started)
00540         {
00541           /* DMAC Control Register 1, 2-51 MVME162LX Programmer's Guide  */
00542           dmac_control_word = *((unsigned long *) 0xfff40030);
00543           /* DTBL = 5 */
00544           if (dmac_control_word & (1 << 5))
00545             {
00546               /* DMAC Table Address Counter, 2-55 MVME162LX Programmer's Guide  */
00547               dmac_table_address_counter = *((unsigned long *) 0xfff40044);
00548 
00549               /* DMAC Byte Counter, 2-55 MVME162LX Programmer's Guide  */
00550               dmac_byte_counter = *((unsigned long *) 0xfff40040);
00551               return (((dmac_table_address_counter & 0x3) != 0)
00552                       && (dmac_byte_counter == 0));
00553             }
00554           else
00555             {
00556               /* DMAC Byte Counter, 2-55 MVME162LX Programmer's Guide  */
00557               dmac_byte_counter = *((unsigned long *) 0xfff40040);
00558               return (dmac_byte_counter == 0);
00559             }
00560         }
00561       if (error)
00562         {
00563           if (!dma_command_started || info->ignore_dma_errors)
00564             {
00565               return 1;
00566             }
00567 #ifdef VXWORKS
00568           if (dma_print_errors)
00569             {
00570               logMsg ("DMA error 0x%X -- %s %s\n", error,
00571                       (int) ((error & 0x2) ? "(VMEbus ERR)" : ""),
00572                       (int) ((error & 0x4) ? "(Command Table ERR)" : ""), 0,
00573                       0, 0);
00574               if (error & 0x8)
00575                 logMsg ("(DLTO - DMA Local Bus Timeout ERR)\n", 0, 0, 0, 0, 0,
00576                         0);
00577               if (error & 0x10)
00578                 logMsg ("(DLOB - DMA Offboard ERR)\n", 0, 0, 0, 0, 0, 0);
00579               if (error & 0x20)
00580                 logMsg ("(DLPE - DMA Parity ERR)\n", 0, 0, 0, 0, 0, 0);
00581               if (error & 0x40)
00582                 logMsg ("(DLBE - DMA Unknown ERR)\n", 0, 0, 0, 0, 0, 0);
00583             }
00584 #endif
00585           /* Clear DMAC byte counter so next time we'll no we`re done */
00586           *((unsigned long *) 0xfff40040) = 0;
00587           dma_command_started = 0;
00588           return -1;
00589         }
00590       if (done || error)
00591         {
00592           dma_command_started = 0;
00593         }
00594       return done;
00595 
00596     default:
00597       break;
00598     }
00599   return 0;
00600 }
00601 
00602 int
00603 DMAScheduleLocalToVMETransfer (struct DMA_ADDR_INFO *info, void *vme_dest,
00604                                void *local_src, unsigned long bytes)
00605 {
00606   struct MVME162_DMAC_COMMAND *mvme162_cmd = 0;
00607   void **next_cmd;
00608 
00609   if (info == 0)
00610     {
00611       return -1;
00612     }
00613   switch (info->board_type)
00614     {
00615     case VX_MVME162_BOARD_TYPE:
00616       mvme162_cmd =
00617         (struct MVME162_DMAC_COMMAND *)
00618         &(mvme162_dmac_commands_list[num_mvme162_dmac_commands]);
00619       num_mvme162_dmac_commands++;
00620       mvme162_cmd->control_word = 0;
00621       /* TVME | VINC | LINC */
00622       mvme162_cmd->control_word |= (1 << 9) | (1 << 10) | (1 << 11);
00623       mvme162_cmd->control_word &= 0xFFFF;
00624       mvme162_cmd->control_word &= ~0x3f;
00625       mvme162_cmd->control_word |= info->am;
00626       mvme162_cmd->local_bus_address = local_src;
00627       mvme162_cmd->vme_bus_address = vme_dest;
00628       mvme162_cmd->byte_count = bytes;
00629       mvme162_cmd->next_command = (void *) 3;
00630       if (dma_command_list == 0
00631           || (((unsigned long) dma_command_list) & 3) != 0)
00632         {
00633           dma_command_list = mvme162_cmd;
00634           /* Table Address Counter, 2-55 MVME162LX Programmer's Guide */
00635           *((unsigned long *) 0xfff40044) = (unsigned long) dma_command_list;
00636         }
00637       else
00638         {
00639           next_cmd =
00640             &((struct MVME162_DMAC_COMMAND *) dma_command_list)->next_command;
00641           while (*next_cmd != 0 && (((unsigned long) (*next_cmd)) & 3) == 0)
00642             {
00643               next_cmd =
00644                 &((struct MVME162_DMAC_COMMAND *) (*next_cmd))->next_command;
00645             }
00646           *next_cmd = mvme162_cmd;
00647         }
00648       return 0;
00649 
00650     default:
00651       break;
00652     }
00653   return -1;
00654 }
00655 
00656 int
00657 DMAScheduleVMEToLocalTransfer (struct DMA_ADDR_INFO *info, void *local_dest,
00658                                void *vme_src, unsigned long bytes)
00659 {
00660   struct MVME162_DMAC_COMMAND *mvme162_cmd = 0;
00661   void **next_cmd;
00662   unsigned long am = 0;
00663 
00664   if (info == 0)
00665     {
00666       return -1;
00667     }
00668   switch (info->board_type)
00669     {
00670     case VX_MVME162_BOARD_TYPE:
00671       if (num_mvme162_dmac_commands >= MAX_MVME162_DMAC_COMMANDS)
00672         {
00673           return -1;
00674         }
00675       mvme162_cmd =
00676         (struct MVME162_DMAC_COMMAND *)
00677         &(mvme162_dmac_commands_list[num_mvme162_dmac_commands]);
00678       num_mvme162_dmac_commands++;
00679       mvme162_cmd->control_word = *((unsigned long *) 0xFFF40034);
00680       /* VINC | LINC */
00681       mvme162_cmd->control_word |= (1 << 10) | (1 << 11);
00682       /* TINC */
00683       mvme162_cmd->control_word &= ~(1 << 9);
00684       mvme162_cmd->control_word &= ~(0x3f);
00685       mvme162_cmd->control_word |= info->am;
00686       mvme162_cmd->local_bus_address = local_dest;
00687       mvme162_cmd->vme_bus_address = vme_src;
00688       mvme162_cmd->byte_count = bytes;
00689       mvme162_cmd->next_command = (void *) 3;
00690       if (dma_command_list == 0
00691           || (((unsigned long) dma_command_list) & 3) != 0)
00692         {
00693           dma_command_list = mvme162_cmd;
00694           /* Table Address Counter, 2-55 MVME162LX Programmer's Guide */
00695           *((unsigned long *) 0xfff40044) = (unsigned long) dma_command_list;
00696         }
00697       else
00698         {
00699           next_cmd =
00700             &((struct MVME162_DMAC_COMMAND *) dma_command_list)->next_command;
00701           while (*next_cmd != 0 && (((unsigned long) (*next_cmd)) & 3) == 0)
00702             {
00703               next_cmd =
00704                 &((struct MVME162_DMAC_COMMAND *) (*next_cmd))->next_command;
00705             }
00706           *next_cmd = mvme162_cmd;
00707         }
00708       return 0;
00709 
00710     default:
00711       break;
00712     }
00713   return -1;
00714 }
00715 
00716 int
00717 DMASingleLocalToVMETransfer (struct DMA_ADDR_INFO *info, void *vme_dest,
00718                              void *local_src, unsigned long bytes)
00719 {
00720   unsigned long dmac_control_word = 0;
00721 
00722   if (info == 0)
00723     {
00724       return -1;
00725     }
00726   dma_command_started = 1;
00727   switch (info->board_type)
00728     {
00729     case VX_MVME162_BOARD_TYPE:
00730       /* Table Address Counter, 2-55 MVME162LX Programmers Guide   */
00731       *((unsigned long *) 0xfff40044) = 0;
00732 
00733       /* DMAC Local Bus Address Counter, 2-54 MVME162LX Programmer's Guide */
00734       *((unsigned long *) 0xfff40038) = (unsigned long) local_src;
00735 
00736       /* DMAC VMEbus Address Counter, 2-54  MVME162LX Programmer's Guide */
00737       *((unsigned long *) 0xfff4003c) = (unsigned long) vme_dest;
00738 
00739       /* DMAC Byte Counter, 2-55 MVME162LX Programmer's Guide */
00740       *((unsigned long *) 0xfff40040) = bytes;
00741 
00742       /* DMAC Control Register 2, 2-52 MVME162LX Programmer's Guide */
00743       dmac_control_word = *((unsigned long *) 0xfff40034);
00744       /* VINC = 11, LINC = 10,  TVME=9 */
00745       dmac_control_word |= (1 << 11) | (1 << 10) | (1 << 9);
00746       /* INTE = 15,  */
00747       dmac_control_word &= ~(1 << 15);
00748       dmac_control_word &= ~(0x3f);
00749       dmac_control_word |= info->am;
00750       *((unsigned long *) 0xfff40034) = dmac_control_word;
00751 
00752       /* DMAC Control Register 1, 2-51 MVME162LX Programmer's Guide */
00753       dmac_control_word = *((unsigned long *) 0xfff40030);
00754       /* DEN = 6  */
00755       dmac_control_word |= (1 << 6);
00756       /* DWB = 13, DTBL = 5 */
00757       dmac_control_word &= ~(1 << 13) & ~(1 << 5);
00758       /* Clear status, MPU Status and Interrupt Count Register, 2-57 MVME162LX Programmer's Guide */
00759       *((unsigned long *) 0xfff40048) = (1 << 11);
00760       *((unsigned long *) 0xfff40030) = dmac_control_word;
00761       return 0;
00762 
00763     default:
00764       break;
00765     }
00766   return -1;
00767 }
00768 
00769 
00770 int
00771 DMASingleVMEToLocalTransfer (struct DMA_ADDR_INFO *info, void *local_dest,
00772                              void *vme_src, unsigned long bytes)
00773 {
00774   unsigned long dmac_control_word = 0;
00775   unsigned long am = 0;
00776 
00777   if (info == 0)
00778     {
00779       return -1;
00780     }
00781   dma_command_started = 1;
00782   switch (info->board_type)
00783     {
00784     case VX_MVME162_BOARD_TYPE:
00785       /* Table Address Counter, 2-55 MVME162LX Programmers Guide   */
00786       *((unsigned long *) 0xfff40044) = 0;
00787 
00788       /* DMAC Local Bus Address Counter, 2-54 MVME162LX Programmer's Guide */
00789       *((unsigned long *) 0xfff40038) = (unsigned long) local_dest;
00790 
00791       /* DMAC VMEbus Address Counter, 2-54  MVME162LX Programmer's Guide */
00792       *((unsigned long *) 0xfff4003c) = (unsigned long) vme_src;
00793 
00794       /* DMAC Byte Counter, 2-55 MVME162LX Programmer's Guide */
00795       *((unsigned long *) 0xfff40040) = bytes;
00796 
00797       /* DMAC Control Register 2, 2-52 MVME162LX Programmer's Guide */
00798       dmac_control_word = *((unsigned long *) 0xfff40034);
00799       /* VINC = 11, LINC = 10 */
00800       dmac_control_word |= (1 << 11) | (1 << 10);
00801       /* INTE = 15,  TVME=9  */
00802       dmac_control_word &= ~(1 << 15) & ~(1 << 9);
00803       dmac_control_word &= ~(0x3f);
00804       dmac_control_word |= info->am;
00805       *((unsigned long *) 0xfff40034) = dmac_control_word;
00806 
00807       /* DMAC Control Register 1, 2-51 MVME162LX Programmer's Guide */
00808       dmac_control_word = *((unsigned long *) 0xfff40030);
00809       /* DEN = 6  */
00810       dmac_control_word |= (1 << 6);
00811       /* DWB = 13, DTBL = 5 */
00812       dmac_control_word &= ~(1 << 13) & ~(1 << 5);
00813       /* Clear status, MPU Status and Interrupt Count Register, 2-57 MVME162LX Programmer's Guide */
00814       *((unsigned long *) 0xfff40048) = (1 << 11);
00815       *((unsigned long *) 0xfff40030) = dmac_control_word;
00816       return 0;
00817 
00818     default:
00819       break;
00820     }
00821   return -1;
00822 }
00823 
00824 int
00825 DMAStartTransfers (struct DMA_ADDR_INFO *info)
00826 {
00827   unsigned long dmac_control_word = 0;
00828   unsigned long dmac_timeout_reg = 0;
00829   unsigned long lvreql;
00830   int i = 0;
00831 
00832   if (info == 0)
00833     {
00834       return -1;
00835     }
00836   if (!checkForDMADone (info))
00837     {
00838       return -1;
00839     }
00840   dma_command_started = 1;
00841   switch (info->board_type)
00842     {
00843     case VX_MVME162_BOARD_TYPE:
00844       if (dma_command_list == 0
00845           || (((unsigned long) dma_command_list) & 3) != 0)
00846         {
00847           return -1;
00848         }
00849       /* Table Address Counter, 2-55 MVME162LX Programmer's Guide */
00850       *((unsigned long *) 0xfff40044) = (unsigned long) dma_command_list;
00851 
00852       /* DMAC Control Register 1, 2-51 MVME162LX Programmer's Guide */
00853       dmac_control_word = *((unsigned long *) 0xfff40030);
00854       /* Get the normal VME bus Request Level and use it for the DMA requests
00855          also. */
00856       lvreql = (dmac_control_word & (3 << 8)) >> 8;
00857       dmac_control_word &= ~(0xff);
00858       /* DEN = 6 (Enable DMAC), DTBL = 5(Use Command Table), */
00859       /* DFAIR=4 (Wait for VME Bus Inactive),  */
00860       /* DRELM=(3-2) (VME Bus Release Mode) { 0=BRx&timer,1=timer,2=BRx,3=BRx|timer */
00861       /* DREQL=(0-1) (VMEbus Request Level) */
00862       dmac_control_word |=
00863         (1 << 5) | MVME162_DMA_CONTROL_OPTIONS | (0x3 &
00864                                                   DMA_VMEBUS_REQUEST_LEVEL);
00865       /* DWB = 13 */
00866       dmac_control_word &= ~(1 << 13);
00867       /* DHALT =7 */
00868       dmac_control_word &= ~(1 << 7) & ~(1 << 6);
00869       /* Clear MPU status, MPU Status and DMA interrupt Count Register */
00870       *((unsigned long *) 0xfff40048) = (1 << 11);
00871 
00872       /* Clear byte counter */
00873       *((unsigned long *) 0xfff40040) = 0;
00874       /* Set DMA options */
00875       *((unsigned long *) 0xfff40030) = dmac_control_word;
00876       /* Clear byte counter */
00877       *((unsigned long *) 0xfff40040) = 0;
00878       /* DMAC Ton/Toff and VMEbus Global Timeout Control Register, 2-59 MVME162LX Programmer's Guide */
00879       dmac_timeout_reg = *((unsigned long *) 0xfff4004c);
00880       dmac_timeout_reg &= ~(0xff << 16);
00881       dmac_timeout_reg |= MVME162_DMA_TIMEOUT_OPTIONS;
00882       *((unsigned long *) 0xfff4004c) = dmac_timeout_reg;
00883       /* Check that the settings are still correct. */
00884       if (*((unsigned long *) 0xfff40044) !=
00885           ((unsigned long) dma_command_list)
00886           || *((unsigned long *) 0xfff40030) != dmac_control_word)
00887         {
00888           return -1;
00889         }
00890       /* Enable DMA */
00891       dmac_control_word |= (1 << 6);
00892       *((unsigned long *) 0xfff40030) = dmac_control_word;
00893 #ifdef VXWORKS
00894       startCommandTicks = tickGet ();
00895 #endif
00896       return 0;
00897 
00898     default:
00899       break;
00900     }
00901   return -1;
00902 }
00903 
00904 int
00905 DMAClearScheduledTransfersList (struct DMA_ADDR_INFO *info)
00906 {
00907   void *cmd_ptr;
00908   void *last_cmd_ptr;
00909   unsigned long dmac_control_word;
00910   unsigned long ticks = 0;
00911 #ifdef VXWORKS
00912   ULONG startTicks = tickGet ();
00913 #endif
00914 
00915   if (info == 0)
00916     {
00917       return -1;
00918     }
00919 
00920   dma_command_started = 0;
00921   switch (info->board_type)
00922     {
00923     case VX_MVME162_BOARD_TYPE:
00924       /* last_cmd_ptr = cmd_ptr = dma_command_list;
00925          while(cmd_ptr != 0 && (((unsigned long) cmd_ptr) & 3) == 0)
00926          {
00927          cmd_ptr = ((struct MVME162_DMAC_COMMAND *)cmd_ptr)->next_command;
00928          DEBUG_FREE(last_cmd_ptr);
00929          } */
00930       /* DMAC Control Register 1, 2-51 MVME162LX Programmer's Guide */
00931       dmac_control_word = *((unsigned long *) 0xfff40030);
00932       /* DHALT =7 */
00933       dmac_control_word |= (1 << 7);
00934       /* DEN = 6 */
00935       dmac_control_word &= ~(1 << 6);
00936       *((unsigned long *) 0xfff40030) = dmac_control_word;
00937       /* DMAC Byte Counter, 2-55 MVME162LX Programmer's Guide */
00938       while (*((unsigned long *) 0xfff40040) > 0)
00939         {
00940           /* Clear MPU status, MPU Status and DMA interrupt Count Register */
00941           if (*((unsigned long *) 0xfff40048) & 0x7f)
00942             {
00943               break;
00944             }
00945 #ifdef VXWORKS
00946           ticks = tickGet () - startTicks;
00947 #else
00948           ticks++;
00949 #endif
00950           if (ticks > 100)
00951             {
00952 #ifdef VXWORKS
00953               displayMemory ((void *) 0xfff40030, 8, 4);
00954 #endif
00955               *((unsigned long *) 0xfff40044) = 0x3;
00956               *((unsigned long *) 0xfff40040) = 0;
00957               return -1;
00958             }
00959         }
00960       /* Table Counter */
00961       *((unsigned long *) 0xfff40044) = 0x3;
00962       memset (mvme162_dmac_commands_list, 0,
00963               sizeof (struct MVME162_DMAC_COMMAND) *
00964               MAX_MVME162_DMAC_COMMANDS);
00965       num_mvme162_dmac_commands = 0;
00966       dma_command_list = 0;
00967       break;
00968 
00969     default:
00970       break;
00971     }
00972   return 0;
00973 }

Generated on Sun Dec 2 15:56:49 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001