SD Karte oder MMC Card über Slot 2 machbar?

Boxenweitwurf
just_me
Einsteiger
Einsteiger
Beiträge: 123
Registriert: Montag 28. November 2005, 11:31

SD Karte oder MMC Card über Slot 2 machbar?

Beitrag von just_me »

Wie wärs mit dem Anschluss einer MMC oder SD-Card im SPI Modus wie z.B. bei:
http://wrt-wiki.bsr-clan.de/index.php?t ... sys_WRT54G

Der Bootloader u-Boot sollte hiermit eigentlich zurechtkommen können und da eine SD oder MMC Karte ja über einen Adapter vom PC aus beschreibbar ist, gäbs da ja noch einen echten Handhabungsvorteil... ... ...

Und zusätzliche 32 MByte oder 512 MByte wären ja auch nicht von Pappe:)
Z.B. müsste man eigentlich damit auch MP3/Ogg (oder sehr kurze/einfache Videoclips) abspielen können.

IMHO ein klarer Punktvorteil bei Funktionalität/Preis/Kapazität/Beschaffbarkeit/Risiko/Aufwand!)

- Frieder

(PS: Dieses Posting ist inspiriert durch den Thread http://forum.tuxbox-cvs.sourceforge.net ... hp?t=39999)
petgun
Tuxboxer
Tuxboxer
Beiträge: 5001
Registriert: Montag 11. November 2002, 15:26

Beitrag von petgun »

...fuer mich ist das eine Spielerei..
Die erreichbare Schreib-/ Lesegeschwindigkeit liegt bei ~200 KB/s.
..was soll man damit sinnvolles anfangen?
just_me
Einsteiger
Einsteiger
Beiträge: 123
Registriert: Montag 28. November 2005, 11:31

Beitrag von just_me »

Die erreichbare Schreib-/ Lesegeschwindigkeit liegt bei ~200 KB/s.
Nun, da ist sicher das letzte Wort noch nicht gesprochen:)
Wenn man sich unter http://kiel.kool.dk:27/mmc.c die allerunterste Routine mmc_spi_io() anschaut:

Code: Alles auswählen

static unsigned char mmc_spi_io(unsigned char data_out)
{
  int i;
  unsigned char result = 0, tmp_data = 0;
  
  for(i=0; i<8; i++) {
    if(data_out & (0x01 << (7-i)))
      port_state |= SD_DI;
    else
      port_state &= ~SD_DI;
    
    *gpioaddr_output = port_state;
    port_state |= SD_CLK;
    *gpioaddr_output = port_state;
    
    tmp_data = *gpioaddr_input;
    
    port_state &= ~SD_CLK;
    *gpioaddr_output = port_state;
    
    result <<= 1;
    
    if(tmp_data & SD_DO)
      result |= 1;
  }
  
  return(result);
}
fällt auf, dass hier noch nicht alle Register gezogen sind:

- result wird unnötigerweise auf 0 gesetzt
- die Schleife ist nicht "unrolled"
- in der Schleife wird ein aufwändiges (0x01 << (7-i)) berechnet
- es ist C und noch kein Assembler und das Setzen/Löschen/Testen der jeweiligen Pins scheint mir unnötig kompliziert
- bei dem Linksysrouter gibt es keine Hardwareunterstützung für SPI und so läuft das ganze mit "BitBanging". Vielleicht gibts Hardwareunterstützung an Slot2?

Und selbst wenn keine Hardwareunterstützung da ist, wird eine 66MHz CPU schon noch mit mehr als 200 kByte pro Sekunde bitbanged IO betreiben können:
330 Zyklen pro Byte ( >40 Zyklen pro Bit) sind IMHO kein hartes Limit - ohne den PowerPC näher zu kennen gehe ich davon aus, dass das 2 bis 5fache schon drin sein dürfte.
Also Video muss vermutlich "leider draussen bleiben" aber für "subVideo-Anvendungen" ist einiger Raum da.

Frieder[/b]
petgun
Tuxboxer
Tuxboxer
Beiträge: 5001
Registriert: Montag 11. November 2002, 15:26

Beitrag von petgun »

