Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Доки по Dma

6.6K
30 сентября 2004 года
developer
9 / / 21.06.2004
Подкиньте, пожалуйста, ссылки на сайты с доками по программированию контроллера DMA.
1.8K
01 октября 2004 года
MishaSt
170 / / 11.08.2003
Цитата:
Originally posted by developer
Подкиньте, пожалуйста, ссылки на сайты с доками по программированию контроллера DMA.


Непомню уже.

Здесь, как я понял, используется 16-ти битный DMA.
Первое, что делаешь, это маскируешь канал, чтобы он случайно не заработал, пока данные записываешь. Потом записываешь 0 в регистр flip-flop. Дело в том, что адресс ты записываешь сначала старшую половину, а потом младшую, ну так вот, flip-flop - это счётчик что-ли, который показывет, какой следующий байт, старший или младший, ну вот, ты его сбрасываешь. Засылаешь режим, адрес, длинну. И размаскируешь канал. Вот как это у меня:

Код:
void SetDMA(unsigned char far *SBS,int mode,unsigned char Ch,unsigned short len){
    unsigned char t;
    LA=SBS;
    // LA = Linear Address
    LA=(LA>>16)*16L+(LA & 0xFFFF);
    outp(0xA,4+Ch);                 //Channel Disabled
    outp(0xB,Ch+(mode*4));              //Select mode
    outp(0xC,Ch);                   //Flip/Flop
    outp(DMAA[Ch],(LA & 0xFF));     //Addres
    t=(LA & 0xFF00) >> 8;
    outp(DMAA[Ch],t);           //Addres
    outp(DMAP[Ch],(LA >> 16));      //Page
    t=lo(len-1);
    outp(DMAC[Ch],t);           //Count
    t=hi(len-1);
    outp(DMAC[Ch],t);           //Count
    outp(0xA,Ch);                   //Channel Enabled
}
...
// пользовал так:
// SBS не должен пересекать 64Кб границу. Так DMA устроен.
SetDMA((unsigned char far *)SBS,0x12,1,26000);

4 года назад писал, сейчас сделал бы это лучше...
1.8K
01 октября 2004 года
MishaSt
170 / / 11.08.2003
Вот как это сделано в Duke Nukem 3D.
dma.c
Код:
/*
Copyright (C) 1994-1995 Apogee Software, Ltd.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
/**********************************************************************
   module: DMA.C

   author: James R. Dose
   date:   February 4, 1994

   Low level routines to for programming the DMA controller for 8 bit
   and 16 bit transfers.

   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
**********************************************************************/

#include <dos.h>
#include <conio.h>
#include <stdlib.h>
#include "dma.h"

#define DMA_MaxChannel 7

#define VALID   ( 1 == 1 )
#define INVALID ( !VALID )

#define BYTE 0
#define WORD 1

typedef struct
   {
   int Valid;
   int Width;
   int Mask;
   int Mode;
   int Clear;
   int Page;
   int Address;
   int Length;
   } DMA_PORT;

static const DMA_PORT DMA_PortInfo[ DMA_MaxChannel + 1 ] =
   {
      {   VALID, BYTE,  0xA,  0xB,  0xC, 0x87,  0x0,  0x1 },
      {   VALID, BYTE,  0xA,  0xB,  0xC, 0x83,  0x2,  0x3 },
      { INVALID, BYTE,  0xA,  0xB,  0xC, 0x81,  0x4,  0x5 },
      {   VALID, BYTE,  0xA,  0xB,  0xC, 0x82,  0x6,  0x7 },
      { INVALID, WORD, 0xD4, 0xD6, 0xD8, 0x8F, 0xC0, 0xC2 },
      {   VALID, WORD, 0xD4, 0xD6, 0xD8, 0x8B, 0xC4, 0xC6 },
      {   VALID, WORD, 0xD4, 0xD6, 0xD8, 0x89, 0xC8, 0xCA },
      {   VALID, WORD, 0xD4, 0xD6, 0xD8, 0x8A, 0xCC, 0xCE },
   };

int DMA_ErrorCode = DMA_Ok;

