Some fix for scrolling with lasso.
[tangerine.git] / arch / common / ata.device / dma_generic.c
blob4191777d1c065fd098d96aa6f04a2a698262cadb
1 /*
2 Copyright © 2004-2006, The AROS Development Team. All rights reserved
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #define DEBUG 0
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>
16 #include <oop/oop.h>
18 #include <hidd/pci.h>
20 #include <dos/bptr.h>
22 #include <proto/exec.h>
23 #include <proto/oop.h>
25 #include "ata.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;
37 int i;
39 D(bug("[DMA] Setup PRD for %d bytes at %x\n",
40 size, ptr));
42 /*
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)
57 break;
60 if (size <= prd[1].prde_Address - prd[0].prde_Address)
62 prd[0].prde_Length = size;
63 size = 0;
65 else
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;
73 i = 1;
75 while(size >= 65536)
77 prd[i].prde_Length = 0; /* 64KB in one PRD */
78 size -= 65536;
79 i++;
82 if (size > 0)
84 prd[i].prde_Length = size;
85 i++;
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
96 if (io)
97 outb(DMA_WRITE, unit->au_DMAPort + dma_Command);
98 else
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)
123 static
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))
129 AROS_USERFUNC_INIT
131 IPTR ProductID, VendorID;
132 IPTR IOBase;
133 OOP_AttrBase __IHidd_PCIDev = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
135 struct TagItem attrs[] = {
136 { aHidd_PCIDevice_isMaster, TRUE },
137 { TAG_DONE, 0UL}
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));
149 if (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);
174 AROS_USERFUNC_EXIT
178 #undef bus
180 VOID dma_Init(struct ata_Bus *bus)
182 OOP_Object *pci;
184 D(bug("[ATA.DMA] Generic init\n"));
186 pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
188 if (pci)
190 struct Hook FindHook = {
191 h_Entry: (IPTR (*)())Enumerator,
192 h_Data: bus,
195 struct TagItem Requirements[] = {
196 {tHidd_PCI_Class, 0x01},
197 {tHidd_PCI_SubClass, 0x01},
198 {TAG_DONE, 0x00}
201 struct pHidd_PCI_EnumDevices enummsg = {
202 mID: OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_EnumDevices),
203 callback: &FindHook,
204 requirements: (struct TagItem *)&Requirements,
205 }, *msg = &enummsg;
207 OOP_DoMethod(pci, (OOP_Msg)msg);
209 OOP_DisposeObject(pci);