just_me hat geschrieben:[ohne den PowerPC näher zu kennen gehe ich davon aus, dass das 2 bis 5fache schon drin sein dürfte.
...mag sein bei 100% CPU-Last...aber die wird hier neuerdings fuer was anderes verschwendet.
Rudi Ratlos 4711
IDE-Frickler und Berufspessimist
Beiträge: 464
Registriert: Samstag 27. Juli 2002, 21:13

Beitrag von Rudi Ratlos 4711 »

just_me hat geschrieben: Und selbst wenn keine Hardwareunterstützung da ist, wird eine 66MHz CPU schon noch mit mehr als 200 kByte pro Sekunde bitbanged IO betreiben können
Dir ist schon klar daß die CPU im Linksys mit 200Mhz läuft....

RR4711
Astra 19.2/Hotbird 13.0
Philips SAT 2xI Avia 600/eNX mit heilem :D Frontpanel-Prozessor aber irgendwas anderem kaputt :(
Philips SAT 2xI Avia 600/eNX Base 1.6.3/ CRAMFS vom 28.11.2002
Nokia SAT 2xI Avia 500/GTX 32/32/8 BMON1.0/jffs2 Head 28.01.03
just_me
Einsteiger
Einsteiger
Beiträge: 123
Registriert: Montag 28. November 2005, 11:31

Beitrag von just_me »

Rudi Ratlos 4711 hat geschrieben:Dir ist schon klar daß die CPU im Linksys mit 200Mhz läuft....
Ja, ist mir klar (ich hätte es hier erwähnen sollen, danke).
chris-berlin
Interessierter
Interessierter
Beiträge: 91
Registriert: Donnerstag 17. März 2005, 08:20

Beitrag von chris-berlin »

Wäre es nicht möglich über COM1 oder den Internen Modem Port ein Reader anzuschließen um MP3, Videos usw. abzuspielen ? Das wäre doch was, ich habe letztens DVD Player gesehen die schon Cardreader haben.

MfG

Chris
Houdini
Developer
Beiträge: 2183
Registriert: Mittwoch 10. Dezember 2003, 07:59

Beitrag von Houdini »

über COM1 ... Videos usw. abzuspielen ?
wenn das gehen würde gäbs kein USB/Firewire,
sprich:viel zu langsam
just_me
Einsteiger
Einsteiger
Beiträge: 123
Registriert: Montag 28. November 2005, 11:31

Beitrag von just_me »

..was soll man damit sinnvolles anfangen?
Dir ist schon klar daß die CPU im Linksys mit 200Mhz läuft....
Hmm, ich glaube, die Situation ist besser als es zunächst aussieht!)

Da ich des PowerPC-Assemblercodes nicht mächtig bin folgt hier ein Beispiel, bei dem ich mit einer 8 Bit CPU argumentiere.

Der SPI Code

Code: Alles auswählen

extern volatile bit MOSI;     /* master out, slave in */
extern volatile bit MISO;     /* master in, slave out */
extern volatile bit MCLK;     /* master clock */

unsigned char spi_io(unsigned char out_byte)
{
     unsigned char i=8;
     do {
         MOSI = out_byte & 0x80;
         out_byte <<= 1;
         MCLK = 1;
         if(MISO)
             out_byte += 1;
         MCLK = 0;
     } while(--i);
    return out_byte;
}
läßt sich auf einer etwa 25 Jahre alten 8 bit CPU (Intel_8051) runterkochen auf:

Code: Alles auswählen

        mov     a,dpl
        mov     r3,#0x08
00103$:
        add     a,acc
        mov     _MOSI,c
        setb    _MCLK
        jnb     _MISO,00102$
        inc     a
00102$:
        clr     _MCLK
        djnz    r3,00103$

        mov     dpl,a
        ret
Dies entspricht etwa 300 ns pro Bit auf einem 50 MHz 8051 Derivat von Silabs, so dass man dort ab 400 kByte/s auf ein hartes Limit (für bitbanged I/O) stossen würde.

Und selbst wenn der PowerPC nicht über 200 kByte/s käme, würde dies eine CPU Load von lediglich 10% für das Lesen eines 196 kBit/s MP3 Streams bedeuten - 90% wären also noch anderweitig zu gebrauchen :D


Frieder

Disclaimer: Alle Rechenfehler sind selbstgemacht!)
Npq
Senior Member
Beiträge: 1339
Registriert: Donnerstag 24. April 2003, 12:12

Beitrag von Npq »

Probier's am besten mal aus, zwischen Theorie und Praxis ist ja immer ein kleiner Unterschied.

Übrigens besitzt der 823 sogar ein SPI-Interface, allerdings hängt an den 4 Pins die Ansteuerung für das Alpha-CAM bzw. der DS2401 und das wird alles per PIO angesprochen.
just_me
Einsteiger
Einsteiger
Beiträge: 123
Registriert: Montag 28. November 2005, 11:31

Beitrag von just_me »

Hallo Npq,
wie ist denn die Pin Belegung von Slot 2 und welches sind die entsprechenden Register?
Unter http://wiki.tuxbox-cvs.sourceforge.net/Hauptseite "DBox2 Hardware" bin ich leider nicht fündig geworden :gruebel:
vSaAmTp
Einsteiger
Einsteiger
Beiträge: 232
Registriert: Sonntag 17. März 2002, 22:14

Beitrag von vSaAmTp »

die idee ist garnet schlecht. wär damit booten möglich? wär ja dann fast wie ne dreambox mit stick. festplatte ist ja auch in arbeit.
DBoxBaer
Senior Member
Beiträge: 255
Registriert: Donnerstag 25. August 2005, 11:34

Beitrag von DBoxBaer »

vSaAmTp hat geschrieben:die idee ist garnet schlecht. wär damit booten möglich? wär ja dann fast wie ne dreambox mit stick. festplatte ist ja auch in arbeit.
In dem Fall kann man es gleich beim CPLD mit anschliessen, das sind ja tatsächlich nur ein paar Pins bei SD-Cards: Die Idee hatte ich vor einer ganzen Weile schon mal, aber hatte keine konkrete Anwendung vor Augen.
Bilder direkt von der Karte der Kamera könnte aber ab und zu interessant sein.
Auf jeden Fall ist das von der Hardware recht einfach. Und der Rest ist dann Software (TM) :-)

