lkml.org 
[lkml]   [2007]   [Oct]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: mmc_spi stopped working
On Wed, 24 Oct 2007 15:37:10 -0700
David Brownell <david-b@pacbell.net> wrote:

> On Monday 22 October 2007, Pierre Ossman wrote:
> >
> > I've been testing a bit more here, and I can't get this particular bug.
>
> It's not just a bug, it's a regression ... a new bug which
> was introduced by some patch. ;)
>

It's a bug in the card, which is what I was referring to. ;)

>
> SPI works fine on all the MMC and SD cards I've got here,
> other than the minor glitch fixed by the "don't just probe"
> patch I sent.
>

Lucky you. :)

> As you know, to be spec-conformant they *must* support SPI.

I never recall which of the different specs require SPI (not all do).

> Agreed, there are too many vendors who don't appear to value
> following specs. If those cards which are using the MMC or
> SD trade marks, you might notify the relevant consortium and
> asking them to fix those vendors. ;)
>

Hah! The SD and MMC boys seem to have no interest in people following the specs, considering all the shite that is out there.

>
> > As for your card, could you send me a dump as I'm unable to produce
> > the issue here?
>
> I'm not sure what you mean by "dump", but appended the sysfs attributes
> produced after I disabled that new "just probe" mechanism.
>

A dmesg with MMC_DEBUG so that I can see just how the card misbehaves.

Also, I see you're dying for my decodecid and decodecsd progs. ;)
I've included both.

Rgds
--
-- Pierre Ossman

Linux kernel, MMC maintainer http://www.kernel.org
PulseAudio, core developer http://pulseaudio.org
rdesktop, core developer http://www.rdesktop.org
#include "crc7.h"

#define CRC7_POLYNOMIAL 0x89 /* x^7 + x^3 + 1 */

static unsigned char crc7_syndrome_table[256];

/*
* Generate a table of CRC-7 syndromes for x^7 * each possible input byte
*/
void
gen_crc7_syndrome_table (void)
{
int i, j, syndrome;
for (i = 0; i < 256; ++i)
{
syndrome = ((i & 0x80) != 0)? i ^ CRC7_POLYNOMIAL : i;
for (j = 0; j < 7; ++j)
{
if (((syndrome <<= 1) & 0x80) != 0)
{
syndrome ^= CRC7_POLYNOMIAL;
}
}
crc7_syndrome_table[i] = (unsigned char) syndrome;
}
}

unsigned char
calc_crc7(unsigned long* resp)
{
unsigned char crc7_accum = 0;
unsigned char byte;
int i, j;

for (i = 0;i < 4;i++)
{
for (j = 0;j < 4;j++)
{
if ((i == 3) && (j == 3))
break;
byte = resp[i] >> (24 - 8 * j);
crc7_accum = crc7_syndrome_table[(crc7_accum << 1) ^ byte];
}
}

return crc7_accum;
}
void gen_crc7_syndrome_table (void);
unsigned char calc_crc7(unsigned long* resp);

#define UNSTUFF_BITS(resp,start,size) \
({ \
const unsigned long __mask = (1 << (size)) - 1; \
const int __off = 3 - ((start) / 32); \
const int __shft = (start) & 31; \
unsigned long __res; \
\
__res = resp[__off] >> __shft; \
if ((size) + __shft >= 32) \
__res |= resp[__off-1] << (32 - __shft); \
__res & __mask; \
})
#include <stdlib.h>
#include <stdio.h>

#include "crc7.h"
#include "decode.h"

