On Wed, 24 Oct 2007 15:37:10 -0700 David Brownell <[email protected]> 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; }
Attachment:
Makefile
Description: Binary data
- References:
- mmc_spi stopped working
- From: Pierre Ossman <[email protected]>
- Re: mmc_spi stopped working
- From: David Brownell <[email protected]>
- Re: mmc_spi stopped working
- From: Pierre Ossman <[email protected]>
- Re: mmc_spi stopped working
- From: David Brownell <[email protected]>
- mmc_spi stopped working
- Prev by Date: Re: [PATCH 1/4] stringbuf: A string buffer implementation
- Next by Date: [GIT PULL] MMX update
- Previous by thread: Re: mmc_spi stopped working
- Next by thread: [2.6 patch] hwmon/ibmpex.c: fix NULL dereference
- Index(es):