Ach so: Booten geht recht sicher auch davon (egal wie man das SD-Card Interface nun anschliesst), solange der U-Boot im Flash der Box das unterstützt: Und im Prinzip ist es sogar einfacher wenn man erstmal nur booten will, im Kernel ist die Welt doch um einiges komplizierter...

Ciao,

Dboxbaer
... und der Rest ist dann Software (TM)
just_me
Einsteiger
Einsteiger
Beiträge: 123
Registriert: Montag 28. November 2005, 11:31

Beitrag von just_me »

DBoxBaer hat geschrieben:In dem Fall kann man es gleich beim CPLD mit anschliessen, das sind ja tatsächlich nur ein paar Pins bei SD-Cards: Die Idee hatte ich vor einer ganzen Weile schon mal, aber hatte keine konkrete Anwendung vor Augen.
Wenn sich auf dem Board Platz für den Anschluss einer
- MMC-Card, RS-MMC Card (18x24x1.4 mm³) oder notfalls MMCmicro (14x12x1.1 mm³)
oder einer
- SD-Card, miniSD-Card oder microSD "TransFlash" (15x11x1 mm³)
fände, wäre das schon hammerhart:)

Alle der genannten Varianten liessen sich über CPLD wohl mit mehr als der 10 MBit Baudrate der Ethernet Schnittstelle auch im SPI Modus betreiben...

Und auf lange Sicht gäbe es noch I/O Karten für SD oder MMC (z.B. SD WLAN Karten, die im Prinzip mit den 10 MBit Halbduplex der eingebauten Ethernetschnittstelle mithalten könnten, falls irgendwann mal Treiber dafür verfügbar werden.)
Tommy
Tuxboxer
Tuxboxer
Beiträge: 4332
Registriert: Dienstag 7. Mai 2002, 17:04

Beitrag von Tommy »

Alle der genannten Varianten liessen sich über CPLD wohl mit mehr als der 10 MBit Baudrate der Ethernet Schnittstelle auch im SPI Modus betreiben...
Kann man denn dann nicht ein interface bauen was eine HD als SD Karte tarnt?
---------------------------
Alle weiteren Infos findest Du im WIKI
Bitte vor dem posten Boardregeln lesen und verstehen!
Wie erstelle ich ein Bootlog? Wo finde ich die FAQ?
DBoxBaer
Senior Member
Beiträge: 255
Registriert: Donnerstag 25. August 2005, 11:34

Beitrag von DBoxBaer »

Tommy hat geschrieben:
Alle der genannten Varianten liessen sich über CPLD wohl mit mehr als der 10 MBit Baudrate der Ethernet Schnittstelle auch im SPI Modus betreiben...
Kann man denn dann nicht ein interface bauen was eine HD als SD Karte tarnt?
Wofür? Das man die interne Festplatte über ein Kabel an einen SD Card Reader stecken kann? Oder um so ein IDE Interface an die Box zu bauen? Dann hat man eine Hardware, die das SD Interface enthält und eine zweite, die eine Platte mit SD Interface ausstattet. Hmm, klingt für mich komplizierter als es sein muss. Dann schon lieber 100MBit oder USB2.0 :-)

Zurück zum SD Anschluss:
Die diversen SDIO Karten sind mir heute morgen auch mal in den Sinn gekommen. Aber ob sich das lohnt, weiss ich nicht: Da darf man die Performance dann nämlich nicht mehr ignorieren, und dann wird die Hardware doch wieder kompliziert. Und das Treiberproblem erst.

Ich finde ein SD Card Interface aber gerade deshalb attraktiv weil es (ohne Perfomance "Übertreibungen") recht einfach sein kann und ein paar interessante Nutzungen erlaubt, gerade auch mit interner Festplatte:

- Mal eben ein paar Fotos von der Digicam auf dem Fernsehe anschauen zu können oder diese auch gleich auf die interne Platte zu kopieren.
- Gilt auch für MP3 Dateien: Die MP3 Sammlung auf ner Platte in der Box updaten oder von dort kopieren.

Aber auch ein neues Image (bzw. Teile davon, also neuen Kernel, Module, oder irgendwelche Config-Dateien) auch mal ohne Netzwerk auf die Box kopieren zu können gefällt mir als Möglichkeit. Oder temporär mal ein "TestImage" von so einer Karte zu booten...

Ciao,

Dboxbaer
... und der Rest ist dann Software (TM)
TaGana
Interessierter
Interessierter
Beiträge: 96
Registriert: Samstag 6. Oktober 2001, 00:00

Beitrag von TaGana »

Hier mal der angepasste treiber und die hardware Beschreibung.

Der init läuft durch (Panasonic 512MB SD Karte):

mmc Hardware init
mmc Card init
mmc Card init *1*
mmc Card init *2*
Size = 483840 KByte, hardsectsize = 512 byte, sectors = 967680

Aber beim:

register_disk(&hd_gendisk, MKDEV(MAJOR_NR,0), 1<<6,&mmc_bdops, hd_sizes[0]*2);


kommt ein segfault, das sollten mal die kernel experten hier untersuchen.