int main(int argc, char** argv)
{
int i, j;
int temp, e, m;
char ch;
unsigned long resp[4];

if (argc != 2)
return -1;

if (strlen(argv[1]) != 8 * 4)
return -1;

for (i = 0;i < 4;i++)
{
resp[i] = 0;
for (j = 0;j < 8;j++)
{
resp[i] <<= 4;
ch = tolower(argv[1][i * 8 + j]);
if (isdigit(ch))
resp[i] |= ch - '0';
else if (isxdigit(ch))
resp[i] |= ch - 'a' + 0xA;
else
return -1;
}
}

printf("Manufacturer ID: %d\n", UNSTUFF_BITS(resp, 120, 8));
printf("OEM/Application ID: %d\n", UNSTUFF_BITS(resp, 104, 16));

printf("Product name: %c%c%c%c%c%c\n",
(char)UNSTUFF_BITS(resp, 96, 8),
(char)UNSTUFF_BITS(resp, 88, 8),
(char)UNSTUFF_BITS(resp, 80, 8),
(char)UNSTUFF_BITS(resp, 72, 8),
(char)UNSTUFF_BITS(resp, 64, 8),
(char)UNSTUFF_BITS(resp, 56, 8));

printf("Product revision: %d:%d\n",
UNSTUFF_BITS(resp, 52, 4),
UNSTUFF_BITS(resp, 48, 4));

printf("Serial: %08x\n", UNSTUFF_BITS(resp, 16, 32));

printf("Manufacturing date: %d/%d\n",
UNSTUFF_BITS(resp, 12, 4) + 1997,
UNSTUFF_BITS(resp, 8, 4));

gen_crc7_syndrome_table();
printf("CRC: ");
if (UNSTUFF_BITS(resp, 1, 7) == calc_crc7(resp))
printf("OK");
else
printf("Fail");
printf("\n");

return 0;
}
#include <stdlib.h>
#include <stdio.h>

#include "crc7.h"
#include "decode.h"

static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
};

static const unsigned char tran_mant[] = {
0, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};

static const unsigned int tacc_exp[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
};

static const unsigned int tacc_mant[] = {
0, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};

static const unsigned int min_cur[] = {
5, 10, 50, 100, 250, 350, 600, 1000,
};

static const unsigned int max_cur[] = {
10, 50, 100, 250, 350, 450, 800, 2000,
};

