DiBR
обычная кошмарная
домашняя страничка
Ежекакполучится околокомпьютерное обозрение
 
  <<<  предыдущий Tech! archive #14 следующий  >>>  
   Последний выпуск       Архив       Ссылки       Полезности       humor.filtered       Фотки       О сайте   
          Это - достаточно беспорядочный архив сообщений конференций сети fidonet, которые на момент их прочтения мной показались полезными или интересными. Многие устарели, многие узкоспецифичны и малоинтересны, но может оказаться и что-то новое...
         
- __techs (2:5015/42) ----------------------------------------------- __techs -
Msg  : 14 of 1000                          Scn
From : Lout Roman                          2:463/586.20    26 Apr 96  21:40:00
To   : VLADIMIR MEDEIKO                                    02 May 96  08:11:18
Subj : DMA...  (Was: Быстpый вывод ...)[2/2]
-------------------------------------------------------------------------------
@AREA:DEMO.DESIGN
                          ---> Hi VLADIMIR! <---

===========cut==============
//далее всё для DMA :

#define CH0_ADR_REG      0 //порт адреса (биты 0...15) RAM канала 0;
#define CH0_COUNT_REG    1 //порт счётчика передаваемых байт канала 0;
#define CH1_ADR_REG      2 //то же для канала 1...
#define CH1_COUNT_REG    3

#define STATUS_REG       8 //порт (read) регистра состояния каналов DMA;
#define COMM_REG         8 //порт (write) регистра команд DMA;
#define REQUEST_REG      9 //порт регистра программных запросов на DMA;
#define MODE_REG        11 //порт регистра установки режимов DMA каналов;
#define FLIP_FLOP_REG   12 //порт регистра сброса триггера пар байт;
#define ALL_MASK_REG    15 //порт регистра маски аппаратных запросов
//на DMA всех 4-х каналов : на программные запросы не влияет (?);

#define CH0_PAGE_REG  0x87 //порт страницы (биты 16...19 адреса) RAM кан. 0;
#define CH1_PAGE_REG  0x83 //порт страницы (биты 16...19 адреса) RAM кан. 1;

#define STATUS_VAL_01 0x03 //xxxx xx11 статус TC канала 0 и 1;
#define STATUS_VAL_0  0x01 //xxxx xxx1 статус TC канала 0;

//эти коды разрешают (clear mask) и запрещают (set mask)
//аппаратные запросы на DMA по всем каналам :
#define CLR_MASK_ALL  0x00 //xxxx 0000;
#define SET_MASK_ALL  0x0F //xxxx 1111;

#define CLR_PREQ_0  0x00 //xxxx x000 сброс программного запр. DMA кан. 0;
#define CLR_PREQ_1  0x01 //xxxx x001 сброс прогр-го запроса DMA кан. 1;
#define SET_PREQ_0  0x04 //xxxx x100 уст-ка прогр-го запроса DMA кан. 0;
#define SET_PREQ_1  0x05 //xxxx x101 установка программного запроса...1;

//стандартные режимы каналов 0/1 (одиночная передача, инкрементирование,
//без автоинициализации, холостой цикл проверки канала) :
#define CH0_STD_MODE_VAL  0x40 //0100 0000;
#define CH1_STD_MODE_VAL  0x41 //0100 0001;

//"мои" режимы каналов 0/1 (блочная передача, инкрементирование,
//без автоинициализации, чтение в канале 0/запись в канале 1) :
#define CH0_MY_MODE_VAL   0x88 //1000 1000;
#define CH1_MY_MODE_VAL   0x85 //1000 0101;

//стандартный режим работы DMA :
#define STD_COMM_VAL       0 //0000 0000;

//DMA в "моём" режиме (память->память) :
#define MY_COMM_VAL     0x01 //0000 0001;

//DMA в "моём" режиме (память->память с удлиненным циклом записи,
//что иногда может уменьшить частоту ошибок) :
#define MY_COMM_VAL1    0x21 //0010 0001;