Partition check:
mmca:Oops: kernel access of bad area, sig: 11
NIP: C3BF33E4 XER: 20000000 LR: C0083810 SP: C17C5C30 REGS: c17c5b80 TRAP: 0300 Not tainted
MSR: 00001032 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 11
DAR: 00000810, DSISR: 0000100B
TASK = c17c4000[147] 'insmod' Last syscall: 128
last math 00000000 last altivec 00000000
GPR00: C0083810 C17C5C30 C17C4000 C015073C 00009032 00000001 00000080 00000000
GPR08: 00000045 C015075C C011B95C 00000800 22004022 100375EC 00000000 00000000
GPR16: 00000001 10030000 10030000 00000000 00009032 10046E38 0000003F 00000000
GPR24: 00000001 C3BF4960 C01C30C8 00000001 C17C4000 C17C5C90 00000000 C3BF33B4
Call backtrace:
C0084B30 C0083810 C0014708 C0035CB8 C0020528 C00231D4 C005844C
C00588A0 C0057DA4 C005839C C0058278 C3BF3ED4 C3BF3F4C C3BF3FDC

Code: Alles auswählen

/* Makefile
TARGET  := mmc
TUXBOX  := -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -fsigned-char -msoft-float -pipe -ffixed-r2 -Wno-uninitialized -mmultiple -mstring -mcpu=823
INCLUDE := -I/dbox2/cdk/bin/powerpc-tuxbox-linux-gnu/include
CFLAGS  := -DMODULE -D__KERNEL__ ${TUXBOX} ${INCLUDE}
CC      := /dbox2/cdk/bin/powerpc-tuxbox-linux-gnu-gcc

${TARGET}.o: ${TARGET}.c

.PHONY: clean

clean:
	rm -rf {TARGET}.o
*/

#include <linux/delay.h>
#include <linux/timer.h>

#include <linux/module.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/blkpg.h>
#include <linux/hdreg.h>
#include <linux/major.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/8xx_immap.h>

#define DEVICE_NAME "mmc"
#define DEVICE_NR(device) (MINOR(device))
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#define MAJOR_NR 121

#include <linux/blk.h>

MODULE_AUTHOR("Madsuk/Rohde/TaGana");
MODULE_DESCRIPTION("Driver MMC/SD-Cards");
MODULE_SUPPORTED_DEVICE("Nokia dbox2 on com2");
MODULE_LICENSE("GPL");

// dbox2 connection sheme and driver update by TaGana/2006
//
//     |
//    _----------------------------------------
//   | |        dbox2 tuner                   |
//    ~----------------------------------------
//     |
//     |
//     |        1  3  5  7  9 11 13 15 17 19
//     |        2  4  6  8 10 12 14 16 18 20
//     |

#define SD_DO  0x0100 // pin 14 (on SD/MMC card pin 7)
#define SD_DI  0x1000 // pin 17 (on SD/MMC card pin 2)
#define SD_CLK 0x0200 // pin 18 (on SD/MMC card pin 5)
#define SD_CS  0x0100 // pin 5  (on SD/MMC card pin 1)
//      GND           // pin 10 (on SD/MMC card pin 3+6)
//      VCC (3V)      // pin 16 (on SD/MMC card pin 4)
//
// Also connect a pullup resistor 100 KOhm from pin14 (SD_DO) to pin16 (VCC)
//
//                     ----------------
//                    / 1 2 3 4 5 6 7 x| MMC/SC Card
//                    |x               |
//

immap_t *immap=(immap_t *)IMAP_ADDR ;

/* we have only one device */
static int hd_sizes[1<<6];
static int hd_blocksizes[1<<6];
static int hd_hardsectsizes[1<<6];
static int hd_maxsect[1<<6];
static struct hd_struct hd[1<<6];

static struct timer_list mmc_timer;
static int mmc_media_detect = 0;
static int mmc_media_changed = 1;

typedef unsigned int uint32;

static void mmc_spi_cs_low(void)
{
  cpm8xx_t *cp  = (cpm8xx_t *) &immap->im_cpm;
  cp->cp_pbdat &= ~(SD_CS);
}

static void mmc_spi_cs_high(void)
{
  cpm8xx_t *cp  = (cpm8xx_t *) &immap->im_cpm;
  cp->cp_pbdat |= SD_CS;
}

