2 Copyright © 2004-2006, The AROS Development Team. All rights reserved
10 #include <aros/debug.h>
12 #include <exec/types.h>
13 #include <exec/exec.h>
14 #include <exec/resident.h>
15 #include <utility/utility.h>
22 #include <proto/exec.h>
23 #include <proto/oop.h>
28 Prepare PRD entries for sectors transfer. This function assumes, that noone
29 else will even touch PRD. It should be however truth, as for given bus all
30 ATA accesses are protected with a semaphore.
32 VOID
dma_SetupPRD(struct ata_Unit
*unit
, APTR buffer
, ULONG sectors
, BOOL io
)
34 struct PRDEntry
*prd
= unit
->au_Bus
->ab_PRD
;
35 IPTR ptr
= (IPTR
)buffer
;
36 ULONG size
= sectors
<< unit
->au_SectorShift
;
39 D(bug("[DMA] Setup PRD for %d bytes at %x\n",
43 The first PRD address is the buffer pointer self, doesn't have to be
44 aligned to 64K boundary
46 prd
[0].prde_Address
= ptr
;
49 All other PRD addresses are the next 64K pages, until the page address
50 is bigger as the highest address used
52 for (i
=1; i
< PRD_MAX
; i
++)
54 prd
[i
].prde_Address
= (prd
[i
-1].prde_Address
& 0xffff0000) + 0x00010000;
55 prd
[i
].prde_Length
= 0;
56 if (prd
[i
].prde_Address
> ptr
+ size
)
60 if (size
<= prd
[1].prde_Address
- prd
[0].prde_Address
)
62 prd
[0].prde_Length
= size
;
67 prd
[0].prde_Length
= prd
[1].prde_Address
- prd
[0].prde_Address
;
68 size
-= prd
[0].prde_Length
;
71 prd
[0].prde_Length
&= 0x0000ffff;
77 prd
[i
].prde_Length
= 0; /* 64KB in one PRD */
84 prd
[i
].prde_Length
= size
;
88 prd
[i
-1].prde_Length
|= 0x80000000;
90 outl((ULONG
)prd
, unit
->au_DMAPort
+ dma_PRD
);
91 outb(inb(unit
->au_DMAPort
+ dma_Status
) | DMAF_Error
| DMAF_Interrupt
, unit
->au_DMAPort
+ dma_Status
);
94 If io set to TRUE, then sectors are readed, when set to FALSE, they are written
97 outb(DMA_WRITE
, unit
->au_DMAPort
+ dma_Command
);
99 outb(DMA_READ
, unit
->au_DMAPort
+ dma_Command
);
102 VOID
dma_StartDMA(struct ata_Unit
*unit
)
104 inb(unit
->au_DMAPort
+ dma_Command
);
105 inb(unit
->au_DMAPort
+ dma_Status
);
106 outb(inb(unit
->au_DMAPort
+ dma_Command
) | DMA_START
, unit
->au_DMAPort
+ dma_Command
);
107 inb(unit
->au_DMAPort
+ dma_Command
);
108 inb(unit
->au_DMAPort
+ dma_Status
);
111 VOID
dma_StopDMA(struct ata_Unit
*unit
)
113 inb(unit
->au_DMAPort
+ dma_Command
);
114 inb(unit
->au_DMAPort
+ dma_Status
);
115 outb(inb(unit
->au_DMAPort
) & ~DMA_START
, unit
->au_DMAPort
+ dma_Command
);
116 inb(unit
->au_DMAPort
+ dma_Command
);
117 inb(unit
->au_DMAPort
+ dma_Status
);
118 outb(inb(unit
->au_DMAPort
+ dma_Status
) | DMAF_Error
| DMAF_Interrupt
, unit
->au_DMAPort
+ dma_Status
);
121 #define bus ((struct ata_Bus*)hook->h_Data)
124 AROS_UFH3(void, Enumerator
,
125 AROS_UFHA(struct Hook
*, hook
, A0
),
126 AROS_UFHA(OOP_Object
*, Device
, A2
),
127 AROS_UFHA(APTR
, message
,A1
))
131 IPTR ProductID
, VendorID
;
133 OOP_AttrBase __IHidd_PCIDev
= OOP_ObtainAttrBase(IID_Hidd_PCIDevice
);
135 struct TagItem attrs
[] = {
136 { aHidd_PCIDevice_isMaster
, TRUE
},
140 D(bug("[ATA.scanbus] got device\n"));
142 OOP_GetAttr(Device
, aHidd_PCIDevice_ProductID
, &ProductID
);
143 OOP_GetAttr(Device
, aHidd_PCIDevice_VendorID
, &VendorID
);
144 OOP_GetAttr(Device
, aHidd_PCIDevice_Base4
, &IOBase
);
146 D(bug("[ATA.scanbus] IDE device %04x:%04x - DMA registers at %x\n",
147 ProductID
, VendorID
, IOBase
));
151 if (bus
->ab_Port
== 0x1f0)
153 if (bus
->ab_Units
[0])
154 bus
->ab_Units
[0]->au_DMAPort
= IOBase
;
155 if (bus
->ab_Units
[1])
156 bus
->ab_Units
[1]->au_DMAPort
= IOBase
;
158 else if (bus
->ab_Port
== 0x170)
160 if (bus
->ab_Units
[0])
161 bus
->ab_Units
[0]->au_DMAPort
= IOBase
+ 8;
162 if (bus
->ab_Units
[1])
163 bus
->ab_Units
[1]->au_DMAPort
= IOBase
+ 8;
167 D(bug("[ATA] Bus0 status says %02x, Bus1 status says %02x\n",
168 inb(IOBase
+ 2), inb(IOBase
+ 10)));
170 OOP_SetAttrs(Device
, attrs
);
172 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice
);
180 VOID
dma_Init(struct ata_Bus
*bus
)
184 D(bug("[ATA.DMA] Generic init\n"));
186 pci
= OOP_NewObject(NULL
, CLID_Hidd_PCI
, NULL
);
190 struct Hook FindHook
= {
191 h_Entry
: (IPTR (*)())Enumerator
,
195 struct TagItem Requirements
[] = {
196 {tHidd_PCI_Class
, 0x01},
197 {tHidd_PCI_SubClass
, 0x01},
201 struct pHidd_PCI_EnumDevices enummsg
= {
202 mID
: OOP_GetMethodID(IID_Hidd_PCI
, moHidd_PCI_EnumDevices
),
204 requirements
: (struct TagItem
*)&Requirements
,
207 OOP_DoMethod(pci
, (OOP_Msg
)msg
);
209 OOP_DisposeObject(pci
);