void Dma(byte srcpg,word srcad,byte dstpg,word dstad,word count)
//передача count байт из srcRAM в destinationRAM (page*64K+adress),
//пока без проверки на переполнение адресов !
{
int loop;

loop=0;
disable(); //запрет аппаратных прерываний, не обязятельно;

//запрет аппаратных запросов на ПДП каналов 0-3
//(на всякий случай):
outportb(ALL_MASK_REG,SET_MASK_ALL);

//любой код в этот регистр гарантирует верную передачу словных
//данных в виде пары байт (младший/старший байты) :
outportb(FLIP_FLOP_REG,0);

//channal 0 :
outportb(CH0_PAGE_REG,srcpg); //страница источника;
//lowbyte/highbyte адреса источника :
outportb(CH0_ADR_REG,(byte)(srcad%256));
outportb(CH0_ADR_REG,(byte)(srcad/256));
//lowbyte/highbyte числа передач (надо вычитать 1 !) :
outportb(CH0_COUNT_REG,(byte)((count-1)%256));
outportb(CH0_COUNT_REG,(byte)((count-1)/256));

//channal 1 (аналогично для приёмника) :
outportb(CH1_PAGE_REG,dstpg); //страница источника;
//lowbyte/highbyte адреса источника :
outportb(CH1_ADR_REG,(byte)(dstad%256));
outportb(CH1_ADR_REG,(byte)(dstad/256));
//lowbyte/highbyte числа передач (надо вычитать 1 !) :
outportb(CH1_COUNT_REG,(byte)((count-1)%256));
outportb(CH1_COUNT_REG,(byte)((count-1)/256));

//установка нужных режимов каналов 0 и 1 :
outportb(MODE_REG,CH0_MY_MODE_VAL);
outportb(MODE_REG,CH1_MY_MODE_VAL);

/***** см ниже эквивалентный ассемблерный текст ******
//установка программного запроса канала 1 :
outportb(REQUEST_REG,SET_PREQ_1);
//старт DMA по установке программного запроса канала 0 :
outportb(REQUEST_REG,SET_PREQ_0);
//перевод DMA в режим память-память:
outportb(COMM_REG,MY_COMM_VAL);
*****/

//мистическая часть программы (!!!) :
//от введения какой-то (бесполезной с точки зрения здравого смысла)
//ассемблерной операции и от ее типа сильно зависит вероятность
//успеха работы ПОСЛЕДУЮЩЕГО кода DMA передачи...
//например, на AT286/10Mhz в случае применения "mov cx,constanta"
//вероятность успешной передачи была 90%, при отключенном турбо
//(6Mhz) она падала до 70% (неясно почему)...
//Я не думаю, что это глюки компилятора (код смотреть неохота),
//хотя по большому счету надо всю эту процедуру перевести на ассемблер...
//Вот достойная задачка для хакера - выяснить причину сбоев, их
//зависимости от нижеприведенной мистики и рецепт получения
//100%-й надежности...
asm{
 mov cx,0;  //отлично, вместо 0 годится любая (?) константа
//  mov cx,cx; //средне;
//  mov al,al; //средне
//  mov ax,ax; //средне
//  nop;       //очень плохо (менее 1% срабатываний)
//  (ничего);  //очень плохо
}

//ассемблерный эквивалент закомментаренного СИ-кода старта DMA;
//от порядка заполнения регистров может тоже зависить результат,
//но это можно понять...
asm{
 mov al,SET_PREQ_1
 out REQUEST_REG,al
 mov al,SET_PREQ_0
 out REQUEST_REG,al
 mov al,MY_COMM_VAL
 out COMM_REG,al
}

//идёт передача DMA канал 0 -> канал 1 !!!

//конец передачи по установке в 1 бита TC канала 0, если не
//проверять это, то неизвестно когда кончится DMA-передача
//(??? если DMA работает неправильно, то цикл будет бесконечным,
//для этого поставлен сторож loop):
while ( STATUS_VAL_0 != (inportb(STATUS_REG) & STATUS_VAL_0) )
      if (++loop>=22222) break;

//возможно периодические сбои в DMA вызваны преждевременным
//прекращением передачи из-за неверного выполнения проверки
//на конец передачи, так как во время блочной передачи память
//вообще не должна быть доступна (???) процессору !!!

//сброс программного запроса канала 1 :
outportb(REQUEST_REG,CLR_PREQ_1);
//сброс программного запроса канала 0 :
outportb(REQUEST_REG,CLR_PREQ_0);
//восстановление обычного режима DMA :
outportb(COMM_REG,STD_COMM_VAL);
//восстановление обычных режимов каналов 0 и 1 :
outportb(MODE_REG,CH0_STD_MODE_VAL);
outportb(MODE_REG,CH1_STD_MODE_VAL);

//разрешение аппар-х запросов ПДП 0-3;
outportb(ALL_MASK_REG,CLR_MASK_ALL);
enable(); //разрешение аппар-х прерыванийй;

//при проверки всегда получается loop=0...
//printf("loop=%i\\n",loop);
}
=========cut===========

---
* Origin: ·Да мне за это шнобелевскую премию должны были дать ! (2:463/586.20)






<<<

архив dibr

>>>'