#define DMA_SetErrorCode( status ) \
   DMA_ErrorCode   = ( status );


/*---------------------------------------------------------------------
   Function: DMA_ErrorString

   Returns a pointer to the error message associated with an error
   number.  A -1 returns a pointer the current error.
---------------------------------------------------------------------*/

char *DMA_ErrorString
   (
   int ErrorNumber
   )

   {
   char *ErrorString;

   switch( ErrorNumber )
      {
      case DMA_Error :
         ErrorString = DMA_ErrorString( DMA_ErrorCode );
         break;

      case DMA_Ok :
         ErrorString = "DMA channel ok.";
         break;

      case DMA_ChannelOutOfRange :
         ErrorString = "DMA channel out of valid range.";
         break;

      case DMA_InvalidChannel :
         ErrorString = "Unsupported DMA channel.";
         break;

      default :
         ErrorString = "Unknown DMA error code.";
         break;
      }

   return( ErrorString );
   }


/*---------------------------------------------------------------------
   Function: DMA_VerifyChannel

   Verifies whether a DMA channel is available to transfer data.
---------------------------------------------------------------------*/

int DMA_VerifyChannel
   (
   int channel
   )

   {
   int      status;
   int      Error;

   status = DMA_Ok;
   Error  = DMA_Ok;

   if ( ( channel < 0 ) || ( DMA_MaxChannel < channel ) )
      {
      Error = DMA_ChannelOutOfRange;
      status = DMA_Error;
      }
   else if ( DMA_PortInfo[ channel ].Valid == INVALID )
      {
      Error = DMA_InvalidChannel;
      status = DMA_Error;
      }

   DMA_SetErrorCode( Error );
   return( status );
   }


/*---------------------------------------------------------------------
   Function: DMA_SetupTransfer

   Programs the specified DMA channel to transfer data.
---------------------------------------------------------------------*/

int DMA_SetupTransfer
   (
   int  channel,
   char *address,
   int  length,
   int  mode
   )

   {
   DMA_PORT *Port;
   int      addr;
   int      ChannelSelect;
   int      Page;
   int      HiByte;
   int      LoByte;
   int      TransferLength;
   int      status;

   status = DMA_VerifyChannel( channel );

   if ( status == DMA_Ok )
      {
      Port = &DMA_PortInfo[ channel ];
      ChannelSelect = channel & 0x3;

      addr = ( int )address;

      if ( Port->Width == WORD )
         {
         Page   = ( addr >> 16 ) & 255;
         HiByte = ( addr >> 9 ) & 255;
         LoByte = ( addr >> 1 ) & 255;

         // Convert the length in bytes to the length in words
         TransferLength = ( length + 1 ) >> 1;

         // The length is always one less the number of bytes or words
         // that we're going to send
         TransferLength--;
         }
      else
         {
         Page   = ( addr >> 16 ) & 255;
         HiByte = ( addr >> 8 ) & 255;
         LoByte = addr & 255;

         // The length is always one less the number of bytes or words
         // that we're going to send
         TransferLength = length - 1;
         }

      // Mask off DMA channel
      outp( Port->Mask, 4 | ChannelSelect );

      // Clear flip-flop to lower byte with any data
      outp( Port->Clear, 0 );

      // Set DMA mode
      switch( mode )
         {
         case DMA_SingleShotRead :
            outp( Port->Mode, 0x48 | ChannelSelect );
            break;

         case DMA_SingleShotWrite :
            outp( Port->Mode, 0x44 | ChannelSelect );
            break;

         case DMA_AutoInitRead :
            outp( Port->Mode, 0x58 | ChannelSelect );
            break;

         case DMA_AutoInitWrite :
            outp( Port->Mode, 0x54 | ChannelSelect );
            break;
         }

      // Send address
      outp( Port->Address, LoByte );
      outp( Port->Address, HiByte );

      // Send page
      outp( Port->Page, Page );

      // Send length
      outp( Port->Length, TransferLength );
      outp( Port->Length, TransferLength >> 8 );

      // enable DMA channel
      outp( Port->Mask, ChannelSelect );
      }

   return( status );
   }


