chiark / gitweb /
mtd_probe: add autodetection for xD cards
authorMaxim Levitsky <maximlevitsky@gmail.com>
Wed, 23 Jun 2010 20:20:29 +0000 (22:20 +0200)
committerKay Sievers <kay.sievers@vrfy.org>
Wed, 23 Jun 2010 20:20:29 +0000 (22:20 +0200)
commit 2599cabd36770785a13bf884049d649d385fd80c
Author: Maxim Levitsky <maximlevitsky@gmail.com>
Date:   Fri Jun 18 02:08:48 2010 +0300

Add autodetection for xD/smartmedia cards
This can easily be extended for other types of FTL

Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Makefile.am
extras/mtd_probe/75-probe_mtd.rules [new file with mode: 0644]
extras/mtd_probe/mtd_probe.c [new file with mode: 0644]
extras/mtd_probe/mtd_probe.h [new file with mode: 0644]
extras/mtd_probe/probe_smartmedia.c [new file with mode: 0644]

index bafe4c7facb2e4155ed72fc4a69237285693d830..5e9234a6990056629eac72336733a8aca29472c9 100644 (file)
@@ -466,6 +466,21 @@ dist_udevrules_DATA += \
 
 libexec_PROGRAMS += extras/mobile-action-modeswitch/mobile-action-modeswitch
 
+# ------------------------------------------------------------------------------
+# mtd_probe - autoloads FTL module for mtd devices
+# ------------------------------------------------------------------------------
+extras_mtd_probe_mtd_probe_SOURCES =  \
+                                                       extras/mtd_probe/mtd_probe.c \
+                                                       extras/mtd_probe/mtd_probe.h \
+                                                       extras/mtd_probe/probe_smartmedia.c
+
+extras_mtd_probe_mtd_probe_CPPFLAGS = $(AM_CPPFLAGS)
+
+dist_udevrules_DATA += extras/mtd_probe/75-probe_mtd.rules
+
+libexec_PROGRAMS += extras/mtd_probe/mtd_probe
+
 # ------------------------------------------------------------------------------
 # keymap - map custom hardware's multimedia keys
 # ------------------------------------------------------------------------------
diff --git a/extras/mtd_probe/75-probe_mtd.rules b/extras/mtd_probe/75-probe_mtd.rules
new file mode 100644 (file)
index 0000000..1d1b398
--- /dev/null
@@ -0,0 +1,10 @@
+#probe mtd devices for FTL
+
+ACTION!="add", GOTO="mtd_probe_end"
+
+KERNEL=="mtd*ro", IMPORT{program}="mtd_probe $tempnode"
+KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", RUN+="/sbin/modprobe sm_ftl"
+
+
+LABEL="mtd_probe_end"
+
diff --git a/extras/mtd_probe/mtd_probe.c b/extras/mtd_probe/mtd_probe.c
new file mode 100644 (file)
index 0000000..d335b06
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * mtd_probe.c
+ * This file is part of mtd_probe
+ *
+ * Copyright (C) 2010 - Maxim Levitsky
+ *
+ * mtd_probe is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mtd_probe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with mtd_probe; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+#include "mtd_probe.h"
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(int argc, char** argv) {
+
+       if (argc != 2) {
+               printf("usage: mtd_probe /dev/mtd[n]\n");
+               return 1;
+       }
+
+       int mtd_fd = open(argv[1], O_RDONLY);
+       if (mtd_fd == -1) {
+               perror("open");
+               exit(-1);
+       }
+
+       mtd_info_t mtd_info;
+       int error = ioctl(mtd_fd, MEMGETINFO, &mtd_info);
+       if (error == -1) {
+               perror("ioctl");
+               exit(-1);
+       }
+
+       probe_smart_media(mtd_fd, &mtd_info);
+       return -1;
+}
diff --git a/extras/mtd_probe/mtd_probe.h b/extras/mtd_probe/mtd_probe.h
new file mode 100644 (file)
index 0000000..845a7a1
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * mtd_probe.h
+ * This file is part of mtd_probe
+ *
+ * Copyright (C) 2010 - Maxim Levitsky
+ *
+ * mtd_probe is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mtd_probe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with mtd_probe; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+#include <mtd/mtd-user.h>
+
+/* Full oob structure as written on the flash */
+struct sm_oob {
+       uint32_t reserved;
+       uint8_t data_status;
+       uint8_t block_status;
+       uint8_t lba_copy1[2];
+       uint8_t ecc2[3];
+       uint8_t lba_copy2[2];
+       uint8_t ecc1[3];
+} __attribute__((packed));
+
+
+/* one sector is always 512 bytes, but it can consist of two nand pages */
+#define SM_SECTOR_SIZE         512
+
+/* oob area is also 16 bytes, but might be from two pages */
+#define SM_OOB_SIZE            16
+
+/* This is maximum zone size, and all devices that have more that one zone
+   have this size */
+#define SM_MAX_ZONE_SIZE       1024
+
+/* support for small page nand */
+#define SM_SMALL_PAGE          256
+#define SM_SMALL_OOB_SIZE      8
+
+
+void probe_smart_media(int mtd_fd, mtd_info_t *info);
diff --git a/extras/mtd_probe/probe_smartmedia.c b/extras/mtd_probe/probe_smartmedia.c
new file mode 100644 (file)
index 0000000..ab6edea
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * probe_smartmedia.c
+ * This file is part of mtd_probe
+ *
+ * Copyright (C) 2010 - Maxim Levitsky
+ *
+ * mtd_probe is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mtd_probe is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with mtd_probe; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mtd/mtd-user.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "mtd_probe.h"
+
+static const uint8_t cis_signature[] = {
+       0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20
+};
+
+
+void probe_smart_media(int mtd_fd, mtd_info_t* info) {
+
+       char* cis_buffer = malloc(SM_SECTOR_SIZE);
+       if (!cis_buffer)
+               return;
+
+       if (info->type != MTD_NANDFLASH)
+               goto exit;
+
+       int sector_size = info->writesize;
+       int block_size = info->erasesize;
+       int size_in_megs = info->size / (1024 * 1024);
+       int spare_count;
+
+
+       if (sector_size != SM_SECTOR_SIZE && sector_size != SM_SMALL_PAGE)
+               goto exit;
+
+       switch(size_in_megs) {
+       case 1:
+       case 2:
+               spare_count = 6;
+               break;
+       case 4:
+               spare_count = 12;
+               break;
+       default:
+               spare_count = 24;
+               break;
+       }
+
+
+       int offset;
+       int cis_found = 0;
+
+       for (offset = 0 ; offset < block_size * spare_count ;
+                                               offset += sector_size) {
+
+               lseek(mtd_fd, SEEK_SET, offset);
+               if (read(mtd_fd, cis_buffer, SM_SECTOR_SIZE) == SM_SECTOR_SIZE){
+                       cis_found = 1;
+                       break;
+               }
+       }
+
+       if (!cis_found)
+               goto exit;
+
+       if (memcmp(cis_buffer, cis_signature, sizeof(cis_signature)) != 0 &&
+               (memcmp(cis_buffer + SM_SMALL_PAGE, cis_signature,
+                       sizeof(cis_signature)) != 0))
+               goto exit;
+
+       printf("MTD_FTL=smartmedia\n");
+       free(cis_buffer);
+       exit(0);
+exit:
+       free(cis_buffer);
+       return;
+}