> + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +#include <common.h> > +#include <command.h> > + > +#if defined (CONFIG_CMD_MG_DISK) > + > +#include <mg_disk.h> > + > +int do_mg_disk_cmd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) > +{ > + u32 from, to, size; > + > + switch (argc) { > + case 2: > + if (!strcmp(argv[1], "init")) > + mg_disk_init(); > + else > + return 1; > + break; > + case 4: > + from = simple_strtoul(argv[2], NULL, 0); > + to = simple_strtoul(argv[3], NULL, 0); > + size = simple_strtoul(argv[4], NULL, 0); > + > + if (!strcmp(argv[1], "read")) > + mg_disk_read(from, (u8 *)to, size); > + else if (!strcmp(argv[1], "write")) > + mg_disk_write(to, (u8 *)from, size); > + else if (!strcmp(argv[1], "readsec")) > + mg_disk_read_sects((void *)to, from, size); > + else if (!strcmp(argv[1], "writesec")) > + mg_disk_write_sects((void *)from, to, size); > + else > + return 1; > + break; > + default: > + printf("Usage:\n%s\n", cmdtp->usage); > + return 1; > + } > + return 0; > +} > + > +U_BOOT_CMD( > + mgd, 5, 0, do_mg_disk_cmd, > + "mgd - mgine m[g]flash command\n", > + ": mgine mflash IO mode (disk) command\n" > + " - initialize : mgd init\n" > + " - random read : mgd read [from] [to] [size]\n" > + " - random write : mgd write [from] [to] [size]\n" > + " - sector read : mgd readsec [sector] [to] [counts]\n" > + " - sector write : mgd writesec [from] [sector] [counts]\n" > +); > + > +#endif > diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c > index 1fcb4c9..649b23d 100644 > --- a/common/cmd_nvedit.c > +++ b/common/cmd_nvedit.c > @@ -52,15 +52,17 @@ > > DECLARE_GLOBAL_DATA_PTR; > > -#if !defined(CONFIG_ENV_IS_IN_NVRAM) && \ > - !defined(CONFIG_ENV_IS_IN_EEPROM) && \ > +#if !defined(CONFIG_ENV_IS_IN_EEPROM) && \ > !defined(CONFIG_ENV_IS_IN_FLASH) && \ > !defined(CONFIG_ENV_IS_IN_DATAFLASH) && \ > + !defined(CONFIG_ENV_IS_IN_MG_DISK) && \ > !defined(CONFIG_ENV_IS_IN_NAND) && \ > + !defined(CONFIG_ENV_IS_IN_NVRAM) && \ > !defined(CONFIG_ENV_IS_IN_ONENAND) && \ > !defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \ > !defined(CONFIG_ENV_IS_NOWHERE) > -# error Define one of > CONFIG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|SPI_FLASH|NOWHERE} > +# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|ONENAND|\ > +SPI_FLASH|MG_DISK|NVRAM|NOWHERE} > #endif > > #define XMK_STR(x) #x > +env_t *env_ptr = 0; > + > +DECLARE_GLOBAL_DATA_PTR; > + > +uchar env_get_char_spec(int index) > +{ > + return (*((uchar *) (gd->env_addr + index))); > +} > + > +void env_relocate_spec(void) > +{ > + unsigned int err; > + > + err = mg_disk_init(); > + if (err) { > + puts ("*** Warning - mg_disk_init error"); > + goto OUT; > + } > + err = mg_disk_read(CONFIG_ENV_ADDR, (u_char *)env_ptr, CONFIG_ENV_SIZE); > + if (err) { > + puts ("*** Warning - mg_disk_read error"); > + goto OUT; > + } > + > + if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) { > + puts ("*** Warning - CRC error"); > + goto OUT; > + } > + > + return; > + > +OUT: > + printf (", using default environment\n\n"); > + set_default_env(); > +} > + > +int saveenv(void) > +{ > + unsigned int err; add an empty line > + env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); > + err = mg_disk_write(CONFIG_ENV_ADDR, (u_char *)env_ptr, > + CONFIG_ENV_SIZE); > + if (err) > + puts ("*** Warning - mg_disk_write error\n\n"); please add an empty line to be concistant with the function > + return err; > +} > + > +int env_init(void) > +{ > + /* use default */ > + gd->env_addr = (ulong) & default_environment[0]; > + gd->env_valid = 1; > + > + return 0; > +} > diff --git a/disk/part.c b/disk/part.c > index e353cee..fe299c7 100644 > --- a/disk/part.c > +++ b/disk/part.c > @@ -35,6 +35,7 @@ > #endif > > #if (defined(CONFIG_CMD_IDE) || \ > + defined(CONFIG_CMD_MG_DISK) || \ > defined(CONFIG_CMD_SATA) || \ > defined(CONFIG_CMD_SCSI) || \ > defined(CONFIG_CMD_USB) || \ > @@ -65,6 +66,9 @@ static const struct block_drvr block_drvr[] = { > #if defined(CONFIG_SYSTEMACE) > { .name = "ace", .get_dev = systemace_get_dev, }, > #endif > +#if defined(CONFIG_CMD_MG_DISK) > + { .name = "mgd", .get_dev = mg_disk_get_dev, }, > +#endif > { }, > }; > > @@ -91,6 +95,7 @@ block_dev_desc_t *get_dev(char* ifname, int dev) > #endif > > #if (defined(CONFIG_CMD_IDE) || \ > + defined(CONFIG_CMD_MG_DISK) || \ > defined(CONFIG_CMD_SATA) || \ > defined(CONFIG_CMD_SCSI) || \ > defined(CONFIG_CMD_USB) || \ > @@ -203,11 +208,12 @@ void dev_print (block_dev_desc_t *dev_desc) > #endif > > #if (defined(CONFIG_CMD_IDE) || \ > + defined(CONFIG_CMD_MG_DISK) || \ > defined(CONFIG_CMD_SATA) || \ > defined(CONFIG_CMD_SCSI) || \ > defined(CONFIG_CMD_USB) || \ > defined(CONFIG_MMC) || \ > - defined(CONFIG_SYSTEMACE) ) > + defined(CONFIG_SYSTEMACE) ) > > #if defined(CONFIG_MAC_PARTITION) || \ > defined(CONFIG_DOS_PARTITION) || \ > diff --git a/disk/part_amiga.c b/disk/part_amiga.c > index 6c3d748..6f25173 100644 > --- a/disk/part_amiga.c > +++ b/disk/part_amiga.c > @@ -27,6 +27,7 @@ > #include "part_amiga.h" > > #if (defined(CONFIG_CMD_IDE) || \ > + defined(CONFIG_CMD_MG_DISK) || \ > defined(CONFIG_CMD_SCSI) || \ > defined(CONFIG_CMD_USB) || \ > defined(CONFIG_MMC) || \ > @@ -154,7 +155,7 @@ struct rigid_disk_block *get_rdisk(block_dev_desc_t > *dev_desc) > > s = getenv("amiga_scanlimit"); > if (s) > - limit = atoi(s); > + limit = simple_strtoul(s, NULL, 10); > else > limit = AMIGA_BLOCK_LIMIT; > > @@ -195,7 +196,7 @@ struct bootcode_block *get_bootcode(block_dev_desc_t > *dev_desc) > > s = getenv("amiga_scanlimit"); > if (s) > - limit = atoi(s); > + limit = simple_strtoul(s, NULL, 10); > else > limit = AMIGA_BLOCK_LIMIT; > > diff --git a/disk/part_dos.c b/disk/part_dos.c > index 4d778ec..845cdb6 100644 > --- a/disk/part_dos.c > +++ b/disk/part_dos.c > @@ -36,6 +36,7 @@ > #include "part_dos.h" > > #if (defined(CONFIG_CMD_IDE) || \ > + defined(CONFIG_CMD_MG_DISK) || \ > defined(CONFIG_CMD_SATA) || \ > defined(CONFIG_CMD_SCSI) || \ > defined(CONFIG_CMD_USB) || \ > diff --git a/disk/part_efi.c b/disk/part_efi.c > index d8a8111..4cf79fb 100644 > --- a/disk/part_efi.c > +++ b/disk/part_efi.c > @@ -37,6 +37,7 @@ > #include "part_efi.h" > > #if (defined(CONFIG_CMD_IDE) || \ > + defined(CONFIG_CMD_MG_DISK) || \ > defined(CONFIG_CMD_SATA) || \ > defined(CONFIG_CMD_SCSI) || \ > defined(CONFIG_CMD_USB) || \ > diff --git a/disk/part_iso.c b/disk/part_iso.c > index 72ff868..8348ce8 100644 > --- a/disk/part_iso.c > +++ b/disk/part_iso.c > @@ -26,6 +26,7 @@ > #include "part_iso.h" > > #if (defined(CONFIG_CMD_IDE) || \ > + defined(CONFIG_CMD_MG_DISK) || \ > defined(CONFIG_CMD_SCSI) || \ > defined(CONFIG_CMD_SATA) || \ > defined(CONFIG_CMD_USB) || \ > diff --git a/disk/part_mac.c b/disk/part_mac.c > index 1922fe5..fce4cc7 100644 > --- a/disk/part_mac.c > +++ b/disk/part_mac.c > @@ -35,6 +35,7 @@ > #include "part_mac.h" > > #if (defined(CONFIG_CMD_IDE) || \ > + defined(CONFIG_CMD_MG_DISK) || \ > defined(CONFIG_CMD_SCSI) || \ > defined(CONFIG_CMD_SATA) || \ > defined(CONFIG_CMD_USB) || \ > diff --git a/doc/README.mflash b/doc/README.mflash > new file mode 100644 > index 0000000..fb74b90 > --- /dev/null > +++ b/doc/README.mflash > @@ -0,0 +1,93 @@ > + > +This document describes m[g]flash support in u-boot. > + > +Contents > + 1. Overview > + 2. Porting mflash driver > + 3. Mflash command > + 4. Misc. > + > +1. Overview > +Mflash and gflash are embedded flash drive. The only difference is mflash is > +MCP(Multi Chip Package) device. These two device operate exactly same way. > +So the rest mflash repersents mflash and gflash altogether. > + > +2. Porting mflash driver > + > +2-1. Board configuration > +* Mflash driver support > +#define CONFIG_CMD_MG_DISK > + > +* Environment variable support (optional) > +#define CONFIG_ENV_IS_IN_MG_DISK > +Also CONFIG_ENV_ADDR and CONFIG_ENV_SIZE should be defined. > +CONFIG_ENV_ADDR is byte offset starting from 0. > + > +Following example sets environment variable location to 0x80000 (1024'th > +sector) and size of 0x400 (1024 byte) > +#define CONFIG_ENV_ADDR 0x80000 > +#define CONFIG_ENV_SIZE 0x400 > + > +* Reserved size config (optional) > +If you want to use some reserved area for bootloader, environment variable or > +whatever, use CONFIG_MG_DISK_RES. The value should be multiple of > +MG_SECTOR_SIZE (512Byte). Mflash's block operation method use this value as > +start offset. So any u-boot's partition table parser and file system command > +work consistently. You can access this area by using mflash command. > + > +Following example sets 10MB of reserved area. > +#define CONFIG_MG_DISK_RES 10485760 > + > +2-2. Porting mg_get_drv_data function > +Mflash is active device and need some gpio control for proper operation. > +This board dependency resolved by using mg_get_drv_data function. > +Port this function at your board init file. See include/mg_disk.h > + > +Here is some pseudo example. > + > +static void custom_hdrst_pin (u8 level) > +{ > + if (level) > + /* set hard reset pin to high */ > + else > + /* set hard reset pin to low */ > +} > + > +static void custom_ctrl_pin_init (void) > +{ > + /* Set hard reset, write protect, deep power down pins > + * to gpio. > + * Set these pins to output high > + */ > +} > + > +struct mg_drv_data* mg_get_drv_data (void) > +{ > + static struct mg_drv_data prv; > + > + prv.base = /* base address of mflash */ > + prv.mg_ctrl_pin_init = custom_ctrl_pin_init; > + prv.mg_hdrst_pin = custom_hdrst_pin; > + > + return &prv; > +} > + > +3. Mflash command > + > +* initialize : mgd init > +* random read : mgd read [from] [to] [size] > + ex) read 256 bytes from 0x300000 of mflash to 0xA0100000 of host memory > + mgd read 0x300000 0xA0100000 256 > +* random write : mgd write [from] [to] [size] > +* sector read : mgd readsec [sector] [to] [count] > + ex) read 10 sectors starts from 400 sector to 0xA0100000 > + mgd readsec 400 0xA0100000 10 > +* sector write : mgd writesec [from] [sector] [count] > + > +4. Misc. > +Mflash's device interface name for block driver is "mgd". > +Here is ext2 file system access example. > + > + mgd init > + ext2ls mgd 0:1 /boot > + ext2load mgd 0:1 0xa0010000 /boot/uImage 1954156 > diff --git a/drivers/block/Makefile b/drivers/block/Makefile > index 59388d9..eccefc1 100644 > --- a/drivers/block/Makefile > +++ b/drivers/block/Makefile > @@ -25,13 +25,14 @@ include $(TOPDIR)/config.mk > > LIB := $(obj)libblock.a > > -COBJS-$(CONFIG_SCSI_AHCI) += ahci.o why? > COBJS-$(CONFIG_ATA_PIIX) += ata_piix.o > +COBJS-$(CONFIG_CMD_MG_DISK) += mg_disk.o > COBJS-$(CONFIG_FSL_SATA) += fsl_sata.o > +COBJS-$(CONFIG_IDE_SIL680) += sil680.o > COBJS-$(CONFIG_LIBATA) += libata.o > COBJS-$(CONFIG_PATA_BFIN) += pata_bfin.o > COBJS-$(CONFIG_SATA_SIL3114) += sata_sil3114.o > -COBJS-$(CONFIG_IDE_SIL680) += sil680.o > +COBJS-$(CONFIG_SCSI_AHCI) += ahci.o > COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o > COBJS-$(CONFIG_SYSTEMACE) += systemace.o > > diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c > new file mode 100644 > index 0000000..4454fca > --- /dev/null > +++ b/drivers/block/mg_disk.c > @@ -0,0 +1,629 @@ > +/* > + * (C) Copyright 2009 mGine co. > + * unsik Kim <donar...@gmail.com> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program 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. > + * > + * This program 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 this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +#include <common.h> > +#include <malloc.h> > +#include <part.h> > +#include <ata.h> > +#include <asm/io.h> > +#include "mg_disk_prv.h" > + > +#ifdef CONFIG_CMD_MG_DISK no need please remove > + > +#ifndef CONFIG_MG_DISK_RES > +#define CONFIG_MG_DISK_RES 0 > +#endif > + > +#if (CONFIG_MG_DISK_RES % MG_SECTOR_SIZE != 0) > +#error "CONFIG_MG_DISK_RES should be MG_SECTOR_SIZE algined" > +#endif > + > +#define MG_DISK_RES ((CONFIG_MG_DISK_RES) / MG_SECTOR_SIZE) > + > +#define MG_BASE (host.drv_data->base) an inline function will be better > + > +static struct mg_host host; > + > +static block_dev_desc_t mg_disk_dev = { > + .if_type = IF_TYPE_ATAPI, > + .part_type = PART_TYPE_UNKNOWN, > + .type = DEV_TYPE_HARDDISK, > + .blksz = MG_SECTOR_SIZE, > + .priv = &host }; > + > +static void mg_dump_status (const char *msg, unsigned int stat, unsigned err) > +{ > + char *name = MG_DEV_NAME; > + > + printf("%s: %s: status=0x%02x { ", name, msg, stat & 0xff); > + if (stat & MG_REG_STATUS_BIT_BUSY) > + printf("Busy "); > + if (stat & MG_REG_STATUS_BIT_READY) > + printf("DriveReady "); > + if (stat & MG_REG_STATUS_BIT_WRITE_FAULT) > + printf("WriteFault "); > + if (stat & MG_REG_STATUS_BIT_SEEK_DONE) > + printf("SeekComplete "); > + if (stat & MG_REG_STATUS_BIT_DATA_REQ) > + printf("DataRequest "); > + if (stat & MG_REG_STATUS_BIT_CORRECTED_ERROR) > + printf("CorrectedError "); > + if (stat & MG_REG_STATUS_BIT_ERROR) > + printf("Error "); > + printf("}\n"); > + > + if ((stat & MG_REG_STATUS_BIT_ERROR)) { > + printf("%s: %s: error=0x%02x { ", name, msg, err & 0xff); > + if (err & MG_REG_ERR_BBK) > + printf("BadSector "); > + if (err & MG_REG_ERR_UNC) > + printf("UncorrectableError "); > + if (err & MG_REG_ERR_IDNF) > + printf("SectorIdNotFound "); > + if (err & MG_REG_ERR_ABRT) > + printf("DriveStatusError "); > + if (err & MG_REG_ERR_AMNF) > + printf("AddrMarkNotFound "); > + printf("}\n"); > + } > +} > + > +#if CONFIG_SYS_HZ == 1000 not supposed to append anymore CONFIG_SYS_HZ supposed to be always 1000 if not thi smust be fix > +#define msecs_to_hz(s) (s) > +#else > +static unsigned int msecs_to_hz (u32 msec) > +{ > + u32 hz = CONFIG_SYS_HZ / 1000 * msec; > + > + if (!hz) > + hz = 1; > + > + return hz; > +} > +#endif > + > +/* > + * copy src to dest, skipping leading and trailing blanks and null > + * terminate the string > + * "len" is the size of available memory including the terminating '\0' > + */ > +static void mg_ident_cpy (unsigned char *dst, unsigned char *src, > + unsigned int len) > +{ > + unsigned char *end, *last; > + > + last = dst; > + end = src + len - 1; > + > + /* reserve space for '\0' */ > + if (len < 2) > + goto OUT; > + > + /* skip leading white space */ > + while ((*src) && (src<end) && (*src==' ')) please add a space before and after '<' '==' & co > + ++src; > + > + /* copy string, omitting trailing white space */ > + while ((*src) && (src<end)) { > + *dst++ = *src; > + if (*src++ != ' ') > + last = dst; > + } > +OUT: > + *last = '\0'; > +} why do you need this? > + > +static unsigned int mg_wait (u32 expect, u32 msec) > +{ > + u8 status; > + u32 from, cur, expire, err; > + > + err = MG_ERR_NONE; > + reset_timer(); > + from = get_timer(0); > + expire = msecs_to_hz(msec); > + > + status = readb(MG_BASE + MG_REG_STATUS); > + do { > + cur = get_timer(from); > + if (status & MG_REG_STATUS_BIT_BUSY) { > + if (expect == MG_REG_STATUS_BIT_BUSY) > + break; > + } else { > + /* Check the error condition! */ > + if (status & MG_REG_STATUS_BIT_ERROR) { > + err = readb(MG_BASE + MG_REG_ERROR); > + mg_dump_status("mg_wait", status, err); > + break; > + } > + > + if (expect == MG_STAT_READY) > + if (MG_READY_OK(status)) > + break; > + > + if (expect == MG_REG_STATUS_BIT_DATA_REQ) > + if (status & MG_REG_STATUS_BIT_DATA_REQ) > + break; > + } > + status = readb(MG_BASE + MG_REG_STATUS); > + } while (cur < expire); > + > + if (cur >= expire) > + err = MG_ERR_TIMEOUT; > + > + return err; > +} > + > +static int mg_get_disk_id (void) > +{ > + u32 iobuf[(MG_SECTOR_SIZE / sizeof(u32))]; > + hd_driveid_t *iop = (hd_driveid_t *)iobuf; > + u32 i, err; > + u16 *buff = (u16 *)iobuf; > + > + writeb(MG_CMD_ID, MG_BASE + MG_REG_COMMAND); > + err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000); > + if (err) > + return err; > + > + for(i = 0; i < (MG_SECTOR_SIZE / sizeof(u32)) >> 1; i++) > + buff[i] = readw(MG_BASE + MG_BUFF_OFFSET + i * 2); > + > + writeb(MG_CMD_RD_CONF, MG_BASE + MG_REG_COMMAND); > + err = mg_wait(MG_STAT_READY, 3000); > + if (err) > + return err; > + > + if((iop->field_valid & 1) == 0) > + return MG_ERR_TRANSLATION; > + > + mg_ident_cpy((unsigned char*)mg_disk_dev.revision, iop->fw_rev, > + sizeof(mg_disk_dev.revision)); > + mg_ident_cpy((unsigned char*)mg_disk_dev.vendor, iop->model, > + sizeof(mg_disk_dev.vendor)); > + mg_ident_cpy((unsigned char*)mg_disk_dev.product, iop->serial_no, > + sizeof(mg_disk_dev.product)); > +#ifdef __LITTLE_ENDIAN > + /* > + * firmware revision, model, and serial number have Big Endian Byte > + * order in Word. Convert all three to little endian. > + * > + * See CF+ and CompactFlash Specification Revision 2.0: > + * 6.2.1.6: Identify Drive, Table 39 for more details > + */ > + > + strswab(mg_disk_dev.revision); > + strswab(mg_disk_dev.vendor); > + strswab(mg_disk_dev.product); > +#endif /* __LITTLE_ENDIAN */ > + > +#ifdef __BIG_ENDIAN maybe use only one ifdef __LITTLE_ENDIAN? > + mg_disk_dev.lba = (iop->lba_capacity << 16) | (iop->lba_capacity >> 16); > +#else /* ! __BIG_ENDIAN */ > + mg_disk_dev.lba = iop->lba_capacity; > +#endif /* __BIG_ENDIAN */ > + > + return MG_ERR_NONE; > +} > + > +static int mg_disk_reset (void) > +{ > + struct mg_drv_data *prv_data = host.drv_data; > + s32 err; > + u8 init_status; > + > + /* hdd rst low */ > + prv_data->mg_hdrst_pin(0); > + err = mg_wait(MG_REG_STATUS_BIT_BUSY, 300); > + if(err) > + return err; > + > + /* hdd rst high */ > + prv_data->mg_hdrst_pin(1); > + err = mg_wait(MG_STAT_READY, 3000); > + if(err) > + return err; > + > + /* soft reset on */ > + writeb(MG_REG_CTRL_RESET | MG_REG_CTRL_INTR_DISABLE, > + MG_BASE + MG_REG_DRV_CTRL); > + err = mg_wait(MG_REG_STATUS_BIT_BUSY, 3000); > + if(err) > + return err; > + > + /* soft reset off */ > + writeb(MG_REG_CTRL_INTR_DISABLE, MG_BASE + MG_REG_DRV_CTRL); > + err = mg_wait(MG_STAT_READY, 3000); > + if(err) > + return err; > + > + init_status = readb(MG_BASE + MG_REG_STATUS) & 0xf; > + > + if (init_status == 0xf) > + return MG_ERR_INIT_STAT; > + > + return err; > +} > + > + > +static unsigned int mg_out(unsigned int sect_num, > + unsigned int sect_cnt, > + unsigned int cmd) > +{ > + u32 err = MG_ERR_NONE; > + > + if ((err = mg_wait(MG_STAT_READY, 3000))) { > + return err; > + } maybe you could use the same coding style in the same file? > + > + writeb((u8)sect_cnt, MG_BASE + MG_REG_SECT_CNT); > + writeb((u8)sect_num, MG_BASE + MG_REG_SECT_NUM); > + writeb((u8)(sect_num >> 8), MG_BASE + MG_REG_CYL_LOW); > + writeb((u8)(sect_num >> 16), MG_BASE + MG_REG_CYL_HIGH); > + writeb((u8)((sect_num >> 24) | MG_REG_HEAD_LBA_MODE), > + MG_BASE + MG_REG_DRV_HEAD); > + writeb(cmd, MG_BASE + MG_REG_COMMAND); please add an empty line > + return err; > +} > + > +static unsigned int mg_do_read_sects(void *buff, u32 sect_num, u32 sect_cnt) > +{ > + u32 i, j, err; > + u8 *buff_ptr = buff; > + > + err = mg_out(sect_num, sect_cnt, MG_CMD_RD); > + if (err) > + return err; > + > + for (i = 0; i < sect_cnt; i++) { > + err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000); > + if (err) > + return err; > + > + /* TODO : u16 unaligned case */ > + for(j = 0; j < MG_SECTOR_SIZE >> 1; j++) { > + *(u16 *)buff_ptr = > + readw(MG_BASE + MG_BUFF_OFFSET + (j << 1)); ?? > + buff_ptr += 2; > + } > + > + writeb(MG_CMD_RD_CONF, MG_BASE + MG_REG_COMMAND); > + > + MG_DBG("%u (0x%8.8x) sector read", sect_num + i, > + (sect_num + i) * MG_SECTOR_SIZE); > + } > + > + return err; > +} > + > +unsigned int mg_disk_read_sects(void *buff, u32 sect_num, u32 sect_cnt) > +{ > + u32 quotient, residue, i, err; > + u8 *buff_ptr = buff; > + > + quotient = sect_cnt >> 8; > + residue = sect_cnt % 256; > + > + for (i = 0; i < quotient; i++) { > + MG_DBG("sect num : %u buff : 0x%8.8x", sect_num, (u32)buff_ptr); > + err = mg_do_read_sects(buff_ptr, sect_num, 256); > + if (err) > + return err; > + sect_num += 256; > + buff_ptr += 256 * MG_SECTOR_SIZE; > + } > + > + if (residue) { > + MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr); please use debug(x) > + err = mg_do_read_sects(buff_ptr, sect_num, residue); > + } > + > + return err; > +} > + > +unsigned long mg_block_read (int dev, unsigned long start, > + lbaint_t blkcnt, void *buffer) > +{ > + start += MG_DISK_RES; > + if (! mg_disk_read_sects(buffer, start, blkcnt)) > + return blkcnt; > + else > + return 0; > +} > + > +unsigned int mg_disk_read (u32 addr, u8 *buff, u32 len) > +{ > + u8 *sect_buff, *buff_ptr = buff; > + u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num; > + u32 err = MG_ERR_NONE; > + > + /* TODO : sanity chk */ > + cnt = 0; > + cur_addr = addr; > + end_addr = addr + len; > + > + sect_buff = malloc(MG_SECTOR_SIZE); > + > + if (cur_addr & MG_SECTOR_SIZE_MASK) { > + next_sec_addr = (cur_addr + MG_SECTOR_SIZE) & > + ~MG_SECTOR_SIZE_MASK; > + sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT; > + err = mg_disk_read_sects(sect_buff, sect_num, 1); > + if (err) > + goto mg_read_exit; > + > + if (end_addr < next_sec_addr) { > + memcpy(buff_ptr, > + sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK), > + end_addr - cur_addr); > + MG_DBG("copies %u byte from sector offset 0x%8.8x", > + end_addr - cur_addr, cur_addr); > + cur_addr = end_addr; > + } else { > + memcpy(buff_ptr, > + sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK), > + next_sec_addr - cur_addr); > + MG_DBG("copies %u byte from sector offset 0x%8.8x", > + next_sec_addr - cur_addr, cur_addr); > + buff_ptr += (next_sec_addr - cur_addr); > + cur_addr = next_sec_addr; > + } > + } > + > + if (cur_addr < end_addr) { > + sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT; > + next_sec_addr = cur_addr + MG_SECTOR_SIZE; > + > + while (next_sec_addr <= end_addr) { > + cnt++; > + next_sec_addr += MG_SECTOR_SIZE; > + } is there any better way to calculate it? > + > + if (cnt) > + err = mg_disk_read_sects(buff_ptr, sect_num, cnt); > + if (err) > + goto mg_read_exit; > + > + buff_ptr += cnt * MG_SECTOR_SIZE; > + cur_addr += cnt * MG_SECTOR_SIZE; > + > + if (cur_addr < end_addr) { > + sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT; > + err = mg_disk_read_sects(sect_buff, sect_num, 1); > + if (err) > + goto mg_read_exit; > + memcpy(buff_ptr, sect_buff, end_addr - cur_addr); > + MG_DBG("copies %u byte", end_addr - cur_addr); > + } > + } > + > +mg_read_exit: > + free(sect_buff); > + > + return err; > +} > + > +static int mg_do_write_sects(void *buff, u32 sect_num, u32 sect_cnt) > +{ > + u32 i, j, err; > + u8 *buff_ptr = buff; > + > + err = mg_out(sect_num, sect_cnt, MG_CMD_WR); > + if (err) > + return err; > + > + for (i = 0; i < sect_cnt; i++) { > + err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000); > + if (err) > + return err; > + > + /* TODO : u16 unaligned case */ > + for(j = 0; j < MG_SECTOR_SIZE >> 1; j++) { > + writew(*(u16 *)buff_ptr, > + MG_BASE + MG_BUFF_OFFSET + (j << 1)); ?? > + buff_ptr += 2; > + } > + > + writeb(MG_CMD_WR_CONF, MG_BASE + MG_REG_COMMAND); > + > + MG_DBG("%u (0x%8.8x) sector write", > + sect_num + i, (sect_num + i) * MG_SECTOR_SIZE); > + } > + > + return err; > +} > + > +unsigned int mg_disk_write_sects(void *buff, u32 sect_num, u32 sect_cnt) > +{ > + u32 quotient, residue, i; > + u32 err = MG_ERR_NONE; > + u8 *buff_ptr = buff; > + > + quotient = sect_cnt >> 8; > + residue = sect_cnt % 256; > + > + for (i = 0; i < quotient; i++) { > + MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr); > + err = mg_do_write_sects(buff_ptr, sect_num, 256); > + if (err) > + return err; > + sect_num += 256; > + buff_ptr += 256 * MG_SECTOR_SIZE; > + } > + > + if (residue) { > + MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr); > + err = mg_do_write_sects(buff_ptr, sect_num, residue); > + } > + > + return err; > +} > + > +unsigned long mg_block_write (int dev, unsigned long start, > + lbaint_t blkcnt, const void *buffer) > +{ > + start += MG_DISK_RES; > + if (!mg_disk_write_sects((void *)buffer, start, blkcnt)) > + return blkcnt; > + else > + return 0; > +} > + > +unsigned int mg_disk_write(u32 addr, u8 *buff, u32 len) > +{ > + u8 *sect_buff, *buff_ptr = buff; > + u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num; > + u32 err = MG_ERR_NONE; > + > + /* TODO : sanity chk */ > + cnt = 0; > + cur_addr = addr; > + end_addr = addr + len; > + > + sect_buff = malloc(MG_SECTOR_SIZE); > + > + if (cur_addr & MG_SECTOR_SIZE_MASK) { > + > + next_sec_addr = (cur_addr + MG_SECTOR_SIZE) & > + ~MG_SECTOR_SIZE_MASK; > + sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT; > + err = mg_disk_read_sects(sect_buff, sect_num, 1); > + if (err) > + goto mg_write_exit; > + > + if (end_addr < next_sec_addr) { > + memcpy(sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK), > + buff_ptr, end_addr - cur_addr); > + MG_DBG("copies %u byte to sector offset 0x%8.8x", > + end_addr - cur_addr, cur_addr); > + cur_addr = end_addr; > + } else { > + memcpy(sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK), > + buff_ptr, next_sec_addr - cur_addr); > + MG_DBG("copies %u byte to sector offset 0x%8.8x", > + next_sec_addr - cur_addr, cur_addr); > + buff_ptr += (next_sec_addr - cur_addr); > + cur_addr = next_sec_addr; > + } > + > + err = mg_disk_write_sects(sect_buff, sect_num, 1); > + if (err) > + goto mg_write_exit; > + } > + > + if (cur_addr < end_addr) { > + > + sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT; > + next_sec_addr = cur_addr + MG_SECTOR_SIZE; > + > + while (next_sec_addr <= end_addr) { > + cnt++; > + next_sec_addr += MG_SECTOR_SIZE; > + } plase do not duplicate it create common code and as precedently is there any better way to calculate it? > + > + if (cnt) > + err = mg_disk_write_sects(buff_ptr, sect_num, cnt); > + if (err) > + goto mg_write_exit; > + > + buff_ptr += cnt * MG_SECTOR_SIZE; > + cur_addr += cnt * MG_SECTOR_SIZE; > + > + if (cur_addr < end_addr) { > + sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT; > + err = mg_disk_read_sects(sect_buff, sect_num, 1); > + if (err) > + goto mg_write_exit; > + memcpy(sect_buff, buff_ptr, end_addr - cur_addr); > + MG_DBG("copies %u byte", end_addr - cur_addr); > + err = mg_disk_write_sects(sect_buff, sect_num, 1); > + } > + > + } > + > +mg_write_exit: > + free(sect_buff); > + > + return err; > +} > + > +block_dev_desc_t *mg_disk_get_dev(int dev) > +{ > + return ((block_dev_desc_t *) & mg_disk_dev); > +} > + > +/* must override this function */ > +struct mg_drv_data * __attribute__((weak)) mg_get_drv_data (void) > +{ > + puts ("### WARNING ### port mg_get_drv_data function\n"); > + return NULL; > +} please do an compile error not a run time error > + > +unsigned int mg_disk_init (void) > +{ > + struct mg_drv_data *prv_data; > + u32 err = MG_ERR_NONE; > + > + prv_data = mg_get_drv_data(); > + if (! prv_data) { > + printf("%s:%d fail (no driver_data)\n", __func__, __LINE__); > + err = MG_ERR_NO_DRV_DATA; > + return err; > + } > + > + ((struct mg_host *)mg_disk_dev.priv)->drv_data = prv_data; > + > + /* init ctrl pin */ > + if (prv_data->mg_ctrl_pin_init) > + prv_data->mg_ctrl_pin_init(); > + > + if (! prv_data->mg_hdrst_pin) { > + err = MG_ERR_CTRL_RST; > + return err;
Best Regards, J. _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot