Bestcomm tasks and interrupts on MPC5200(B)
Frank Bennett
bennett78 at lpbroadband.net
Wed Jan 21 02:59:46 EST 2009
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 at 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;
}
}
}
More information about the Linuxppc-dev
mailing list