static unsigned char bitarray[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

static unsigned char mmc_spi_io(unsigned char data_out)
{
  int i;
  unsigned char result = 0;
  cpm8xx_t *cp  = (cpm8xx_t *) &immap->im_cpm;
  iop8xx_t *cpi = (iop8xx_t *) &immap->im_ioport;

  for(i=0; i<8; i++) {
    if (data_out & bitarray[i])
      cp->cp_pbdat |= SD_DI;
    else
      cp->cp_pbdat &= ~SD_DI;

    cp->cp_pbdat |= SD_CLK;
    if (cpi->iop_padat & SD_DO) result |= bitarray[i];
    cp->cp_pbdat &= ~SD_CLK;
  }

  return(result);
}


static int mmc_write_block(unsigned int dest_addr, unsigned char *data)
{
	unsigned int address;
	unsigned char r = 0;
	unsigned char ab0, ab1, ab2, ab3;
	int i;

	address = dest_addr;

	ab3 = 0xff & (address >> 24);
	ab2 = 0xff & (address >> 16);
	ab1 = 0xff & (address >> 8);
	ab0 = 0xff & address;
	mmc_spi_cs_low();
	for (i = 0; i < 4; i++) mmc_spi_io(0xff);
	mmc_spi_io(0x58);
	mmc_spi_io(ab3); /* msb */
	mmc_spi_io(ab2);
	mmc_spi_io(ab1);
	mmc_spi_io(ab0); /* lsb */
	mmc_spi_io(0xff);
	for (i = 0; i < 8; i++)
	{
		r = mmc_spi_io(0xff);
		if (r == 0x00) break;
	}
	if (r != 0x00)
	{
		mmc_spi_cs_high();
		mmc_spi_io(0xff);
		return(1);
	}

	mmc_spi_io(0xfe);
	for (i = 0; i < 512; i++) mmc_spi_io(data[i]);
	for (i = 0; i < 2; i++) mmc_spi_io(0xff);

	for (i = 0; i < 1000000; i++)
	{
		r = mmc_spi_io(0xff);
		if (r == 0xff) break;
	}
	if (r != 0xff)
	{
		mmc_spi_cs_high();
		mmc_spi_io(0xff);
		return(3);
	}
	mmc_spi_cs_high();
	mmc_spi_io(0xff);
	return(0);
}

static int mmc_read_block(unsigned char *data, unsigned int src_addr)
{
	unsigned int address;
	unsigned char r = 0;
	unsigned char ab0, ab1, ab2, ab3;
	int i;

	address = src_addr;

	ab3 = 0xff & (address >> 24);
	ab2 = 0xff & (address >> 16);
	ab1 = 0xff & (address >> 8);
	ab0 = 0xff & address;

	mmc_spi_cs_low();
	for (i = 0; i < 4; i++) mmc_spi_io(0xff);
	mmc_spi_io(0x51);
	mmc_spi_io(ab3); /* msb */
	mmc_spi_io(ab2);
	mmc_spi_io(ab1);
	mmc_spi_io(ab0); /* lsb */

	mmc_spi_io(0xff);
	for (i = 0; i < 8; i++)
	{
		r = mmc_spi_io(0xff);
		if (r == 0x00) break;
	}
	if (r != 0x00)
	{
		mmc_spi_cs_high();
		mmc_spi_io(0xff);
		return(1);
	}
	for (i = 0; i < 100000; i++)
	{
		r = mmc_spi_io(0xff);
		if (r == 0xfe) break;
	}
	if (r != 0xfe)
	{
		mmc_spi_cs_high();
		mmc_spi_io(0xff);
		return(2);
	}
	for (i = 0; i < 512; i++)
	{
		r = mmc_spi_io(0xff);
		data[i] = r;
	}
	for (i = 0; i < 2; i++)
	{
		r = mmc_spi_io(0xff);
	}
	mmc_spi_cs_high();
	mmc_spi_io(0xff);

	return(0);
}

static void mmc_request(request_queue_t *q)
{
	unsigned int mmc_address;
	unsigned char *buffer_address;
	int nr_sectors;
	int i;
	int cmd;
	int rc, code;

	(void)q;
	while (1)
	{
		code = 1; // Default is success
		INIT_REQUEST;
		mmc_address = (CURRENT->sector + hd[MINOR(CURRENT->rq_dev)].start_sect) * hd_hardsectsizes[0];
		buffer_address = CURRENT->buffer;
		nr_sectors = CURRENT->current_nr_sectors;
		cmd = CURRENT->cmd;
		if (((CURRENT->sector + CURRENT->current_nr_sectors + hd[MINOR(CURRENT->rq_dev)].start_sect) > hd[0].nr_sects) || (mmc_media_detect == 0))
		{
			code = 0;
		}
		else if (cmd == READ)
		{
			spin_unlock_irq(&io_request_lock);
			for (i = 0; i < nr_sectors; i++)
			{
				rc = mmc_read_block(buffer_address, mmc_address);
				if (rc != 0)
				{
					printk("mmc: error in mmc_read_block (%d)\n", rc);
					code = 0;
					break;
				}
				else
				{
					mmc_address += hd_hardsectsizes[0];
					buffer_address += hd_hardsectsizes[0];
				}
			}
			spin_lock_irq(&io_request_lock);
		}
		else if (cmd == WRITE)
		{
			spin_unlock_irq(&io_request_lock);
			for (i = 0; i < nr_sectors; i++)
			{
				rc = mmc_write_block(mmc_address, buffer_address);
				if (rc != 0)
				{
					printk("mmc: error in mmc_write_block (%d)\n", rc);
					code = 0;
					break;
				}
				else
				{
					mmc_address += hd_hardsectsizes[0];
					buffer_address += hd_hardsectsizes[0];
				}
			}
			spin_lock_irq(&io_request_lock);
		}
		else
		{
			code = 0;
		}
		end_request(code);
	}
}


static int mmc_open(struct inode *inode, struct file *filp)
{
  //int device;
	(void)filp;

	if (mmc_media_detect == 0) return -ENODEV;

#if defined(MODULE)
	MOD_INC_USE_COUNT;
#endif
	return 0;
}

static int mmc_release(struct inode *inode, struct file *filp)
{
	(void)filp;
	fsync_dev(inode->i_rdev);
        invalidate_buffers(inode->i_rdev);

#if defined(MODULE)
	MOD_DEC_USE_COUNT;
#endif
	return 0;
}

extern struct gendisk hd_gendisk;

static int mmc_revalidate(kdev_t dev)
{
	int target, max_p, start, i;
	if (mmc_media_detect == 0) return -ENODEV;

	target = DEVICE_NR(dev);

	max_p = hd_gendisk.max_p;
	start = target << 6;
	for (i = max_p - 1; i >= 0; i--) {
		int minor = start + i;
		invalidate_device(MKDEV(MAJOR_NR, minor), 1);
		hd_gendisk.part[minor].start_sect = 0;
		hd_gendisk.part[minor].nr_sects = 0;
	}

	grok_partitions(&hd_gendisk, target, 1 << 6,
			hd_sizes[0] * 2);

	return 0;
}

static int mmc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	if (!inode || !inode->i_rdev)
		return -EINVAL;

	switch(cmd) {
	case BLKGETSIZE:
		return put_user(hd[MINOR(inode->i_rdev)].nr_sects, (unsigned long *)arg);
	case BLKGETSIZE64:
		return put_user((u64)hd[MINOR(inode->i_rdev)].
				nr_sects, (u64 *) arg);
	case BLKRRPART:
		if (!capable(CAP_SYS_ADMIN))
			return -EACCES;

		return mmc_revalidate(inode->i_rdev);
	case HDIO_GETGEO:
	{
		struct hd_geometry *loc, g;
		loc = (struct hd_geometry *) arg;
		if (!loc)
			return -EINVAL;
		g.heads = 4;
		g.sectors = 16;
		g.cylinders = hd[0].nr_sects / (4 * 16);
		g.start = hd[MINOR(inode->i_rdev)].start_sect;
		return copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0;
	}
	default:
		return blk_ioctl(inode->i_rdev, cmd, arg);
	}
}

static int mmc_card_init(void)
{
	unsigned char r = 0;
	short i, j;
	unsigned long flags;

	save_flags(flags);
	cli();

        printk("mmc Card init\n");
	mmc_spi_cs_high();
  for (i = 0; i < 1000; i++) mmc_spi_io(0xff);

	mmc_spi_cs_low();

	mmc_spi_io(0x40);
	for (i = 0; i < 4; i++) mmc_spi_io(0x00);
	mmc_spi_io(0x95);
	for (i = 0; i < 8; i++)
	{
		r = mmc_spi_io(0xff);
		if (r == 0x01) break;
	}
	mmc_spi_cs_high();
	mmc_spi_io(0xff);
	if (r != 0x01)
	{
		restore_flags(flags);
		return(1);
	}

        printk("mmc Card init *1*\n");
  for (j = 0; j < 30000; j++)
	{
		mmc_spi_cs_low();

		mmc_spi_io(0x41);
		for (i = 0; i < 4; i++) mmc_spi_io(0x00);
		mmc_spi_io(0xff);
		for (i = 0; i < 8; i++)
		{
			r = mmc_spi_io(0xff);
			if (r == 0x00) break;
		}
		mmc_spi_cs_high();
		mmc_spi_io(0xff);
		if (r == 0x00)
		{
			restore_flags(flags);
			printk("mmc Card init *2*\n");
			return(0);
		}
	}
	restore_flags(flags);

	return(2);
}

static int mmc_card_config(void)
{
	unsigned char r = 0;
	short i;
	unsigned char csd[32];
	unsigned int c_size;
	unsigned int c_size_mult;
	unsigned int mult;
	unsigned int read_bl_len;
	unsigned int blocknr = 0;
	unsigned int block_len = 0;
	unsigned int size = 0;

	mmc_spi_cs_low();
	for (i = 0; i < 4; i++) mmc_spi_io(0xff);
	mmc_spi_io(0x49);
	for (i = 0; i < 4; i++) mmc_spi_io(0x00);
	mmc_spi_io(0xff);
	for (i = 0; i < 8; i++)
	{
		r = mmc_spi_io(0xff);
		if (r == 0x00) break;
	}
	if (r != 0x00)
	{
		mmc_spi_cs_high();
		mmc_spi_io(0xff);
		return(1);
	}
	for (i = 0; i < 8; i++)
	{
		r = mmc_spi_io(0xff);
		if (r == 0xfe) break;
	}
	if (r != 0xfe)
	{
		mmc_spi_cs_high();
		mmc_spi_io(0xff);
		return(2);
	}
	for (i = 0; i < 16; i++)
	{
		r = mmc_spi_io(0xff);
		csd[i] = r;
	}
	for (i = 0; i < 2; i++)
	{
		r = mmc_spi_io(0xff);
	}
	mmc_spi_cs_high();
	mmc_spi_io(0xff);
	if (r == 0x00) return(3);

	c_size = csd[8] + csd[7] * 256 + (csd[6] & 0x03) * 256 * 256;
	c_size >>= 6;
	c_size_mult = csd[10] + (csd[9] & 0x03) * 256;
	c_size_mult >>= 7;
	read_bl_len = csd[5] & 0x0f;
	mult = 1;
	mult <<= c_size_mult + 2;
	blocknr = (c_size + 1) * mult;
	block_len = 1;
	block_len <<= read_bl_len;
	size = block_len * blocknr;
	size >>= 10;

	for(i=0; i<(1<<6); i++) {
	  hd_blocksizes[i] = 1024;
	  hd_hardsectsizes[i] = block_len;
	  hd_maxsect[i] = 256;
	}
	hd_sizes[0] = size;
	hd[0].nr_sects = blocknr;


	printk("Size = %d, hardsectsize = %d, sectors = %d\n",
	       size, block_len, blocknr);

	return 0;
}

