00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00047 #include "StdAfx.h"
00048 #include "System.h"
00049 #include "DMA.h"
00050 #include "AliM1543C.h"
00051
00055 CDMA::CDMA(CConfigurator* cfg, CSystem* c) : CSystemComponent(cfg, c)
00056 {
00057 int i;
00058
00059
00060 c->RegisterMemory(this, 0, U64(0x00000801fc000000), 16);
00061 c->RegisterMemory(this, 1, U64(0x00000801fc0000c0), 32);
00062 c->RegisterMemory(this, 2, U64(0x00000801fc000080), 16);
00063 c->RegisterMemory(this, 3, U64(0x00000801fc000480), 16);
00064 for(i = 0; i < 8; i++)
00065 {
00066 state.channel[i].c_lobyte = true;
00067 state.channel[i].a_lobyte = true;
00068 }
00069
00070 printf("dma: $Id: DMA.cpp,v 1.5 2008/03/14 15:30:51 iamcamiel Exp $\n");
00071 }
00072
00076 CDMA::~CDMA()
00077 { }
00078 int CDMA::DoClock()
00079 {
00080 return 0;
00081 }
00082
00083 u64 CDMA::ReadMem(int index, u64 address, int dsize)
00084 {
00085 u64 ret;
00086 u8 data;
00087 int num;
00088 switch(dsize)
00089 {
00090 case 32:
00091 ret = ReadMem(index, address, 8);
00092 ret |= ReadMem(index, address + 1, 8) << 8;
00093 ret |= ReadMem(index, address + 2, 8) << 16;
00094 ret |= ReadMem(index, address + 3, 8) << 32;
00095 return ret;
00096
00097 case 16:
00098 ret = ReadMem(index, address, 8);
00099 ret |= ReadMem(index, address + 1, 8) << 8;
00100 return ret;
00101
00102 case 8:
00103 if(index == 1)
00104 address >>= 1;
00105 switch(index)
00106 {
00107 case 0:
00108 case 1:
00109 switch(address)
00110 {
00111 case 0x00:
00112 case 0x02:
00113 case 0x04:
00114 case 0x06:
00115 num = ((int) address / 2) + (index * 4);
00116 if(state.channel[num].a_lobyte)
00117 {
00118 data = state.channel[num].current & 0xff;
00119 state.channel[num].a_lobyte = false;
00120 }
00121 else
00122 {
00123 data = (state.channel[num].current >> 8) & 0xff;
00124 state.channel[num].a_lobyte = true;
00125 }
00126 break;
00127
00128 case 0x01:
00129 case 0x03:
00130 case 0x05:
00131 case 0x07:
00132 num = (((int) address - 1) / 2) + (index * 4);
00133 if(state.channel[num].c_lobyte)
00134 {
00135 data = state.channel[num].count & 0xff;
00136 state.channel[num].c_lobyte = false;
00137 }
00138 else
00139 {
00140 data = (state.channel[num].count >> 8) & 0xff;
00141 state.channel[num].c_lobyte = true;
00142 }
00143 break;
00144
00145 default:
00146 data = 0;
00147
00148
00149 }
00150 break;
00151
00152 case 2:
00153 case 3:
00154 data = 0;
00155 break;
00156
00157 default:
00158 FAILURE(InvalidArgument, "dma: ReadMem index out of range");
00159 }
00160
00161 #if defined(DEBUG_DMA)
00162 printf("dma: read %d,%02x: %02x. \n", index, address, data);
00163 #endif
00164 return data;
00165 }
00166 }
00167
00168 void CDMA::WriteMem(int index, u64 address, int dsize, u64 data)
00169 {
00170 int num;
00171 switch(dsize)
00172 {
00173 case 32:
00174 WriteMem(index, address + 0, 8, (data >> 0) & 0xff);
00175 WriteMem(index, address + 1, 8, (data >> 8) & 0xff);
00176 WriteMem(index, address + 2, 8, (data >> 16) & 0xff);
00177 WriteMem(index, address + 3, 8, (data >> 24) & 0xff);
00178 return;
00179
00180 case 16:
00181 WriteMem(index, address + 0, 8, (data >> 0) & 0xff);
00182 WriteMem(index, address + 1, 8, (data >> 8) & 0xff);
00183 return;
00184
00185 case 8:
00186 if(index == 1)
00187 address >>= 1;
00188 #if defined(DEBUG_DMA)
00189 printf("dma: write %d,%02x: %02x. \n", index, address, data);
00190 #endif
00191 switch(index)
00192 {
00193 case 0:
00194 case 1:
00195 switch(address)
00196 {
00197 case 0x00:
00198 case 0x02:
00199 case 0x04:
00200 case 0x06:
00201 num = ((int) address / 2) + (index * 4);
00202 if(state.channel[num].a_lobyte)
00203 {
00204 state.channel[num].base = (u8) data;
00205 state.channel[num].a_lobyte = false;
00206 }
00207 else
00208 {
00209 state.channel[num].base |= ((u8) data << 8);
00210 state.channel[num].current = state.channel[num].base;
00211 state.channel[num].a_lobyte = true;
00212 }
00213 break;
00214
00215 case 0x01:
00216 case 0x03:
00217 case 0x05:
00218 case 0x07:
00219 num = (((int) address - 1) / 2) + (index * 4);
00220 if(state.channel[num].c_lobyte)
00221 {
00222 state.channel[num].count = (u8) data;
00223 state.channel[num].c_lobyte = false;
00224 }
00225 else
00226 {
00227 state.channel[num].count |= ((u8) data << 8);
00228 state.channel[num].c_lobyte = true;
00229 }
00230 break;
00231
00232 case 0x08:
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 state.controller[index].command = data;
00250 break;
00251
00252 case 0x09:
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 state.controller[index].writereq = data;
00265 break;
00266
00267 case 0x0a:
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 state.controller[index].mask = data;
00280 break;
00281
00282 case 0x0b:
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 state.controller[index].mode = data;
00304 break;
00305
00306 case 0x0c:
00307 for(num = index * 4; num < (index * 4) + 3; num++)
00308 {
00309 state.channel[num].a_lobyte = true;
00310 state.channel[num].c_lobyte = true;
00311 }
00312 break;
00313
00314 case 0x0d:
00315 #if defined(DEBUG_DMA)
00316 printf("DMA-I-RESET: DMA %d reset.", index);
00317 #endif
00318 state.controller[index].status = 0;
00319 state.controller[index].command = 0;
00320 state.controller[index].writereq = 0;
00321 state.controller[index].mode = 0;
00322 state.controller[index].mask = 0x0f;
00323 break;
00324
00325 case 0x0e:
00326 state.controller[index].mask = 0x00;
00327 break;
00328
00329 case 0x0f:
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 state.controller[index].mask = data;
00340 break;
00341
00342 default:
00343 FAILURE(NotImplemented, "dma: don't know what to do");
00344 }
00345 break;
00346
00347 case 2:
00348 case 3:
00349 switch(address)
00350 {
00351 case 1: num = 2; break;
00352 case 2: num = 3; break;
00353 case 3: num = 1; break;
00354 case 7: num = 0; break;
00355 case 9: num = 6; break;
00356 case 0xa: num = 7; break;
00357 case 0xb: num = 5; break;
00358 default: printf("dma: Unknown page register: %x\n", address); return;
00359 }
00360
00361 if(index == 2)
00362 state.channel[num].pagebase = (state.channel[num].pagebase & 0xff00) | (u8) data;
00363 else
00364 state.channel[num].pagebase = (state.channel[num].pagebase & 0xff) | (data << 8);
00365
00366
00367 break;
00368
00369 default:
00370 FAILURE(InvalidArgument, "dma: ReadMem index out of range");
00371 }
00372
00373 return;
00374 }
00375 }
00376
00377 static u32 dma_magic1 = 0x65324387;
00378 static u32 dma_magic2 = 0x24092875;
00379
00383 int CDMA::SaveState(FILE* f)
00384 {
00385 long ss = sizeof(state);
00386
00387 fwrite(&dma_magic1, sizeof(u32), 1, f);
00388 fwrite(&ss, sizeof(long), 1, f);
00389 fwrite(&state, sizeof(state), 1, f);
00390 fwrite(&dma_magic2, sizeof(u32), 1, f);
00391 printf("dma: %d bytes saved.\n", ss);
00392 return 0;
00393 }
00394
00398 int CDMA::RestoreState(FILE* f)
00399 {
00400 long ss;
00401 u32 m1;
00402 u32 m2;
00403 size_t r;
00404
00405 r = fread(&m1, sizeof(u32), 1, f);
00406 if(r != 1)
00407 {
00408 printf("dma: unexpected end of file!\n");
00409 return -1;
00410 }
00411
00412 if(m1 != dma_magic1)
00413 {
00414 printf("dma: MAGIC 1 does not match!\n");
00415 return -1;
00416 }
00417
00418 fread(&ss, sizeof(long), 1, f);
00419 if(r != 1)
00420 {
00421 printf("dma: unexpected end of file!\n");
00422 return -1;
00423 }
00424
00425 if(ss != sizeof(state))
00426 {
00427 printf("dma: STRUCT SIZE does not match!\n");
00428 return -1;
00429 }
00430
00431 fread(&state, sizeof(state), 1, f);
00432 if(r != 1)
00433 {
00434 printf("dma: unexpected end of file!\n");
00435 return -1;
00436 }
00437
00438 r = fread(&m2, sizeof(u32), 1, f);
00439 if(r != 1)
00440 {
00441 printf("dma: unexpected end of file!\n");
00442 return -1;
00443 }
00444
00445 if(m2 != dma_magic2)
00446 {
00447 printf("dma: MAGIC 1 does not match!\n");
00448 return -1;
00449 }
00450
00451 printf("dma: %d bytes restored.\n", ss);
00452 return 0;
00453 }