public int Arm(IdeRequest !ideRequest) { byte value = BUSMASTER_CONTROL_MASK_START; if (ideRequest.Command == IdeCmdType.Read) { value |= BUSMASTER_CONTROL_MASK_WRITE; } commandPort.Write8(value); // enable BM return(0); } // BmArm
public void BmPrepareController(IdeRequest !ideRequest) { // Perform steps 1 and 2 above: set up PRD, clear // error snd interrupt // Init. Scatter Gather List Register uint thePrd = FillPrdTable(ideRequest); prdPort.Write32(thePrd); // Clear Errors byte status = (byte)(BUSMASTER_STATUS_MASK_INTERRUPT | BUSMASTER_STATUS_MASK_ERROR); statusPort.Write8(status); return; } // BmPrepareController
private uint FillPrdTable(IdeRequest !ideRequest) { // given a memory address and a length generate // a Physical Region Descriptor Table (PDRT) to be used // in a IDE busmaster DMA transfer //a PRDT table is an array of PRD entries, each 8 bytes in //length. There is no count associated with this structure // Bit 7 of the last byte of the last entry signifies the //end of the table // PRD (Physical Region Descriptor) // the first 4 bytes of a PRD specify the memory address // Bytes 5 and 6 (16 bits) specify the length. // At most a PRD can specify a transfer of 64KB. // The memory specified by a PRD cannot cross a 64KB boundary // Any transfer that would cross such a boundary needs to be // split into to separate PRDs uint addr = (uint)((UIntPtr)ideRequest.BufferAddress + ideRequest.BufferOffset); uint len = (uint)ideRequest.Length; // Write a bad entry at the end WritePrdEntry(PRD_MAX_ENTRIES - 1, 0, 0xbad1, true); uint baseAddr = addr; uint bytesToMap = len; int i = 0; while (0 != bytesToMap) { uint did = WritePrdChunk(i, baseAddr, bytesToMap); baseAddr += did; bytesToMap -= did; i++; } // DEBUG CHECK uint computedLen = 0; bool eotFound = false; for (i = 0; i < PRD_MAX_ENTRIES; i++) { uint dummy; uint length; bool eot; ReadPrdEntry(i, out dummy, out length, out eot); computedLen = computedLen + length; if (eot) { eotFound = true; break; } } if (computedLen != len || !eotFound) { throw new ApplicationException("PRD length mismatch"); } DumpPrd(); return((uint)prdRegion.PhysicalAddress.Value); }