revert between 56095 -> 55830 in arch
[AROS.git] / arch / m68k-amiga / expansion / configboard.c
blob776a3be21c6b5e43d22e9c0b94106f7032bbf893
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #define DEBUG 1
10 #include <aros/debug.h>
11 #include "expansion_intern.h"
12 #include <proto/expansion.h>
13 #include <aros/asmcall.h>
15 /* See rom/expansion/configboard.c for documentation */
17 #define Z3SLOT 0x01000000
19 /* do not touch. Ugly hack. UAE direct JIT versions need this */
20 /* check UAE expansion.c for ugly details */
21 AROS_UFH5(void, writeexpansion,
22 AROS_UFHA(APTR, board, A0),
23 AROS_UFHA(APTR, configdev, A3), // <- configdev = A3. This is important.
24 AROS_UFHA(UBYTE, type, D0),
25 AROS_UFHA(UWORD, startaddr, D1),
26 AROS_UFHA(struct ExpansionBase *, ExpansionBase, A6))
28 AROS_USERFUNC_INIT
30 if (type == ERT_ZORROII) {
31 WriteExpansionByte(board, 18, startaddr);
32 } else {
33 WriteExpansionWord(board, 17, startaddr);
36 AROS_USERFUNC_EXIT
40 #include <clib/expansion_protos.h>
42 AROS_LH2(BOOL, ConfigBoard,
43 AROS_LHA(APTR , board, A0),
44 AROS_LHA(struct ConfigDev *, configDev, A1),
45 struct ExpansionBase *, ExpansionBase, 10, Expansion)
47 AROS_LIBFUNC_INIT
49 UBYTE type = configDev->cd_Rom.er_Type & ERT_TYPEMASK;
50 ULONG size = configDev->cd_BoardSize;
52 D(bug("Configuring board: cd=%p mfg=%d prod=%d size=%08x type=%02x\n",
53 configDev, configDev->cd_Rom.er_Manufacturer, configDev->cd_Rom.er_Product, size, configDev->cd_Rom.er_Type));
55 if (type == ERT_ZORROIII) {
56 UWORD prevslot, newslot;
57 UWORD endslot = 255;
58 UWORD slotsize = (size + 0x00ffffff) / Z3SLOT;
59 if (IntExpBase(ExpansionBase)->z3Slot == 0)
60 IntExpBase(ExpansionBase)->z3Slot = 0x40000000 / Z3SLOT;
61 prevslot = IntExpBase(ExpansionBase)->z3Slot;
62 // handle alignment
63 newslot = (prevslot + slotsize - 1) & ~(slotsize - 1);
64 D(bug("size=%d prev=%d new=%d end=%d\n", slotsize, prevslot, newslot, endslot));
65 if (newslot + slotsize <= endslot) {
66 ULONG startaddr = newslot * Z3SLOT;
67 configDev->cd_BoardAddr = (APTR)startaddr;
68 configDev->cd_SlotAddr = IntExpBase(ExpansionBase)->z3Slot;
69 configDev->cd_SlotSize = slotsize;
70 configDev->cd_Flags |= CDF_CONFIGME;
71 IntExpBase(ExpansionBase)->z3Slot = newslot + slotsize;
72 AROS_UFC5NR(void, writeexpansion,
73 AROS_UFCA(APTR, board, A0),
74 AROS_UFCA(APTR, configDev, A3),
75 AROS_UFCA(UBYTE, type, D0),
76 AROS_UFCA(UWORD, (startaddr >> 16), D1),
77 AROS_UFCA(struct ExpansionBase*, ExpansionBase, A6)
79 D(bug("-> configured, %p - %p\n", startaddr, startaddr + configDev->cd_BoardSize - 1));
80 return TRUE;
82 } else {
83 ULONG start, end, addr, step;
84 UBYTE *space;
85 UBYTE area;
87 for (area = 0; area < 2; area++) {
89 if (area == 0 && size >= 8 * E_SLOTSIZE)
90 continue;
92 if (area == 0) {
93 start = 0x00E90000;
94 end = 0x00EFFFFF;
95 } else {
96 start = 0x00200000;
97 end = 0x009FFFFF;
99 space = IntExpBase(ExpansionBase)->z2Slots;
100 step = 0x00010000;
101 for (addr = start; addr < end; addr += step) {
102 ULONG startaddr = addr;
103 UWORD offset = startaddr / (E_SLOTSIZE * SLOTSPERBYTE);
104 BYTE bit = 7 - ((startaddr / E_SLOTSIZE) % SLOTSPERBYTE);
105 UBYTE res = space[offset];
106 ULONG sizeleft = size;
108 if (res & (1 << bit))
109 continue;
111 if (size < 4 * 1024 * 1024) {
112 // handle alignment, 128k boards must be 128k aligned and so on..
113 if ((startaddr & (size - 1)) != 0)
114 continue;
115 } else {
116 // 4M and 8M boards have different alignment requirements
117 if (startaddr != 0x00200000 && startaddr != 0x00600000)
118 continue;
121 // found free start address
122 if (size >= E_SLOTSIZE * SLOTSPERBYTE) {
123 // needs at least 1 byte and is always aligned to byte
124 while (space[offset] == 0 && sizeleft >= E_SLOTSIZE && offset <= end / (E_SLOTSIZE * SLOTSPERBYTE)) {
125 offset++;
126 sizeleft -= E_SLOTSIZE * SLOTSPERBYTE;
128 } else {
129 // bit by bit small board check (fits in one byte)
130 while ((res & (1 << bit)) == 0 && sizeleft >= E_SLOTSIZE && bit >= 0) {
131 sizeleft -= E_SLOTSIZE;
132 bit--;
136 if (sizeleft >= E_SLOTSIZE)
137 continue;
139 configDev->cd_BoardAddr = (APTR)startaddr;
140 configDev->cd_Flags |= CDF_CONFIGME;
141 configDev->cd_SlotAddr = (startaddr >> 16);
142 configDev->cd_SlotSize = size >> 16;
143 AROS_UFC5NR(void, writeexpansion,
144 AROS_UFCA(APTR, board, A0),
145 AROS_UFCA(APTR, configDev, A3),
146 AROS_UFCA(UBYTE, type, D0),
147 AROS_UFCA(UWORD, (startaddr >> 16), D1),
148 AROS_UFCA(struct ExpansionBase*, ExpansionBase, A6)
150 D(bug("-> configured, %p - %p\n", startaddr, startaddr + configDev->cd_BoardSize - 1));
152 // do not remove this, configDev->cd_BoardAddr
153 // might have changed inside writeexpansion
154 startaddr = (ULONG)configDev->cd_BoardAddr;
155 offset = startaddr / (E_SLOTSIZE * SLOTSPERBYTE);
156 bit = 7 - ((startaddr / E_SLOTSIZE) % SLOTSPERBYTE);
157 sizeleft = size;
158 // now allocate area we reserved
159 while (sizeleft >= E_SLOTSIZE) {
160 space[offset] |= 1 << bit;
161 sizeleft -= E_SLOTSIZE;
162 bit--;
165 return TRUE;
170 D(bug("Configuration failed!\n"));
171 if (!(configDev->cd_Flags & ERFF_NOSHUTUP)) {
172 configDev->cd_Flags |= CDF_SHUTUP;
173 WriteExpansionByte(board, 19, 0); // SHUT-UP!
174 } else {
175 // uh?
177 return FALSE;
179 AROS_LIBFUNC_EXIT
180 } /* ConfigBoard */