Это - достаточно беспорядочный архив сообщений конференций сети 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)