/*---------------------------------------------------------------------
   Function: DMA_EndTransfer

   Ends use of the specified DMA channel.
---------------------------------------------------------------------*/

int DMA_EndTransfer
   (
   int channel
   )

   {
   DMA_PORT *Port;
   int       ChannelSelect;
   int       status;

   status = DMA_VerifyChannel( channel );
   if ( status == DMA_Ok )
      {
      Port = &DMA_PortInfo[ channel ];
      ChannelSelect = channel & 0x3;

      // Mask off DMA channel
      outp( Port->Mask, 4 | ChannelSelect );

      // Clear flip-flop to lower byte with any data
      outp( Port->Clear, 0 );
      }

   return( status );
   }


/*---------------------------------------------------------------------
   Function: DMA_GetCurrentPos

   Returns the position of the specified DMA transfer.
---------------------------------------------------------------------*/

char *DMA_GetCurrentPos
   (
   int channel
   )

   {
   DMA_PORT      *Port;
   unsigned long addr;
   int           status;

   addr   = NULL;
   status = DMA_VerifyChannel( channel );

   if ( status == DMA_Ok )
      {
      Port = &DMA_PortInfo[ channel ];

      if ( Port->Width == WORD )
         {
         // Get address
         addr  = inp( Port->Address ) << 1;
         addr |= inp( Port->Address ) << 9;

         // Get page
         addr |= inp( Port->Page ) << 16;
         }
      else
         {
         // Get address
         addr = inp( Port->Address );
         addr |= inp( Port->Address ) << 8;

         // Get page
         addr |= inp( Port->Page ) << 16;
         }
      }

   return( ( char * )addr );
   }


/*---------------------------------------------------------------------
   Function: DMA_GetTransferCount

   Returns how many bytes are left in the DMA's transfer.
---------------------------------------------------------------------*/

int DMA_GetTransferCount
   (
   int channel
   )

   {
   DMA_PORT      *Port;
   int           count;
   int           status;

   status = DMA_Ok;

   count = 0;

   if ( ( channel < 0 ) || ( DMA_MaxChannel < channel ) )
      {
      status = DMA_ChannelOutOfRange;
      }
   else if ( DMA_PortInfo[ channel ].Valid == INVALID )
      {
      status = DMA_InvalidChannel;
      }

   if ( status == DMA_Ok )
      {
      Port = &DMA_PortInfo[ channel ];

      outp( Port->Clear, 0 );
      count  = inp( Port->Length );
      count += inp( Port->Length ) << 8;

      if ( Port->Width == WORD )
         {
         count <<= 1;
         }
      }

   DMA_SetErrorCode( status );

   return( count );
   }
1.8K
01 октября 2004 года
MishaSt
170 / / 11.08.2003
dma.h
Код:
/*
Copyright (C) 1994-1995 Apogee Software, Ltd.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
/**********************************************************************
   file:   DMA.H

   author: James R. Dose
   date:   February 4, 1994

   Public header file for DMA.C

   (c) Copyright 1994 James R. Dose.  All Rights Reserved.
**********************************************************************/

#ifndef __DMA_H
#define __DMA_H

enum DMA_ERRORS
   {
   DMA_Error = -1,
   DMA_Ok    = 0,
   DMA_ChannelOutOfRange,
   DMA_InvalidChannel
   };

enum DMA_Modes
   {
   DMA_SingleShotRead,
   DMA_SingleShotWrite,
   DMA_AutoInitRead,
   DMA_AutoInitWrite
   };

char *DMA_ErrorString
   (
   int ErrorNumber
   );

int DMA_VerifyChannel
   (
   int channel
   );

int DMA_SetupTransfer
   (
   int  channel,
   char *address,
   int  length,
   int  mode
   );

int DMA_EndTransfer
   (
   int channel
   );

char *DMA_GetCurrentPos
   (
   int channel
   );

int DMA_GetTransferCount
   (
   int channel
   );

#endif
6.6K
01 октября 2004 года
developer
9 / / 21.06.2004
Всем спасибо!
Но если кто найдет доки: киньте, пожалуйста, на "developer@hotmail.ru".
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог