Dave Best wrote:
I'm trying to write a driver which uses the Local Plus Bus on my MPC5200B and
therefore have to use BestComm DMA, which requires me to use a Gen_BD task for
data transfer with Local Plus.
I tried to follow the fec driver that is currently used and took a peek at the
mpc52xx-ac97 driver which at least uses the same kind of bus as I.
Initialising the task, resetting and enabling works fine. Even request_irq reports no error, but when I start a transfer it hangs and if I am lucky, an interrupt occurs after quite some time. But it's always the BestComm ethernet rx task which produces an RFIFO interrupt, presumably after the watchdog catches on.
If this happens my interrupt occurs to.
I tried to debug this situation but I am still clueless.
If I use the MPC5200 Interrupt emulation registers to force an interrupt for my
interface to occur, nothing happens except that it hangs.
Any hints, tips or help appreciated.
Below is a Disassembler I wrote a couple years ago. Just paste
the hex of interest in the array below, re-compile and run.
Cheers,
-Frank
Dave
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
/*
* disasm.c - disassembler for MPC5200 Bestcomm DMA Firmware
* copy and paste task code into fw, compile a run
* by Frank bennett, 3/29/2006
*
* Based on Freescale pdf "SmartDMA Hand-Assembly Guides"
*
* TODO:
* o add inc[0:7] array (maybe var) to deternmine proper term condition (upper
3 bits)
* o need to review sheet 3 of the pdf
* o simulator would be nice
*
*/
// Task12 (TASK_GEN_TX_BD) : Start of TDT -> 0xf0008528
//
linuxppc_2_4_devel/arch/ppc/5xxx_io/bestcomm/code_dma/image_rtos1/"dma_image.reloc.c
//
// 31,30,29,28|27,26,25,24|23,22,21,20|19,18,17,16|15,14,13,12|11,10, 9, 8| 7,
6, 5, 4| 3, 2, 1, 0
// 0 0 0 1 0 0| 0 0 0 0 0| 0 0| 0 0| 0| 0 0 0 1 0 0| 1| 1 0
0 0 0 1| 0 0 0
// 0x10001308, /* 000C DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=2 */
// 1 0 0| 1 1 0 0 1 0| 0| 0| 1 1 0 0 1 0| 0 0| 0| 0 0 0 0 0
0| 1 1 0| 1 1 0
// 0x99190036, /* 002C LCD: idx2 = idx2; idx2 once var0; idx2 += inc6 */
// 31,30,29,28|27,26,25,24|23,22,21,20|19,18,17,16|15,14,13,12|11,10, 9, 8| 7,
6, 5, 4| 3, 2, 1, 0
// 1 0| 0 1 1 0, 0 1 0 1, 1 0 0, 0 0 1| 1 0| 1 0 0 1 0 0
0 0 1 0 0 0 0
// 0x9950d210
/* Task12(TASK_GEN_TX_BD): Start of TDT -> 0xf0008528 */
unsigned long fw[] = {
0x800220e3, /* 0000 LCD: idx0 = var0, idx1 = var4; idx1 <= var3; idx0 +=
inc4, idx1 += inc3 */
0x13e01010, /* 0004 DRD1A: var4 = var2; FN=0 MORE init=24 WS=0 RS=0 */
0xb8808264, /* 0008 LCD: idx2 = *idx1, idx3 = var1; idx2 < var9; idx2 +=
inc4, idx3 += inc4 */
0x10001308, /* 000C DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=2 */
0x60140002, /* 0010 DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2
*/
0x0cccfcca, /* 0014 DRD2B1: *idx3 = EU3(); EU3(*idx3,var10) */
0xd9190300, /* 0018 LCDEXT: idx2 = idx2; idx2 > var12; idx2 += inc0 */
0xb8c5e009, /* 001C LCD: idx3 = *(idx1 + var00000015); ; idx3 += inc1 */
0x03fec398, /* 0020 DRD1A: *idx0 = *idx3; FN=0 init=24 WS=3 RS=2 */
0x9919826a, /* 0024 LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 +=
inc5, idx3 += inc2 */
0x0feac398, /* 0028 DRD1A: *idx0 = *idx3; FN=0 TFD INT init=24 WS=1
RS=2 */
0x99190036, /* 002C LCD: idx2 = idx2; idx2 once var0; idx2 += inc6 */
0x60000005, /* 0030 DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0
*/
0x0c4cf889, /* 0034 DRD2B1: *idx1 = EU3(); EU3(idx2,var9) */
0x000001f8, /* 0038 NOP */
0x9950d210,
0x2c4cf889,
0
};
union
{
unsigned long i;
struct
{
unsigned sb:3; // [02:00] increment #2
unsigned sa:3; // [05:03] increment #1
unsigned tc:6; // [11:06] variable to which idx is compared
unsigned drtc:1; // [12] dr ? *(tc) : (tc)
unsigned tu:2; // [14:13] term usage 00-idx_a, 01-idx_b, 10- lit
init 11-no cond
unsigned ib:6; // [20:15] init_b
unsigned drib:1; // [21] dr ? *(init_a) : (init_a)
unsigned p:1; // [22] indx plus offset
unsigned ia:6; // [28:23] init_a
unsigned dria:1; // [29] dr ? *(init_a) : (init_a)
unsigned ext:1; // [30] = 2 or 3 for LCD
unsigned op:1; // [31] = 2 or 3 for LCD
} lcd;
struct
{
unsigned ll:13; // [12:00] literal init low
unsigned tu:2; // [14:13] term usage == 2
unsigned lh:15; // [29:15] literal init hi
unsigned bas:1; // [30] = 2 or 3 for LCD
unsigned op:1; // [31] = 2 or 3 for LCD
} lcdl;
struct
{
unsigned fn:3; // [02:00]
unsigned src:6; // [08:03]
unsigned drs:1; // [09] deref src?
unsigned dst:6; // [15:10]
unsigned drd:1; // [16] deref dst? scal?
unsigned ws:2; // [18:17] 0-32bit, 1-1 byte, 2-16 word,
3-dynamic/reserved??
unsigned rs:2; // [20:19] 0-32bit, 1-1 byte, 2-16 word,
3-dynamic/reserved??
unsigned init:5; // [25:21]
unsigned intr:1; // [26]
unsigned tfd:1; // [27]
unsigned more:1; // [28]
unsigned type:1; // [29]
unsigned ext:1; // [30]
unsigned op:1; // [31] = 0 for DRD
} drd1a;
struct
{
unsigned eu3:4; // [03:00] Execution Unit3 Function number
unsigned eu2:4; // [07:04] Execution Unit3 Function number
unsigned eu1:4; // [11:08] Execution Unit3 Function number
unsigned eu0:4; // [15:12] Execution Unit3 Function number
unsigned drd:1; // [16] deref dst? scal?
unsigned ws:2; // [18:17] 0-32bit, 1-1 byte, 2-16 word,
3-dynamic/reserved??
unsigned rs:2; // [20:19] 0-32bit, 1-1 byte, 2-16 word,
3-dynamic/reserved??
unsigned init:5; // [25:21]
unsigned int:1; // [26]
unsigned tfd:1; // [27]
unsigned more:1; // [28]
unsigned type:1; // [29]
unsigned ext:1; // [30]
unsigned op:1; // [31] = 0 for DRD
} drd2a;
struct
{
unsigned od1:6; // [05:00] EU operand 1
unsigned od0:6; // [11:06] EU operand 0
unsigned eu:2; // [13:12] EU#, only #3 available on MPC5200
unsigned mems:6; // [19:14] memory write source
unsigned drds:1; // [20]
unsigned rsv2:1; // [21]
unsigned memd:6; // [27:22] memory write destination
unsigned rsv1:1; // [28] reserved?
unsigned type:1; // [29]
unsigned ext:1; // [30]
unsigned op:1; // [31] = 0 for DRD
} drd2b1;
struct
{
unsigned odb1:6; // [05:00] EUb operand 1/3/5/7
unsigned odb0:6; // [11:06] EUb operand 0/2/4/6
unsigned eub:2; // [13:12] EUb#, only #3 available on MPC5200
unsigned oda1:6; // [19:14] EUa operand 1/3/5/7
unsigned oda0:6; // [25:20] EUa operand 0/2/4/6
unsigned eua:2; // [27:26] EUa#, only #3 available on MPC5200
unsigned rsv1:1; // [28]
unsigned type:1; // [29]
unsigned ext:1; // [30]
unsigned op:1; // [31] = 0 for DRD
} drd2b2;
} x;
// Condition codes (first 4 bits of the increments)
// >= c
// > 4
// once 0
// != 6
// <= a
// < 2
char *ft[] = {
"ld_acc", "unld_acc", "and", "or", "xor" "andn", "not",
"add", "sub", "lsh", "rsh", "crc8", "crc16", "crc32",
"endian32", "endian16"
};
char s[8];
indvar (int i)
{
switch ((i & 0x3f) >> 4)
{
case 0:
sprintf (s, "var%d", i & 0x1f); // varN
break;
case 1:
sprintf (s, "inc%d", i & 0x07); // incN
break;
case 2: // extraN
case 3:
sprintf (s, "idx%d", i & 0x0f); // idxN
break;
}
}
#define L2 LLev*2
main ()
{
int i, j, LLev = 0, drdt, ex = 0, ml;
char in[12];
for (i = 0; fw[i]; i++)
{
x.i = fw[i];
if (x.i == 0x1f8)
printf ("0x%08x, // NOP\n", x.i);
else if (x.lcd.op) // LCD
{
if (LLev == 0)
strcpy (in, "");
else
strcpy (in, " ");
if (x.lcd.ext) // LCDEXT
{
indvar (x.lcd.tc);
printf
("0x%08x, // %sLCDEXT: idx%d=idx%d; idx%d >%s%s ; idx%d +=
inc%d\n",
x.i, in, L2, L2, L2, x.lcd.drtc ? "*" : " ", s, L2,
x.lcd.sb);
} else if (x.lcd.tu == 2) // LCDLIT
{
printf ("0x%08x, // %sLCDLIT: idx%d = 0x%07x ??\n",
x.i, in, L2, (x.lcdl.lh << 13) | x.lcdl.ll);
} else // LCD
{
printf ("0x%08x, // %sLCD: ", x.i, in);
if (x.lcd.p) // indexed p-plus
{
indvar (x.lcd.ia);
printf ("idx%d = %s(%s + ", L2 + 1, x.lcd.dria ? "*" : " ",
s);
indvar (x.lcd.ib);
printf ("%s%s); ; ", x.lcd.drib ? "*" : " ", s);
} else
{
indvar (x.lcd.ia);
printf ("idx%d=%s%s, ", L2, x.lcd.dria ? "*" : " ", s);
indvar (x.lcd.ib);
printf ("idx%d=%s%s, ", L2 + 1, x.lcd.drib ? "*" : " ", s);
}
if (x.lcd.tu < 2)
{
indvar (x.lcd.tc);
printf ("idx%d <=%s%s, ", (x.lcd.tu == 0) ? L2 : L2 + 1,
x.lcd.drtc ? "*" : " ", s);
}
if (x.lcd.tu != 3)
printf ("idx%d += inc%01x, ", L2, x.lcd.sa);
printf ("idx%d += inc%01x\n", L2 + 1, x.lcd.sb);
ex = 0;
}
}
else
{
// DRD
if (LLev == 0)
strcpy (in, " ");
else
strcpy (in, " ");
drdt = (ex << 2) | (x.drd1a.ext << 1) | x.drd1a.type;
switch (drdt)
{
case 0: // DRD1A
printf ("0x%08x, // %sDRD1A: ", x.i, in);
indvar (x.drd1a.dst);
printf ("%s%s =", x.drd1a.drd ? "*" : " ", s);
indvar (x.drd1a.src);
printf ("%s%s; ", x.drd1a.drs ? "*" : " ", s);
printf ("FN=%d (%s) ", x.drd1a.fn, ft[x.drd1a.fn]);
if (x.drd1a.more)
printf ("MORE ");
if (x.drd1a.tfd)
printf ("TFD ");
if (x.drd1a.intr)
printf ("INT ");
printf ("init=%d ", x.drd1a.init);
printf ("WS=%d RS=%d \n", x.drd1a.ws, x.drd1a.rs);
break;
case 3: // DRD2A
ex = x.drd2a.ext;
printf ("0x%08x, // %sDRD2A: ", x.i, in);
printf ("EU0=0 EU1=0 EU2=0 EU3=%d (%s) EXT init=%d ",
x.drd2a.eu3, ft[x.drd2a.eu3], x.drd2a.init);
printf ("WS=%d RS=%d \n", x.drd2a.ws, x.drd2a.rs);
break;
case 4: // DRD2B1
printf ("0x%08x, // %sDRD2B1: ", x.i, in);
indvar (x.drd2b1.memd); // mems ??
printf ("*%s=EU%d(); ", s, x.drd2b1.eu);
indvar (x.drd2b1.od0); printf ("EU%d(%s, ", x.drd2b1.eu, s);
indvar (x.drd2b1.od1); printf ("%s) \n", s);
break;
case 5: // DRD2B2
case 7: // DRD2B2?
printf ("0x%08x, // %sDRD2B2: ", x.i, in);
indvar (x.drd2b2.oda0); printf ("EU%d(%s, ", x.drd2b2.eub, s);
indvar (x.drd2b2.oda1); printf ("%s) , ", s);
indvar (x.drd2b2.odb0); printf ("EU%d(%s, ", x.drd2b2.eua, s);
indvar (x.drd2b2.odb1); printf ("%s) ??\n", s);
break;
case 1:
case 2:
case 6:
printf ("fix_me\n");
ex = x.drd1a.ext;
break;
}
LLev |= 1;
}
}
}
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev