I am writing a floppy driver and am trying to make sure my DMA code is correct. The code I have I got from somewhere else, so I have almost no idea what it means. I understand some, but not enough to know if there are problems with it.
For now, I am just trying to write to video memory(0xa0000), just to see if the floppy read sector worked.
Can you tell me if this should work?
I call it with:
Setup_DMA(0x2, buffer, 512, 1); //buffer is ignored; 0xa0000
//is used instead, 1 means floppy to dma, 512 bytes, channel 2
Code: Select all
typedef unsigned short int ushort;
typedef unsigned long int ulong;
typedef unsigned char uchar;
ushort AddrP[4] = {0x00, 0x02, 0x04, 0x06};
ushort PageP[4] = {0x87, 0x83, 0x81, 0x82};
ushort CountP[4] = {0x01, 0x03, 0x05, 0x07};
int Setup_DMA(int Channel, char *Buffer, ulong Length, uchar Direction) {
//Pre: 0 <= Channel <= 3
// Buffer < 1048576
// 0 < Length <= 65536
// Direction == 0 if Memory-to-I/O, Direction == 1 if I/O-to-Memory
//
//Post: Return 0 if successful, else return 1.
uchar Out;
uchar LSB;
uchar MSB;
uchar Page;
Out = 0x40;
//Only support DMA channels 1-3
if(Channel > 3) return 1;
Out = Out | Channel;
if(Direction == 0) Out = Out | 0x08;
else if(Direction == 1) Out = Out | 0x04;
else return 1;
//Only does DMA in the first 1Meg (for now). And only if thebuffer does notcross a 64K page boundary.
//if((ulong)Buffer > 1048576 || (ulong)Buffer >> 16 != ((ulong)Buffer + (Length - 1)) >> 16) return 1;
LSB = 0x0; //(uchar)Buffer;
MSB = 0x0; //(uchar)((ulong)Buffer >> 8);
Page = 0xa; //(uchar)((ulong)Buffer >> 16);
if(Length > 65536 || Length == 0) return 1;
Length--;
//Mask this DMA channel.
outportb(0x0A, (uchar)Channel | 4);
//Send the mode.
outportb(0x0B, Out);
//Clear LSB/MSB flip/flop
outportb(0x0C, 0);
//Send the address & page.
outportb(AddrP[Channel], LSB);
outportb(AddrP[Channel], MSB);
outportb(PageP[Channel], Page);
//Clear LSB/MSB flip/flop
outportb(0x0C, 0);
//Send the length of transfer.
outportb(CountP[Channel], (uchar)Length);
outportb(CountP[Channel], (uchar)(Length >> 8));
//Unmask this DMA channel.
outportb(0x0A, (uchar)Channel);
return 0;