int main(int argc, char** argv)
{
int i, j;
int temp, e, m;
char ch;
unsigned long resp[4];

if (argc != 2)
return -1;

if (strlen(argv[1]) != 8 * 4)
return -1;

for (i = 0;i < 4;i++)
{
resp[i] = 0;
for (j = 0;j < 8;j++)
{
resp[i] <<= 4;
ch = tolower(argv[1][i * 8 + j]);
if (isdigit(ch))
resp[i] |= ch - '0';
else if (isxdigit(ch))
resp[i] |= ch - 'a' + 0xA;
else
return -1;
}
}

printf("CSD Version: ");
temp = UNSTUFF_BITS(resp, 126, 2);
switch (temp)
{
case 0:
printf("v1.0");
break;
case 1:
printf("v1.1");
break;
case 2:
printf("v1.2");
break;
default:
printf("Unknown [%d]", temp);
}
printf("\n");

printf("MMCA Version: ");
temp = UNSTUFF_BITS(resp, 122, 4);
switch (temp)
{
case 0:
printf("v1.0 to v1.2");
break;
case 1:
printf("v1.4");
break;
case 2:
printf("v2.0 to v2.2");
break;
case 3:
printf("v3.1 to v3.3");
break;
default:
printf("Unknown [%d]", temp);
}
printf("\n");

m = UNSTUFF_BITS(resp, 115, 4);
e = UNSTUFF_BITS(resp, 112, 3);
printf("TACC: %d ns\n", (tacc_exp[e] * tacc_mant[m] + 9) / 10);
printf("NSAC: %d clks\n", UNSTUFF_BITS(resp, 104, 8) * 100);

m = UNSTUFF_BITS(resp, 99, 4);
e = UNSTUFF_BITS(resp, 96, 3);
printf("Max rate: %d kHz\n", tran_exp[e] * tran_mant[m] / 1000);

printf("Command classes: ");
temp = UNSTUFF_BITS(resp, 84, 12);
for (i = 0;i < 12;i++)
{
if (temp & (1 << i))
{
switch (i)
{
case 0:
printf("basic, ");
break;
case 1:
printf("stream read, ");
break;
case 2:
printf("block read, ");
break;
case 3:
printf("stream write, ");
break;
case 4:
printf("block write, ");
break;
case 5:
printf("erase, ");
break;
case 6:
printf("write prot., ");
break;
case 7:
printf("lock, ");
break;
case 8:
printf("app. specific, ");
break;
case 9:
printf("I/O mode, ");
break;
default:
printf("class %d, ", i);
}
}
}
printf("\n");

temp = 1 << UNSTUFF_BITS(resp, 80, 4);
printf("Read block size: %d bytes\n", temp);

temp = 1 << UNSTUFF_BITS(resp, 22, 4);
printf("Write block size: %d bytes\n", temp);

printf("Partial read: ");
if (UNSTUFF_BITS(resp, 79, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("Partial write: ");
if (UNSTUFF_BITS(resp, 21, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("Read misalign: ");
if (UNSTUFF_BITS(resp, 77, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("Write misalign: ");
if (UNSTUFF_BITS(resp, 78, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("DSR: ");
if (UNSTUFF_BITS(resp, 76, 1))
printf("Yes");
else
printf("No");
printf("\n");

e = UNSTUFF_BITS(resp, 47, 3);
m = UNSTUFF_BITS(resp, 62, 12);
printf("Capacity: %d blocks %d %d\n", ((1 + m) << (e + 2)), m, e);

printf("Min read current: %0.1f mA\n",
(float)min_cur[UNSTUFF_BITS(resp, 59, 3)]/10);
printf("Max read current: %0.1f mA\n",
(float)max_cur[UNSTUFF_BITS(resp, 56, 3)]/10);

printf("Min write current: %0.1f mA\n",
(float)min_cur[UNSTUFF_BITS(resp, 53, 3)]/10);
printf("Max write current: %0.1f mA\n",
(float)max_cur[UNSTUFF_BITS(resp, 50, 3)]/10);

m = UNSTUFF_BITS(resp, 42, 5);
e = UNSTUFF_BITS(resp, 37, 5);
printf("Erase group size: %d blocks\n", (m+1) * (e+1));

printf("WP group size: %d erase group(s)\n", UNSTUFF_BITS(resp, 32, 5));

printf("WP enable: ");
if (UNSTUFF_BITS(resp, 31, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("R2W factor: %d\n", UNSTUFF_BITS(resp, 26, 3));

printf("Content protect: ");
if (UNSTUFF_BITS(resp, 16, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("File format: ");
if (UNSTUFF_BITS(resp, 15, 1))
printf("Reserved");
else
{
switch (UNSTUFF_BITS(resp, 10, 2))
{
case 0:
printf("Hard disk");
break;
case 1:
printf("Floppy");
break;
case 2:
printf("Universal");
break;
case 3:
printf("Unknown");
break;
}
}
printf("\n");

printf("Copy: ");
if (UNSTUFF_BITS(resp, 14, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("Perm write protect: ");
if (UNSTUFF_BITS(resp, 13, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("Tmp write protect: ");
if (UNSTUFF_BITS(resp, 12, 1))
printf("Yes");
else
printf("No");
printf("\n");

printf("ECC: ");
switch (UNSTUFF_BITS(resp, 8, 2))
{
case 0:
printf("none");
break;
case 1:
printf("BCH(512,512)");
break;
default:
printf("Reserved");
}
printf("\n");

gen_crc7_syndrome_table();
printf("CRC: ");
if (UNSTUFF_BITS(resp, 1, 7) == calc_crc7(resp))
printf("OK");
else
printf("Fail");
printf("\n");

return 0;
}
[unhandled content-type:application/octet-stream]
\
 
 \ /
  Last update: 2007-10-27 14:55    [W:0.062 / U:0.048 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site