static int mmc_hardware_init(void)
{
  cpm8xx_t *cp  = (cpm8xx_t *) &immap->im_cpm;
  iop8xx_t *cpi = (iop8xx_t *) &immap->im_ioport;

  printk("mmc Hardware init\n");
  cp->cp_pbpar &=  ~(SD_CLK | SD_DI | SD_CS);
  cp->cp_pbodr &=  ~(SD_CLK | SD_DI | SD_CS);
  cp->cp_pbdir |=   (SD_CLK | SD_DI | SD_CS);
  cpi->iop_papar &= ~SD_DO;
  cpi->iop_paodr &= ~SD_DO;
  cpi->iop_padir &= ~SD_DO;

  // Clock low
  cp->cp_pbdat &= ~(SD_CLK | SD_DI | SD_CS);

  return 0;
}
/*
static int mmc_check_media_change(kdev_t dev)
{
	(void)dev;
	if (mmc_media_changed == 1)
	{
		mmc_media_changed = 0;
		return 1;
	}
	else return 0;
}
*/
static struct block_device_operations mmc_bdops =
{
	open: mmc_open,
	release: mmc_release,
	ioctl: mmc_ioctl,
#if 0
	check_media_change: mmc_check_media_change,
	revalidate: mmc_revalidate,
#endif
};

static struct gendisk hd_gendisk = {
	major:		MAJOR_NR,
	major_name:	DEVICE_NAME,
	minor_shift:	6,
	max_p:		1 << 6,
	part:		hd,
	sizes:		hd_sizes,
	fops:		&mmc_bdops,
};

static int mmc_init(void)
{
	int rc;

	rc = mmc_hardware_init();

	if ( rc != 0)
	{
		printk("mmc: error in mmc_hardware_init (%d)\n", rc);
		return -1;
	}

	rc = mmc_card_init();
	if ( rc != 0)
	{
		// Give it an extra shot
		rc = mmc_card_init();
		if ( rc != 0)
		{
			printk("mmc: error in mmc_card_init (%d)\n", rc);
			return -1;
		}
	}

	memset(hd_sizes, 0, sizeof(hd_sizes));
	rc = mmc_card_config();
	if ( rc != 0)
	{
		printk("mmc: error in mmc_card_config (%d)\n", rc);
		return -1;
	}


	blk_size[MAJOR_NR] = hd_sizes;

	memset(hd, 0, sizeof(hd));
	hd[0].nr_sects = hd_sizes[0]*2;

	blksize_size[MAJOR_NR] = hd_blocksizes;
	hardsect_size[MAJOR_NR] = hd_hardsectsizes;
	max_sectors[MAJOR_NR] = hd_maxsect;

	hd_gendisk.nr_real = 1;

  register_disk(&hd_gendisk, MKDEV(MAJOR_NR,0), 1<<6,&mmc_bdops, hd_sizes[0]*2);

	return 0;
}

static void mmc_exit(void)
{
	blk_size[MAJOR_NR] = NULL;
	blksize_size[MAJOR_NR] = NULL;
	hardsect_size[MAJOR_NR] = NULL;
	max_sectors[MAJOR_NR] = NULL;
	hd[0].nr_sects = 0;
}

static void mmc_check_media(void)
{
	int old_state;
	int rc;

	old_state = mmc_media_detect;

	// TODO: Add card detection here
	mmc_media_detect = 1;
	if (old_state != mmc_media_detect)
	{
		mmc_media_changed = 1;
		if (mmc_media_detect == 1)
		{
			rc = mmc_init();
			if (rc != 0) printk("mmc: error in mmc_init (%d)\n", rc);
		}
		else
		{
			mmc_exit();
		}
	}

	/* del_timer(&mmc_timer);
	mmc_timer.expires = jiffies + 10*HZ;
	add_timer(&mmc_timer); */
}

static int __init mmc_driver_init(void)
{
	int rc;

	rc = devfs_register_blkdev(MAJOR_NR, DEVICE_NAME, &mmc_bdops);
	if (rc < 0)
	{
		printk(KERN_WARNING "mmc: can't get major %d\n", MAJOR_NR);
		return rc;
	}

	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), mmc_request);

	read_ahead[MAJOR_NR] = 8;
	add_gendisk(&hd_gendisk);

	mmc_check_media();

	/*init_timer(&mmc_timer);
	mmc_timer.expires = jiffies + HZ;
	mmc_timer.function = (void *)mmc_check_media;
	add_timer(&mmc_timer);*/

	return 0;
}

static void __exit mmc_driver_exit(void)
{
	int i;
	del_timer(&mmc_timer);

	for (i = 0; i < (1 << 6); i++)
		fsync_dev(MKDEV(MAJOR_NR, i));

	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
	del_gendisk(&hd_gendisk);
	devfs_unregister_blkdev(MAJOR_NR, DEVICE_NAME);
	mmc_exit();
}

