1 /* $Id: adapter.c,v 1.4 2002/10/01 19:27:18 chorns Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: hal/x86/adapter.c (from ntoskrnl/io/adapter.c)
6 * PURPOSE: DMA handling
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <ddk/iotypes.h>
16 #include <internal/debug.h>
19 /* FUNCTIONS *****************************************************************/
21 /* NOTE: IoAllocateAdapterChannel in NTOSKRNL.EXE */
24 HalAllocateAdapterChannel(PADAPTER_OBJECT AdapterObject
,
25 PDEVICE_OBJECT DeviceObject
,
26 ULONG NumberOfMapRegisters
,
27 PDRIVER_CONTROL ExecutionRoutine
,
33 LARGE_INTEGER MaxAddress
;
35 MaxAddress
.QuadPart
= 0x1000000;
36 Buffer
= MmAllocateContiguousAlignedMemory( NumberOfMapRegisters
* PAGE_SIZE
,
40 return STATUS_INSUFFICIENT_RESOURCES
;
41 KeAcquireSpinLock( &AdapterObject
->SpinLock
, &OldIrql
);
42 if( AdapterObject
->Inuse
)
44 // someone is already using it, we need to wait
45 // create a wait block, and add it to the chain
49 AdapterObject
->Inuse
= TRUE
;
50 KeReleaseSpinLock( &AdapterObject
->SpinLock
, OldIrql
);
51 ret
= ExecutionRoutine( DeviceObject
,
55 KeAcquireSpinLock( &AdapterObject
->SpinLock
, &OldIrql
);
56 if( ret
== DeallocateObject
)
58 MmFreeContiguousMemory( Buffer
);
59 AdapterObject
->Inuse
= FALSE
;
61 else AdapterObject
->Buffer
= Buffer
;
63 KeReleaseSpinLock( &AdapterObject
->SpinLock
, OldIrql
);
64 return STATUS_SUCCESS
;
69 IoFlushAdapterBuffers (PADAPTER_OBJECT AdapterObject
,
71 PVOID MapRegisterBase
,
74 BOOLEAN WriteToDevice
)
76 // if this was a read from device, copy data back to caller buffer, otherwise, do nothing
78 memcpy( (PVOID
)((DWORD
)MmGetSystemAddressForMdl( Mdl
) + (DWORD
)CurrentVa
- (DWORD
)MmGetMdlVirtualAddress( Mdl
)), MapRegisterBase
, Length
);
84 IoFreeAdapterChannel (PADAPTER_OBJECT AdapterObject
)
88 KeAcquireSpinLock( &AdapterObject
->SpinLock
, &OldIrql
);
89 if( AdapterObject
->Inuse
== FALSE
)
91 DbgPrint( "Attempting to IoFreeAdapterChannel on a channel not in use\n" );
94 AdapterObject
->Inuse
= FALSE
;
95 if( AdapterObject
->Buffer
)
97 MmFreeContiguousMemory( AdapterObject
->Buffer
);
98 AdapterObject
->Buffer
= 0;
100 KeReleaseSpinLock( &AdapterObject
->SpinLock
, OldIrql
);
105 IoFreeMapRegisters (PADAPTER_OBJECT AdapterObject
,
106 PVOID MapRegisterBase
,
107 ULONG NumberOfMapRegisters
)
113 PHYSICAL_ADDRESS STDCALL
114 IoMapTransfer (PADAPTER_OBJECT AdapterObject
,
116 PVOID MapRegisterBase
,
119 BOOLEAN WriteToDevice
)
121 PHYSICAL_ADDRESS Address
;
122 // program up the dma controller, and return
123 // if it is a write to the device, copy the caller buffer to the low buffer
125 memcpy( MapRegisterBase
,
126 MmGetSystemAddressForMdl( Mdl
) + ( (DWORD
)CurrentVa
- (DWORD
)MmGetMdlVirtualAddress( Mdl
) ),
128 Address
= MmGetPhysicalAddress( MapRegisterBase
);
129 // port 0xA is the dma mask register, or a 0x10 on to the channel number to mask it
130 WRITE_PORT_UCHAR( (PVOID
)0x0A, AdapterObject
->Channel
| 0x10 );
131 // write zero to the reset register
132 WRITE_PORT_UCHAR( (PVOID
)0x0C, 0 );
133 // mode register, or channel with 0x4 for write memory, 0x8 for read memory, 0x10 for non auto initialize
134 WRITE_PORT_UCHAR( (PVOID
)0x0B, AdapterObject
->Channel
| ( WriteToDevice
? 0x8 : 0x4 ) );
135 // set the 64k page register for the channel
136 WRITE_PORT_UCHAR( AdapterObject
->PagePort
, (UCHAR
)(((ULONG
)Address
.QuadPart
)>>16) );
137 // low, then high address byte, which is always 0 for us, because we have a 64k alligned address
138 WRITE_PORT_UCHAR( AdapterObject
->OffsetPort
, 0 );
139 WRITE_PORT_UCHAR( AdapterObject
->OffsetPort
, 0 );
140 // count is 1 less than length, low then high
141 WRITE_PORT_UCHAR( AdapterObject
->CountPort
, (UCHAR
)(*Length
- 1) );
142 WRITE_PORT_UCHAR( AdapterObject
->CountPort
, (UCHAR
)((*Length
- 1)>>8) );
143 // unmask the channel to let it rip
144 WRITE_PORT_UCHAR( (PVOID
)0x0A, AdapterObject
->Channel
);
145 Address
.QuadPart
= (DWORD
)MapRegisterBase
;