module_init(mmc_driver_init);
module_exit(mmc_driver_exit);

vSaAmTp
Einsteiger
Einsteiger
Beiträge: 232
Registriert: Sonntag 17. März 2002, 22:14

Beitrag von vSaAmTp »

wird aber langsam
TaGana
Interessierter
Interessierter
Beiträge: 96
Registriert: Samstag 6. Oktober 2001, 00:00

Beitrag von TaGana »

Noch zu erwähnen ... die I/O Leitungen wurden so gewählt das die SD/MMC karte parallel zuEdit: anderen Erweiterungen laufen kann.

Also com2 ist neben der SD karte weiterhin voll funktionsfähig, samt RTS/DTR/CTS und selbstverständlich TX/RX.


Theroretisch könnte man die SD karte noch im SD modus betreiben (4 bit datenbreite), die zwei zusätzlich benötigte I/O Leitungen sind auch noch da, das würde den durchsatz noch weiter beschleunigen und die CPU entlasten, wenn doch das protokoll verfügbar währe ... ist leider NDA.
zexma
Tuxboxer
Tuxboxer
Beiträge: 2067
Registriert: Mittwoch 6. März 2002, 15:29

Beitrag von zexma »

TaGana hat geschrieben:Noch zu erwähnen ... die I/O Leitungen wurden so gewählt das die SD/MMC karte parallel zuEdit: anderen Erweiterungen laufen kann.

Also com2 ist neben der SD karte weiterhin voll funktionsfähig, samt RTS/DTR/CTS und selbstverständlich TX/RX.


Theroretisch könnte man die SD karte noch im SD modus betreiben (4 bit datenbreite), die zwei zusätzlich benötigte I/O Leitungen sind auch noch da, das würde den durchsatz noch weiter beschleunigen und die CPU entlasten, wenn doch das protokoll verfügbar währe ... ist leider NDA.
cool, danke! 8)
---
Huch, TaGana höchstselbtpersönlich... :wink:
Gorcon
Tuxboxer
Tuxboxer
Beiträge: 5873
Registriert: Samstag 23. Februar 2002, 22:46

Beitrag von Gorcon »

Wie kann ich mir das dann vorstellen? Wird die Speicherkarte dann als zustzliches "Laufwerk" gemountet oder wird der freie Speicher dem des Flashs "hinzugefügt"?
Welche Speicher sind zu bevorzugen (vor und Nachteile).
Als Kartenadapter werde ich wohl einen USB Leser ausschlachten oder gibts entsprechende "Fassungen" auch einzeln?

Gruß Gorcon
TaGana
Interessierter
Interessierter
Beiträge: 96
Registriert: Samstag 6. Oktober 2001, 00:00

Beitrag von TaGana »

> Wird die Speicherkarte dann als zustzliches "Laufwerk" gemountet

ja,

Nur der kernel müsste mal recompiliert werden mit den richtigen Einstellungen um das neue "Laufwerk" zu unterstützen.



> oder gibts entsprechende "Fassungen" auch einzeln?

Bei Farnell für 1-2 Euro.

http://de.farnell.com/jsp/endecaSearch/ ... 186182&N=0
Zuletzt geändert von TaGana am Freitag 3. März 2006, 00:10, insgesamt 1-mal geändert.
zexma
Tuxboxer
Tuxboxer
Beiträge: 2067
Registriert: Mittwoch 6. März 2002, 15:29

Beitrag von zexma »

Gorcon hat geschrieben:Welche Speicher sind zu bevorzugen (vor und Nachteile).
Als Kartenadapter werde ich wohl einen USB Leser ausschlachten oder gibts entsprechende "Fassungen" auch einzeln?Gruß Gorcon
von reichelt so einen 8in1 usb-kartenleser schlachten (6,90€).
sonstige sd/mmc-cardfassungen sind imho quasi alle teurer.
Gorcon
Tuxboxer
Tuxboxer
Beiträge: 5873
Registriert: Samstag 23. Februar 2002, 22:46

Beitrag von Gorcon »

Danke euch beiden.
Farnell ist mir unterm Strich zu teuer. Um auf ein halbwegs vernünftiges Produkt/Versandkostenverhältniss zu kommen sollte man wenigstens für 20€ etwas bestellen. Die MMC Karten dort sind aber mehr als doppelt so teuer wie bei Rechelt.

Gruß Gorcon
just_me
Einsteiger
Einsteiger
Beiträge: 123
Registriert: Montag 28. November 2005, 11:31

Beitrag von just_me »

Gorcon hat geschrieben:Als Kartenadapter werde ich wohl einen USB Leser ausschlachten oder gibts entsprechende "Fassungen" auch einzeln?
Es geht auch anders: Du bekommst teilweise die etwa halb so grossen miniSD Cards zusammen mit einem Adapter auf SD Card für einen geringen oder keinen Aufpreis.

Den Adapter kannst Du dann fest einlöten und die miniSD dort bei Bedarf ein-/ausstecken:)

http://images-eu.amazon.com/images/P/B0 ... ZZZZZZ.jpg